硬汉嵌入式论坛

 找回密码
 立即注册
查看: 503|回复: 20
收起左侧

[MDK] Keil 5.36 数据右移会出问题

  [复制链接]

6

主题

50

回帖

68

积分

初级会员

积分
68
发表于 7 天前 | 显示全部楼层 |阅读模式
一个简单的程序,我发现数据右移,哪怕只右移一位,实际得到的数据也不是理论计算出来的值。
我监控数据的方式,是用串口助手读取。不过数据实际上是高速USB发送的,用一个USB3300的模块。
[C] 纯文本查看 复制代码
void SEND(uint32_t value)
{
        uint32_t valu_un = 0;
        uint8_t  val[3] = {0};

        valu_un = value;

        val[0] = (valu_un >> 30);
        val[1] = (valu_un >> 22);
        val[2] = (valu_un >> 14);

        CDC_Transmit_HS(val, sizeof(val));    //通过USB3300模块把数据发送到上位机
}

哪怕我直接给这个valu_un 赋一个确定的值,右移之后给val[],读取的值也不对。
我在想,是编译器的问题吗?这个右移的写法应该没有问题吧



回复

使用道具 举报

0

主题

21

回帖

21

积分

新手上路

积分
21
发表于 7 天前 | 显示全部楼层
valu_un是多少,移位之后的var 012是多少,在线调试值和usb传出来的值一样吗
回复

使用道具 举报

6

主题

50

回帖

68

积分

初级会员

积分
68
 楼主| 发表于 7 天前 | 显示全部楼层
m1249394401 发表于 2025-6-27 15:57
valu_un是多少,移位之后的var 012是多少,在线调试值和usb传出来的值一样吗

valu_un = value,value是ADC采集的结果,是左对齐的18位有效数值;移位之后,val[0]就是0,val[1]是01,val[2]最低3位会跳动。总之就是肯定不是正常的值。
回复

使用道具 举报

2

主题

80

回帖

86

积分

初级会员

积分
86
发表于 7 天前 | 显示全部楼层
log 贴出来让大伙看看
回复

使用道具 举报

6

主题

50

回帖

68

积分

初级会员

积分
68
 楼主| 发表于 7 天前 | 显示全部楼层
CoderXMan 发表于 2025-6-27 18:46
log 贴出来让大伙看看

log 是什么?
回复

使用道具 举报

85

主题

792

回帖

1047

积分

至尊会员

积分
1047
发表于 7 天前 | 显示全部楼层
就没有怀疑大小端的问题吗
回复

使用道具 举报

4

主题

395

回帖

407

积分

高级会员

积分
407
发表于 7 天前 | 显示全部楼层
庄永 发表于 2025-6-27 21:51
就没有怀疑大小端的问题吗

他这个代码是移位操作和大小端无关,不是操作原始内存字节。但是电脑那边拼接数据就不好说了
其实先用串口打印val各个字节再折腾更合适。
回复

使用道具 举报

4

主题

121

回帖

133

积分

初级会员

积分
133
发表于 6 天前 | 显示全部楼层
"uint8_t  val[3]",你到底是要取“uint32_t value”的那些字段?
回复

使用道具 举报

6

主题

50

回帖

68

积分

初级会员

积分
68
 楼主| 发表于 4 天前 | 显示全部楼层
cctv180 发表于 2025-6-27 23:37
他这个代码是移位操作和大小端无关,不是操作原始内存字节。但是电脑那边拼接数据就不好说了
其实先 ...

我这个是用单片机的高速USB、通过USB3300模块,用虚拟串口发送到上位机,我想应该和串口打印一样的吧?
回复

使用道具 举报

6

主题

50

回帖

68

积分

初级会员

积分
68
 楼主| 发表于 4 天前 | 显示全部楼层
我需要的是其中18位有效数据,原始数据为左对齐,我想改成右对齐,然后发送
回复

使用道具 举报

25

主题

216

回帖

291

积分

高级会员

积分
291
QQ
发表于 3 天前 | 显示全部楼层
红烧鱼头 发表于 2025-6-27 17:28
valu_un = value,value是ADC采集的结果,是左对齐的18位有效数值;移位之后,val[0]就是0,val[1]是01, ...

我大概理解了,这不是你移位移错了嘛。

传入的 value 应该是低18位是有效值,高位根本没有,就导致这种情况了。
回复

使用道具 举报

6

主题

50

回帖

68

积分

初级会员

积分
68
 楼主| 发表于 3 天前 | 显示全部楼层
yono 发表于 2025-7-1 14:39
我大概理解了,这不是你移位移错了嘛。

