最近发现同事严重忽略的联合的应用,甚至很多人学了联合体这个类型也没用到过。今天浅谈一下联合体的使用。
本期以STM32刷新IO举例。
例:
在上位机发送指令过控制IO时通常采用按位来刷IO,假如不采用结构联合体往往需要与或非各种计算来获取IO状态。
例如上位机发送 0xff设置8个IO状态位高电平
采用按位与计算来获取IO状态
uint8_t cmd =0xff; //上位机发送的命令
for(int i=0; i<8; i++) //分别获取8位数据状态
{
if(cmd & (0x01 <<i))
{
GPIOX=1; //设置IO状态高电平
}else{
GPIOX=0; //设置IO状态低电平
}
}
采用联合体加结构体来获取状态
首先定义一个协议结构体
typedef union{
uint8_t data[10]; //数据
struct
{
uint16_t head; //帧头
uint8_t com; //功能
struct{ //IO输出状态
uint8_t out1:1;
uint8_t out2:1;
uint8_t out3:1;
uint8_t out4:1;
uint8_t out5:1;
uint8_t out6:1;
uint8_t out7:1;
uint8_t out8:1;
}io;
uint16_t crc; //CRC校验
uint16_t end; //帧尾
}arg;
uint8_t reserve[2]; //保留
}SPCPdata,* pSPCPdata;
使用
pSPCPdata spcp = NULL; //实例化
uint8_t tempbuff[10]; //临时变量
uint8_t usartbuff[255]; //串口缓冲区
//假设接收到串口数据
memcpy(usartbuff , tempbuff , 10); //copy数据
spcp = (pSPCPdata )tempbuff; //指针指向临时变量缓冲区,即获取所有数据,下面判断帧头、CRC、帧尾是否正确
if( spcp -> arg.head == 0x5aa5){ //帧头校验
if( spcp -> arg.com== 0x01){ //命令判断
if( spcp -> arg.crc == 校验值){ //CRC判断
if( spcp -> arg.end== 0x0d0a) //帧尾判断
{
GPIOX1=spcp -> arg.out1;
GPIOX2=spcp -> arg.out2;
GPIOX3=spcp -> arg.out3;
GPIOX4=spcp -> arg.out4;
GPIOX5=spcp -> arg.out5;
GPIOX6=spcp -> arg.out6;
GPIOX7=spcp -> arg.out7;
GPIOX8=spcp -> arg.out8;
}
}
}
}
上面联合将data与结构体arg数据进行联合,数据最终大小为10字节,非常方便。之前NFC的帖子也是采用这个结构,采用者这种方法可以直接结构体变量的某一位进行赋值运算,发送时可直接发送data数组。