arduino 大小端数据问题
来源:互联网 发布:写筒谱的软件 编辑:程序博客网 时间:2024/04/28 18:14
以前在百度空间写的文章,现在百度空间关闭了,搬到这里吧,做个笔记吧。
arduino数据的存储方式是小端的,调试了两天的程序,终于发现这个问题了。
下面说一下发现问题的过程:
首先我定义了一个结构体,用来接收串口发送来的数据,串口发送来的数据首先放到数组中,再强制转换成结构体类型,定义结构体的意义就在于我想实现一种自定义的协议。
协议如下
命令头+命令长度+数据长度+命令+错误代码+数据+校验码
由于命令头是固定的,我的命令以0xFE开头,因此没有定义到结构体中。
结构体如下
/******************
* UartCmdLen:UartCmd + UartErrCode
* UartDataLen:UartDataBuf
*******************/
typedef struct __sUartData{
uint8_t UartCmdLen;
uint8_t UartDataLen;
uint16_t UartCmd;
uint8_t UartErrCode;
uint8_t UartDataBuf[1];
}
*psUartData;
定义的数组
uint8_t UartBuf[UART_MAX_LEN] = { 0 };
用于存放串口接收的数据。
把数组的数据转换成结构体格式
psUartDataRevSend = (psUartData)UartBuf;
这样访问发送来的数据就方便多了,比如psUartDataRevSend->UartCmdLen ,psUartDataRevSend->UartDataLen等。
但是发现发送来的数据发生了错误。读取数组的数据没有错误,访问结构体中uint8_t类型的数据也正常,uint16_t类型的数据却不符。
比如我发送如下数据(16进制)
FE 03 04 0003 00 00000000 FA
发送的不含空格,为方便大家看清协议,添加了空格。我发现收到的是0x300(或者是0x000300),而不是0x0003(也就是0x03),我怀疑uint16_t类型的数据多了一个字节。
首先我以为是int类型长度的问题,arduino uno的int是2个字节,arduino due的是4个字节,我的是uno,板子是uno,ide中选择的也是uno,
应该不是类型长度的问题。在arduino ide中如下定义也是编译通过的 uint8_t t=0xffffffff;,这个明显超出了范围,不知道原因啊。
其次我也为时结构体对齐的问题,我用sizeof()测试结构体的大小也是6,也不是这个问题,为保险起见,我用
#pragma pack(1)指定对齐方式,但是还是不对,应该也不是这个原因。
百思不得其解的时候,我决定多用几组数据去测试,后面是得到的uint16_t成员变量的值(16进制)
FE0304 0130 0001000000C9 3001
FE0304 0003 0000000000FA 300
FE0304 0102 0304050607FE 201
FE0304 0310 0001000000C9 1003这样大家可能没发现什么问题,我给大家补齐一下
FE0304 0130 0001000000C9 3001
FE0304 0003 0000000000FA 0300
FE0304 0102 0304050607FE 0201
FE0304 0310 0001000000C9 1003再转一下
FE0304 01 30 0001000000C9 30 01
FE0304 00 03 0000000000FA 03 00
FE0304 01 02 0304050607FE 02 01
FE0304 03 10 0001000000C9 10 03应该发现uint16_t类型的数据高低位颠倒了,这就是大小端存储方式不同造成的。
下面分别是2字节和4字节转换的宏命令。arduino论坛有用union来转换4字节的方法,至于更大的数据float也是用union,再大的数据就是用数组,数组从大到小读取就能实现转换了。
#define htons(A) ((((uint16_t)(A) & 0xff00) >> 8 ) | (((uint16_t)(A) & 0x00ff) << 8 ))
#define htonl(A) ((((uint32_t)(A) & 0xff000000) >> 24) | (((uint32_t)(A) & 0x00ff0000) >> 8 ) | (((uint32_t)(A) & 0x0000ff00) << 8 ) | (((uint32_t)(A) & 0x000000ff) << 24))
这样就能正确识别命令了htons(psUartDataRevSend->UartCmd);
下面show一下具体的使用代码
switch(htons(psUartDataRevSend->UartCmd))
{
case 0x0002: //检测串口状态
//check_com( psUartDataRevSend );
break;
case 0x0003: //查询卡号
Serial.print("111");
break;case 0x0110: //修改密码方式
//updata_key( psUartDataRevSend );
break;case 0x0120: //读数据块方式
//block_read( psUartDataRevSend );
break;case 0x0130: //写数据块方式
//block_write( psUartDataRevSend );
break;case 0x0140: //板子控制
//ctrl_by_board( psUartDataRevSend );
break;default:
psUartDataRevSend->UartErrCode = ERROR_NOCMD;
break;
}
- arduino 大小端数据问题
- EDK中数据大小端的问题
- 数据存储的大小端问题
- 大小端数据转换
- 大小端数据转换
- 数据存储大小端
- Arduino处理JSON数据
- 段中的实际数据大小与占用空间大小问题
- 段中的实际数据大小与占用空间大小问题
- arduino问题记录
- arduino实践问题
- ARDUINO驱动问题
- python中比较数据大小的问题
- 存储大小端问题
- 大小端存储问题
- 大小端问题
- cpu大小端问题
- 大小端问题
- 火星坐标系转北京54坐标方法
- Jenkins部署新项目
- Eclipse NDK安装流程详解
- GCD与NSOperation
- 在Windows下使用Gpg4win对文件进行完整性校验(PGP校验)
- arduino 大小端数据问题
- Linux内核IP Queue机制的分析(一)——用户态接收数据包
- KMP算法总结
- canvas基础学习(二)-线条的属性与星空和图形变换
- Intent 实现Activity跳转
- 发表测试
- 面向对象之三大特点
- 米老师讲课:到底怎么学习
- scrapy爬取动态分页内容