传入的 value 应该是低18位是有效值,高位根本没有,就导致这 ...

不是,我确定是高18位有效,这是左对齐的数据。
回复

使用道具 举报

25

主题

216

回帖

291

积分

高级会员

积分
291
QQ
发表于 3 天前 | 显示全部楼层
红烧鱼头 发表于 2025-7-1 15:56
不是,我确定是高18位有效,这是左对齐的数据。

你有调试监控val[0...2] 吗?

移位操作不会有问题的,我刚也测试了一下。

另外你这样移位出来得到的val数组是大端的。
回复

使用道具 举报

6

主题

50

回帖

68

积分

初级会员

积分
68
 楼主| 发表于 3 天前 | 显示全部楼层
yono 发表于 2025-7-1 16:58
你有调试监控val[0...2] 吗?

移位操作不会有问题的,我刚也测试了一下。

我知道原因了!
我在watch里面看了,移位操作没有问题。确实是输入的数据本身不对。之前我说直接给valu_un 赋值也不行,实际上是我的操作和记录出错了。
回复

使用道具 举报

25

主题

216

回帖

291

积分

高级会员

积分
291
QQ
发表于 3 天前 | 显示全部楼层
红烧鱼头 发表于 2025-7-1 17:26
我知道原因了!
我在watch里面看了,移位操作没有问题。确实是输入的数据本身不对。之前我说直接给valu_ ...

您这调试马大哈,帖子曼德拉👍
回复

使用道具 举报

3

主题

28

回帖

37

积分

新手上路

积分
37
发表于 前天 08:26 | 显示全部楼层
不要动不动怀疑编译器的问题, 而且还是这么基础的操作。
回复

使用道具 举报

6

主题

50

回帖

68

积分

初级会员

积分
68
 楼主| 发表于 前天 08:47 | 显示全部楼层
问题已搞明白,是数据输入的问题。
回复

使用道具 举报

0

主题

61

回帖

61

积分

初级会员

积分
61
发表于 前天 09:00 | 显示全部楼层
红烧鱼头 发表于 2025-7-2 08:47
问题已搞明白,是数据输入的问题。

怀疑 Keil 有问题,可以写个简单的移位程序验证。

若还不放心,可以用 gcc 也跑下。
回复

使用道具 举报

6

主题

50

回帖

68

积分

初级会员

积分
68
 楼主| 发表于 前天 14:02 | 显示全部楼层
cdr430 发表于 2025-7-2 09:00
怀疑 Keil 有问题,可以写个简单的移位程序验证。

若还不放心,可以用 gcc 也跑下。

我就是在别的编译器上验证了移位的程序没有问题,才觉得奇怪。后来发现和输入的数据有关,输入数据是个共用体,我对共用体的理解很不到位。
回复

使用道具 举报

6

主题

50

回帖

68

积分

初级会员

积分
68
 楼主| 发表于 前天 14:13 | 显示全部楼层
本帖最后由 红烧鱼头 于 2025-7-2 14:14 编辑

解释一下吧,输入SEND(uint32_t value)这个函数的数据本身是个共用体。

[C] 纯文本查看 复制代码
union data
{
        uint8_t arr[4];
        uint32_t nu;
};
union data value;


我把ADC采样到的数据依次放入 value.arr[0] 到 value.arr[3],然后再把 value.nu 的值作为 SEND(uint32_t value) 函数的输入值。

这个时候出了问题!
因为采集到的值是高位在前、左对齐的数据,也就是说,value.arr[0] 存的是最高8位的数据,value.arr[3] 是最低8位。
但是把 value.nu 发送出去的时候,value.nu 的地址 其实是value.arr[3] !
也就说,32位的数据 value.nu 不能直接进行使用。


举个例子,ADC采集到的值是 0x12345678(纯粹举例子,实际ADC的精度是18位),保存到value.arr[]时,依次是:
value.arr[0]=0x12;
value.arr[0]=0x34;
value.arr[0]=0x56;
value.arr[0]=0x78;
此时  value.nu = 0x78563412,而不是0x12345678 !

我把这个数作为SEND(uint32_t value)的输入参数,并直接把数据右移,这个时候当然就出问题了!

回复

使用道具 举报

0

主题

61

回帖

61

积分

初级会员

积分
61
发表于 前天 16:06 | 显示全部楼层
红烧鱼头 发表于 2025-7-2 14:13
解释一下吧,输入SEND(uint32_t value)这个函数的数据本身是个共用体。

[mw_shl_code=c,true]union data ...

总结三个字:大小端。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-7-4 18:36 , Processed in 0.386734 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表