C和Python的串口通信协议小技巧-创新互联

文章目录
    • C
      • 取 u8
      • 从 u8 数组取数据
      • 使用联合体 union
    • Python
      • dict 功能帧
      • struct 包

由于进行串口通信的时候,只能传递 unsigned char(u8) 字节型的数据,所以就会有一些要将几个 u8 合并或者将 (unsigned int)u32 拆成4个 u8 的需求。
在此做一些总结归纳供大家参考,需要有一定嵌入式串口开发经验。

在潞城等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供做网站、成都网站设计 网站设计制作按需定制网站,公司网站建设,企业网站建设,成都品牌网站建设,成都全网营销推广,成都外贸网站建设公司,潞城网站建设费用合理。C
#define u32 unsigned int 
#define s32 int 
#define u16 unsigned short 
#define s16 short
#define u8  unsigned char 
#define s8  char
取 u8
#define BYTE0(dwTemp) (*((char *)(&dwTemp)))
#define BYTE1(dwTemp) (*((char *)(&dwTemp) + 1))
#define BYTE2(dwTemp) (*((char *)(&dwTemp) + 2))
#define BYTE3(dwTemp) (*((char *)(&dwTemp) + 3))

例子:

u32 temp_data_32;
u8 buffer[4];

buffer[0] = BYTE0[temp_data_32];
buffer[1] = BYTE1[temp_data_32];
buffer[2] = BYTE2[temp_data_32];
buffer[3] = BYTE3[temp_data_32];
从 u8 数组取数据
u8 data[num];	// 假设你所需的数据大量存在data数组中

// 取 8bit
u8 data_u8[num];
data_u8[0] = *(data);
data_u8[1] = *(data + 1);
...

// 取 16bit
u16 data_u16[num];
data_u16[0] = *((u16 *)(data));
data_u16[1] = *((u16 *)(data + 2));
data_u16[2] = *((u16 *)(data + 4));
...

s16 data_s16[num];
data_s16[0] = (*((s16 *)(data))) / 1.0f;
data_s16[1] = (*((s16 *)(data + 2))) / 1.0f;
data_s16[2] = (*((s16 *)(data + 4))) / 1.0f;
...

// 取 32bit
s32 data_s32[num];
data_s32[0] = *((s32 *)(data));
data_s32[1] = *((s32 *)(data + 4));
data_s32[2] = *((s32 *)(data + 8));
使用联合体 union

使用联合体将float型数据拆分成字节数组
首先定义一个联合体

typedef union{float data;
	uint8_t data8[4];
}data_u;

这个联合体中有两个成员,一个是32位的float数据data,另一个同样是占据了32位字长的字节数组data8,根据联合体的性质,这两个成员所在的内存位置是一样的,也就是说,改变其中任何一个成员的值,另一个也会被改变.利用这个性质,我们就可以实现float与字节数据的互换。

data_u _temp; // 声明一个联合体实例,使用它将待发送数据转换为字节数组
uint8_t data_to_send[100]; // 待发送的字节数组

data_to_send[_cnt++]=0xAA;
data_to_send[_cnt++]=0xBB;
		
// 将要发送的数据赋值给联合体的float成员
// 相应的就能更改字节数组成员的值
_temp.data = imu_data.yaw;
data_to_send[_cnt++]=_temp.data8[0];
data_to_send[_cnt++]=_temp.data8[1];
data_to_send[_cnt++]=_temp.data8[2];
data_to_send[_cnt++]=_temp.data8[3]; // 最高位

_temp.data = imu_data.pit;
data_to_send[_cnt++]=_temp.data8[0];
data_to_send[_cnt++]=_temp.data8[1];
data_to_send[_cnt++]=_temp.data8[2];
data_to_send[_cnt++]=_temp.data8[3]; // 最高位

_temp.data = imu_data.rol;
data_to_send[_cnt++]=_temp.data8[0];
data_to_send[_cnt++]=_temp.data8[1];
data_to_send[_cnt++]=_temp.data8[2];
data_to_send[_cnt++]=_temp.data8[3]; // 最高位

接收端同理,只要将接收到的数据逐个存入联合体的 data8[] 数组中就好,然后调用data进行使用。

Python dict 功能帧

可以巧妙使用 Python 中的 dict 数据类型,以此来记入功能帧。

param_dic = {'speed': 0x01, 'voltage': 0x02, 'read': 0x03}
struct 包

python struct
参考上面的官方文档,使用就好了
列举一些注意点:

  1. 注意本机字节顺序,可用sys.byteorder来检查你的系统字节顺序
  2. 解包(unpack)后,低字节在前,高字节在后
  3. 由于串口传递的是无符号字节型数据,若接收的变量是有符号类型如h格式,将自动进行如下操作。在C语言端的处理要注意
    eg.
import struct

data = struct.pack('BBBBBBBB', 0xEA, 0xFF, 0x1E, 0x00, 0x64, 0x60, 0xEA, 0xFF)	# 打包
print(data)
data = struct.unpack('
b'\xea\xff\x1e\x00d`\xea\xff'
-22
30
65514

data[0] = eaff = ffea = 65514-65536 = - 22
data[1] = 1e00 = 001e = 30
data[4] = eaff = ffea = 65514
因为有符号类型,最高位表示正负。

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


本文名称:C和Python的串口通信协议小技巧-创新互联
分享地址:http://azwzsj.com/article/jcdhc.html