打印

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

[复制链接]
531|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类型的数加减乘除往往就要出错.
大家有什么建议?

使用特权

评论回复
5
llia| | 2020-10-20 20:35 | 只看该作者

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

使用特权

评论回复
6
zhuww| | 2020-10-20 20:39 | 只看该作者
这种情况,我一般直接用联合体,直接取数了

使用特权

评论回复
7
wangpe| | 2020-10-20 20:42 | 只看该作者
这不是编译器的问题
强制转换u32就可以了

使用特权

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

使用特权

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

使用特权

评论回复
10
renyaq| | 2020-10-20 21:05 | 只看该作者

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

使用特权

评论回复
11
liuzaiy| | 2020-10-20 21:08 | 只看该作者
字长应该是16位的,计算结果超过16位的会截取,保留低16位。

使用特权

评论回复
12
ousj| | 2020-10-20 21:12 | 只看该作者
在表达式的右边,dat1,dat2,dat3,dat4加类型强制转换(uin_32)

使用特权

评论回复
13
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的地方就是断点处,也是判断异常的一个分支)

使用特权

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

使用特权

评论回复
15
zhuww| | 2020-10-20 21:31 | 只看该作者
能用移位操作的不用计算。

使用特权

评论回复
16
tian111| | 2020-10-20 21:37 | 只看该作者
运算之前加强制转换指令

使用特权

评论回复
17
zhuhuis| | 2020-10-20 21:42 | 只看该作者
借用了楼主所说的常规写法,发现是先前讨论过的数据格式的问题

使用特权

评论回复
18
chuxh| | 2020-10-20 21:50 | 只看该作者
楼主将char型强制转换为long型再相乘就不会有问题了。

使用特权

评论回复
19
houcs|  楼主 | 2020-10-20 21:53 | 只看该作者

使用特权

评论回复
20
houcs|  楼主 | 2020-10-20 21:56 | 只看该作者
所以不强制转换你这里也验证会出问题是么

使用特权

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

本版积分规则

743

主题

8382

帖子

5

粉丝