打印
[PIC®/AVR®/dsPIC®产品]

大家有没有碰到过pic16x单片机uint32类型数据加减乘除运算错

[复制链接]
1178|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吧

使用特权

评论回复
评论
wooda 2019-7-1 13:04 回复TA
这个...写程序总归会碰到unsigned char 参与int32的计算的...不能这样啊 另外好像就算4个int32的运算好像也有问题...回头再研究看看 
板凳
gx_huang| | 2019-7-1 13:41 | 只看该作者
这种情况,我一般直接用联合体,直接取数了

使用特权

评论回复
地板
ayb_ice| | 2019-7-1 14:16 | 只看该作者
这不是编译器的问题
强制转换u32就可以了

使用特权

评论回复
5
奔波儿熊| | 2019-7-1 14:30 | 只看该作者
上面有人提到的用uint32 定义变量, 应该可以解决吧, 但我奇怪的是编译器会根据参与计算的数自动转换的吧, 楼主也可以试试在常数后面加U

使用特权

评论回复
6
wooda|  楼主 | 2019-7-1 16:01 | 只看该作者
gx_huang 发表于 2019-7-1 13:41
这种情况,我一般直接用联合体,直接取数了

嗯,我后来也是这个方法,...但是编译器处理u32的计算出问题也太不应该了,我跟踪过,基本是0xffff到0x010000这里的进位问题

使用特权

评论回复
7
lcczg| | 2019-7-1 16:13 | 只看该作者
试了下,没出现问题。楼主贴个简单的测试工程,我运行看看。

使用特权

评论回复
8
iDiy| | 2019-7-1 16:27 | 只看该作者
字长应该是16位的,计算结果超过16位的会截取,保留低16位。
在表达式的右边,dat1,dat2,dat3,dat4加类型强制转换(uin_32)

使用特权

评论回复
9
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型数的运算子函数导致堆栈方面传递值出错....

使用特权

评论回复
10
21mengnan| | 2019-7-1 23:32 | 只看该作者
能用移位操作的不用计算。

使用特权

评论回复
11
eastin| | 2019-7-2 08:50 | 只看该作者
顶起来哦。。。。。。。。。。。。

使用特权

评论回复
12
decoding| | 2019-7-2 09:32 | 只看该作者
运算之前加强制转换指令

使用特权

评论回复
13
lcczg| | 2019-7-2 15:38 | 只看该作者
本帖最后由 lcczg 于 2019-7-2 15:53 编辑
wooda 发表于 2019-7-1 22:54
union
                                     ...

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

multi.JPG (180.09 KB )

multi.JPG

使用特权

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

所以不强制转换你这里也验证会出问题是么

使用特权

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

本版积分规则

45

主题

464

帖子

1

粉丝