使用 SDCC(Little Endian)编译器时,这个算术有什么问题?

发布于 2024-08-23 07:10:13 字数 752 浏览 4 评论 0原文

我对 C 编程非常陌生,正在为我的 MCU 开发固件应用程序。当我使用KEIL编译器(Big Endian)时,此方法工作正常,但当我切换到SDCC编译器(Little Endian)时,它无法正常工作。有人可以解释一下我做错了什么吗???

目标设备是基于8051架构的Silicon Labs C8051F320。

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 (十进制) )。如果我将调试器切换为以十六进制显示,则 t = 0x3d010300。就像 t 永远不会被分配一样......

I am very new at C programming and I am working on a firmware application for my MCU. This method was working fine when I was using the KEIL compiler (Big Endian) but when I switched to the SDCC compiler (Little Endian) it is not working properly. Can someone please explain what I am doing wrong???

The target device is a Silicon Labs C8051F320 which is based on the 8051 architecture.

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;
}

ADDED:
First, I now changed the MotorSteps and MotorSpeed to be unsigned ints.
In my debugger, for some reason, if I set a break point at the if-statement line, on the first entrance of this function MotorSteps = 00, so t should get assigned to 0 also but the debugger shows that t=0.031497 (decimal). If I switch the debugger to display in Hex, t = 0x3d010300. It's like t is never getting assigned...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

迟到的我 2024-08-30 07:10:13

如果 MotorSteps = 49 则

(50 - 49) / 50 = 0.02

下一步

(1 - 0.02) = 0.98

0.98 * 15 = 14.7

对该值进行平方会将 t 设置为

t = 14.7 * 14.7 = 216.09

最后,从 float 到 unsigned char 的隐式转换会溢出 MotorSpeed 变量:

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

100 + 216 = 316 的总和当然会溢出 unsigned char 并且您最终结果为 316-256 = 60。

无论编译器如何,这都可能是不需要的行为。

If MotorSteps = 49 then

(50 - 49) / 50 = 0.02

next

(1 - 0.02) = 0.98

and

0.98 * 15 = 14.7

Squaring this value would set t as

t = 14.7 * 14.7 = 216.09

Finally, the implicit conversion from the float back to the unsigned char overflows the MotorSpeed variable:

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

The sum of 100 + 216 = 316, of course, overflows an unsigned char and you end up with 316-256 = 60.

This is probably unwanted behavior regardless of the compiler.

书信已泛黄 2024-08-30 07:10:13

就像永远得不到
分配...

编译器没有理由在声明中将 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;
}

It's like t is never getting
assigned...

There is no reason for the compiler to assign a value of 0 to t in the declaration

float t = 0;

since it immediately gets assigned to MotorSteps on the next line. My guess is the optimizer is ignoring the assignment to zero in the declaration and the debugger is simply displaying the uninitialized value for the memory where t is located on the stack.

You might want to consider getting rid of the formula altogether and using a look up table for the ramp values. It looks like there are only 51 values so the table would be relatively small. The code to look up a value would be much quicker than using the floating point libraries on an 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;
}

At least you could test your integer rather than the float to avoid the floating point libraries unless you need them...

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;
}
┾廆蒐ゝ 2024-08-30 07:10:13

为什么从 BE 切换到 LE?目标设备的架构是什么?顺便问一下,它是什么?

无论如何,还是要提问。我很确定转换发生时就会出现问题。尝试使用计算器逐行跟踪代码,并尝试找出数字何时变得意外。

why did you switch from BE to LE? What is architecture of target device? And by the way what is it?

Anyway, to question. I am pretty sure that problem comes when conversion takes place. Try to trace your code line by line with calculator and try to find when the numbers become unexpected.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文