最近在做移植时,遇到个问题,之前采用的IAR STVD环境都没有问题,今天采用MDK 4.12,出现了问题,出现 'expected an identifier'警告。
typedef struct _data { u8 phy_id[8]; u8 sec_id[6]; u8 switch_s; union battery { u16 battery0; //高位字节填充整数部分,低位字节填充小数部分 struct { u8 battery2; //电池部分的小数部分 u8 battery1; //电池能量的整数部分 }; }; }data;
//message 的大小字节对齐为21个字节typedef struct _message { u8 cmd; struct _data data; u8 reserved; u16 ack; }message;
下图是不顾警告直接编译后动态调试时所看到的结构内容,明显的没有battery0的符号,后面证实,这里MDK没有给分配空间
(STVD 编译的STM8S程序)发送端填充结构体内容如下:
msg.cmd = TAG_COORDINARY_CMD; seq++; battery_h=3; _memcpy(&msg.data.phy_id[4],(char *)&seq,4); _memcpy(msg.data.sec_id,(char *)&seq,4); msg.data.switch_s = 0; msg.data.battery0 = battery_h << 8 | battery_l; //标签电压值 msg.reserved = 0x36; msg.ack = 0xFFEE;
(MDK 编译的STM32程序) 接收端接收后内容如下:
万恶的MDK啊,reserved 和ack的数值都是错误的。
非的改成这样才能编译通过:
这样问题又来了,与原来的字节数比多了几个字节,估计是对齐导致的。这里是24个字节。typedef struct _data { u8 phy_id[8]; u8 sec_id[6]; u8 switch_s; union { u16 battery0; //高位字节填充整数部分,低位字节填充小数部分 struct { u8 battery2; //电池部分的小数部分 u8 battery1; //电池能量的整数部分 }batt; }battery; }data;
最后是使用__packed进行修饰才正常,调试也通过
typedef __packed struct _data { u8 phy_id[8]; u8 sec_id[6]; u8 switch_s; __packed union { u16 battery0; //高位字节填充整数部分,低位字节填充小数部分 __packed struct { u8 battery2; //电池部分的小数部分 u8 battery1; //电池能量的整数部分 }batt; }battery; }data; typedef __packed struct _message { u8 cmd; struct _data data; u8 reserved; u16 ack; }message;
总结:
MDK 4.12在处理联合体与结构体时,语法上与IAR STVD VS等工具的编译器有些出入。
MDK 4.12下编译STM32程序时,要注意结构体大小问题,默认是字对齐方式的。可使用__packed关键字修饰为字节方式对齐。