uint32类型数据加减乘除运算错

[复制链接]
443|19
手机看帖
扫描二维码
随时随地手机跟帖
houcs|  楼主 | 2020-10-20 20:17 | 显示全部楼层 |阅读模式
大家有没有碰到过pic16x单片机uint32类型数据加减乘除运算错

使用特权

评论回复
zyf部长| | 2020-10-20 20:20 | 显示全部楼层

什么意思?不是很明白你说的什么,能再解释一下这个现象吗

使用特权

评论回复
houcs|  楼主 | 2020-10-20 20:26 | 显示全部楼层
详细情况是uint32类型的数,加减乘除错误,不知道大家有没有碰到过.
我琢磨着是编译器问题
用得编译器是xc8,
类似下面的计算:
unsigned char dat1,dat2,dat3,dat4;
uint_32 data;
data=dat1*0x1000000
      +dat2*0x10000
      +dat3*0x100
      +dat4;
计算出来结果就是不正确的.

使用特权

评论回复
houcs|  楼主 | 2020-10-20 20:29 | 显示全部楼层

另外诸如涉及uint_32类型的数加减乘除往往就要出错.
大家有什么建议?

使用特权

评论回复
llia| | 2020-10-20 20:35 | 显示全部楼层

将dat1,dat2,dat3,dat4定义为uint_32吧

使用特权

评论回复
zhuww| | 2020-10-20 20:39 | 显示全部楼层
这种情况,我一般直接用联合体,直接取数了

使用特权

评论回复
wangpe| | 2020-10-20 20:42 | 显示全部楼层
这不是编译器的问题
强制转换u32就可以了

使用特权

评论回复
wenfen| | 2020-10-20 20:59 | 显示全部楼层
上面有人提到的用uint32 定义变量, 应该可以解决吧, 但我奇怪的是编译器会根据参与计算的数自动转换的吧, 楼主也可以试试在常数后面加U

使用特权

评论回复
houcs|  楼主 | 2020-10-20 21:02 | 显示全部楼层
嗯,我后来也是这个方法,...但是编译器处理u32的计算出问题也太不应该了,我跟踪过,基本是0xffff到0x010000这里的进位问题

使用特权

评论回复
renyaq| | 2020-10-20 21:05 | 显示全部楼层

试了下,没出现问题。楼主贴个简单的测试工程,我运行看看。

使用特权

评论回复
liuzaiy| | 2020-10-20 21:08 | 显示全部楼层
字长应该是16位的,计算结果超过16位的会截取,保留低16位。

使用特权

评论回复
ousj| | 2020-10-20 21:12 | 显示全部楼层
在表达式的右边,dat1,dat2,dat3,dat4加类型强制转换(uin_32)

使用特权

评论回复
houcs|  楼主 | 2020-10-20 21:18 | 显示全部楼层
    union
                                                                { unsigned char byte[4];
                                                                  unsigned long L32;//[trainID_LENGTH];
                                                          }value;
                            unsigned char buffer[5];
                            unsigned char number[11];//[5];
                            unsigned char temp;
                           //      value.L32=0x1131A3b0;
                                                        value.byte[3]=g_ucTempbuf[0];//.L32
                                                        value.byte[2]=g_ucTempbuf[1];//.L32
                                                        value.byte[1]=g_ucTempbuf[2];//.L32
                                                        value.byte[0]=g_ucTempbuf[3];//.L32
                            //一共10位数
                        //    if(value!=0x1131A3b0){value=999999;};        //debug
                            buffer[4]=value.L32/100000000;
                            buffer[3]=value.L32%100000000/1000000;
                            buffer[2]=value.L32%1000000  /10000;
                            buffer[1]=value.L32%10000    /100;
                            buffer[0]=value.L32%100;//   /10000;

就是这样一段代码,如果直接用常规写法就会在0x00010000这一位和0x00001000这一位出错
出错情况就是这上面为1的位是1或者是0的时候,算出来是不对的.
常规写法就是
unsigned long L32;
unsigned g_ucTempbuf[4];
unsigned char buf[5];
L32=g_ucTempbuf[0]*0x01000000
     +g_ucTempbuf[1]*0x010000
     +g_ucTempbuf[2]*0x0100
     +g_ucTempbuf[3];
   buffer[4]=value.L32/100000000;
   buffer[3]=value.L32%100000000/1000000;
   buffer[2]=value.L32%1000000  /10000;
   buffer[1]=value.L32%10000    /100;
   buffer[0]=value.L32%100;//   /10000;

问题应该在乘法进位上,,我跟踪断点到乘法完成时候看值就是不对了一个bit,(我标注//debug的地方就是断点处,也是判断异常的一个分支)

使用特权

评论回复
houcs|  楼主 | 2020-10-20 21:24 | 显示全部楼层
我也有怀疑我硬件堆栈快用满了,可能调用long型数的运算子函数导致堆栈方面传递值出错....

使用特权

评论回复
zhuww| | 2020-10-20 21:31 | 显示全部楼层
能用移位操作的不用计算。

使用特权

评论回复
tian111| | 2020-10-20 21:37 | 显示全部楼层
运算之前加强制转换指令

使用特权

评论回复
zhuhuis| | 2020-10-20 21:42 | 显示全部楼层
借用了楼主所说的常规写法,发现是先前讨论过的数据格式的问题

使用特权

评论回复
chuxh| | 2020-10-20 21:50 | 显示全部楼层
楼主将char型强制转换为long型再相乘就不会有问题了。

使用特权

评论回复
houcs|  楼主 | 2020-10-20 21:53 | 显示全部楼层
498765f8eebe8435b5.png

使用特权

评论回复
houcs|  楼主 | 2020-10-20 21:56 | 显示全部楼层
所以不强制转换你这里也验证会出问题是么

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

743

主题

8382

帖子

5

粉丝