[PIC®/AVR®/dsPIC®产品] 大家有没有碰到过pic16x单片机uint32类型数据加减乘除运算错

[复制链接]
1382|14
 楼主| wooda 发表于 2019-6-29 17:58 | 显示全部楼层 |阅读模式
如题
详细情况是uint32类型的数,加减乘除错误,不知道大家有没有碰到过.
我琢磨着是编译器问题
用得编译器是xc8,
类似下面的计算:
unsigned char dat1,dat2,dat3,dat4;
uint_32 data;
data=dat1*0x1000000
      +dat2*0x10000
      +dat3*0x100
      +dat4;
计算出来结果就是不正确的.
另外诸如涉及uint_32类型的数加减乘除往往就要出错.
大家有什么建议?
lcczg 发表于 2019-7-1 10:12 | 显示全部楼层
将dat1,dat2,dat3,dat4定义为uint_32吧

评论

这个...写程序总归会碰到unsigned char 参与int32的计算的...不能这样啊 另外好像就算4个int32的运算好像也有问题...回头再研究看看  发表于 2019-7-1 13:04
gx_huang 发表于 2019-7-1 13:41 | 显示全部楼层
这种情况,我一般直接用联合体,直接取数了
ayb_ice 发表于 2019-7-1 14:16 | 显示全部楼层
这不是编译器的问题
强制转换u32就可以了
奔波儿熊 发表于 2019-7-1 14:30 | 显示全部楼层
上面有人提到的用uint32 定义变量, 应该可以解决吧, 但我奇怪的是编译器会根据参与计算的数自动转换的吧, 楼主也可以试试在常数后面加U
 楼主| wooda 发表于 2019-7-1 16:01 | 显示全部楼层
gx_huang 发表于 2019-7-1 13:41
这种情况,我一般直接用联合体,直接取数了

嗯,我后来也是这个方法,...但是编译器处理u32的计算出问题也太不应该了,我跟踪过,基本是0xffff到0x010000这里的进位问题
lcczg 发表于 2019-7-1 16:13 | 显示全部楼层
试了下,没出现问题。楼主贴个简单的测试工程,我运行看看。
iDiy 发表于 2019-7-1 16:27 | 显示全部楼层
字长应该是16位的,计算结果超过16位的会截取,保留低16位。
在表达式的右边,dat1,dat2,dat3,dat4加类型强制转换(uin_32)
 楼主| wooda 发表于 2019-7-1 22:54 | 显示全部楼层
本帖最后由 wooda 于 2019-7-1 22:57 编辑
lcczg 发表于 2019-7-1 16:13
试了下,没出现问题。楼主贴个简单的测试工程,我运行看看。

                                                        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的地方就是断点处,也是判断异常的一个分支)
另外我也有怀疑我硬件堆栈快用满了,可能调用long型数的运算子函数导致堆栈方面传递值出错....

21mengnan 发表于 2019-7-1 23:32 | 显示全部楼层
能用移位操作的不用计算。
eastin 发表于 2019-7-2 08:50 | 显示全部楼层
顶起来哦。。。。。。。。。。。。
decoding 发表于 2019-7-2 09:32 | 显示全部楼层
运算之前加强制转换指令
lcczg 发表于 2019-7-2 15:38 | 显示全部楼层
本帖最后由 lcczg 于 2019-7-2 15:53 编辑
wooda 发表于 2019-7-1 22:54
union
                                     ...

借用了楼主所说的常规写法,发现是先前讨论过的数据格式的问题。楼主将char型强制转换为long型再相乘就不会有问题了。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| wooda 发表于 2019-7-3 13:47 | 显示全部楼层
本帖最后由 wooda 于 2019-7-3 13:50 编辑
lcczg 发表于 2019-7-2 15:38
借用了楼主所说的常规写法,发现是先前讨论过的数据格式的问题。楼主将char型强制转换为long型再相乘就不 ...

所以不强制转换你这里也验证会出问题是么
您需要登录后才可以回帖 登录 | 注册

本版积分规则

45

主题

470

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部