Что не так с этой арифметикой при использовании компилятора SDCC (Little Endian)?

StackOverflow https://stackoverflow.com/questions/2374367

Вопрос

Я очень новый в программировании C, и я работаю над приложением прошивки для моего MCU. Этот метод работал нормально, когда я использовал компилятор KEIL (большой Endian), но когда я переключился на компилятор SDCC (маленький Endian), он не работает должным образом. Может кто-нибудь, пожалуйста, объясните, что я делаю не так ???

Целевое устройство представляет собой кремниевые лаборатории C8051F320, которые основаны на архитектуре 8051.

unsigned **int** MotorSteps  = 0;     //"Global" variables
unsigned **int** MotorSpeed  = 0;
bit RampUp()
{
    float t = 0;
    t = MotorSteps;
    if ( t < 51 )
    {
        t = (1-((50 - t)/50))*15;   
        t = (t * t);        
        MotorSpeed = 100 + t;           
        return 0;
    }
    else return 1;
}

Добавлено: Во-первых, я теперь изменил Motorsteps и MotorSpeed, чтобы быть без знакиВ моем отладчике по какой-то причине, если я установлю точку перерыва на линию оператора IF-оператора, на первом входе в эту функцию motorsteps = 00, поэтому t также следует назначать на 0, но отладчик показывает, что T = 0,031497 (десятичный ). Если я переключаю отладчик для отображения в Hex, t = 0x3d010300. Это как т это никогда не назначается ...

Это было полезно?

Решение

Если motorsteps = 49, то

(50 - 49) / 50 = 0.02

следующий

(1 - 0.02) = 0.98

а также

0.98 * 15 = 14.7

Скарящий это значение установлено так, как

t = 14.7 * 14.7 = 216.09

Наконец, неявное преобразование от поплавка обратно в беззнаковие, переполнено переменной MotorSpeed:

MotorSpeed = 100 + 216.09...// Implicitly converts the float t to an unsigned char of 216

Сумма 100 + 216 = 316, конечно, переполнена unsigned Char, и вы в конечном итоге с 316-256 = 60.

Это, вероятно, нежелательное поведение независимо от компилятора.

Другие советы

Это как т это никогда не назначается ...

Для компилятора нет причин назначать значение от 0 до T в декларации

float t = 0;

Так как он немедленно назначается для Motorsteps на следующей строке. Мое предположение - это оптимизатор игнорирует назначение до нуля в декларации, и отладчик просто отображает неинициализированное значение для памяти, где T находится в стеке.

Возможно, вы захотите подумать об этом избавиться от формулы и использовать таблицу поиска для значений рампы. Похоже, что есть только 51 значений, поэтому таблица будет относительно маленькой. Код, чтобы посмотреть значение, будет много быстрее, чем использовать библиотеки с плавающей точкой на 8051.

#define NUM_RAMP_STEPS 51
unsigned char MotorSteps = 0;     //"Global" variables
unsigned char MotorSpeed = 0;
const unsigned char RampTable[NUM_RAMP_STEPS] = {...appropriate values...};
bit RampUp()
{
    if ( MotorSteps < NUM_RAMP_STEPS )
    {
        MotorSpeed = RampTable[MotorSteps];           
        return 0;
    }
    else return 1;
}

По крайней мере, вы могли бы проверить вашу целое число, а не поплавок, чтобы избежать библиотек с плавающей точкой, если вам они не нужны ...

unsigned **int** MotorSteps  = 0;     //"Global" variables
unsigned **int** MotorSpeed  = 0;
bit RampUp()
{
    if ( MotorSteps < 51 )
    {
        float t = MotorSteps;
        t = (1-((50 - t)/50))*15;   
        t = (t * t);        
        MotorSpeed = 100 + t;           
        return 0;
    }
    else return 1;
}

Почему вы перешли с Le? Что такое архитектура целевого устройства? И кстати, что это?

Во всяком случае, к вопросу. Я уверен, что проблема приходит, когда преобразование происходит. Попробуйте проследить вашу строку кода по линии с помощью калькулятора и попробуйте найти, когда числа становятся неожиданными.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top