好多时候大家可能碰上要将一些比较古怪的自定义数据结构按字节放入一些片外器件里的情况,比如I2C总线的FLASH。 举个例子先: ============================================下面先定义一个要用到的结构============================================ typedef unsigned char UINT8; typedef unsigned short int UINT16; typedef unsigned long int UINT32; typedef signed char INT8; typedef signed short int INT6; typedef signed long int INT32;
typedef struct { UINT8 D0[12]; UINT16 D1[34]; UINT32 D2[56] UINT32 D3 : 8; UINT32 D4 : 2; UINT32 D5 : 2; UINT32 D6 : 8; UINT32 D7 : 12; INT8 D8[560]; INT16 D9[126]; INT32 D10[11]; }EXP_Struct_1;
============================================然后用上面的结构定义需要保存的内容============================================ EXP_Struct_1 Save;
这时候save结构体中假设已经有了需要进行存储的数据,只需要将相关数据全部转化为字节然后就能存储的时候,可以采用两种方法: 1,强制类型转换 memcpy( Buffer, (UINT8 *)&Save, sizeof(Save) );
memcpy是库函数,或自己实现的函数,功能是将(uint8 *)&Save为首地址,需拷贝的长度为sizeof(Save)的内容拷贝到Buffer中 函数原型void *memcpy(void *dest, const void *src, size_t n);
2,共用体的转换(利用其共享内存空间的特性) typedef union { EXP_Struct_1 Struct_Type; UINT8 Mem_Type[/*注意*/]; }TEMP_UNION; /*方括号内填入的大小就是sizeof(Save)的大小*/
然后可以编写一个“发送”函数,在函数中定义并赋值: TEMP_UNION Temp; Temp.Struct_Type = Save; 此时Temp.Mem_Type[]中就是你需要存储的结构体,这时候已经是uint8数组了...发送起来自然就可以很方便得用数组下标++,或者Temp.Mem_Type(该数组首地址)作为指针++的方式,然后发送完毕,作为auto变量存在的TEMP_UNION共用体Temp会被自动销毁(因为这是在“发送”函数内部定义的),所以绝对绿色+环保。
我现在用的是第二种方法...毕竟第二种方法较第一种来得更直观,下面以最近的应用再举个例子: 有这么个中断驱动扫描按键的应用,按一定时间的周期扫描24个按键的状态,按键为74HC165级联方式读入,按键模式有常开、常闭以及类似于拨码开关的类型,也就是所谓“没有按键”的时候,读入的并不是全1或全0,而是一个1及0组合的定值,读入的并不是“有无按键”而是“按键状态改变” 我在处理的时候设定为定时器触发,每10ms一次,在中断中读入74HC165的值,按键值类型是这样定义的(由于使用32位MCU,为效率考虑,变量定义我都是按32位为主): typedef struct { // Input Data UINT32 X027 : 1; // LSB UINT32 X026 : 1; UINT32 X025 : 1; UINT32 X024 : 1; UINT32 X023 : 1; UINT32 X022 : 1; UINT32 X021 : 1; UINT32 X020 : 1; UINT32 X017 : 1; UINT32 X016 : 1; UINT32 X015 : 1; UINT32 X014 : 1; UINT32 X013 : 1; UINT32 X012 : 1; UINT32 X011 : 1; UINT32 X010 : 1; UINT32 X007 : 1; UINT32 X006 : 1; UINT32 X005 : 1; UINT32 X004 : 1; UINT32 X003 : 1; UINT32 X002 : 1; UINT32 X001 : 1; UINT32 X000 : 1; // Unused UINT32 UN07 : 1; UINT32 UN06 : 1; UINT32 UN05 : 1; UINT32 UN04 : 1; UINT32 UN03 : 1; UINT32 UN02 : 1; UINT32 UN01 : 1; UINT32 UN00 : 1; // MSB }Digital_Input_Struct;
// 按键结构体声明(定义+赋值部分省略) extern volatile Digital_Input_Struct DIN; 这样的结构是为了使用起来方便,读入第一个按键时只需要判定DIN.X000为0和1就能知道目前按键的状态,且按键为10ms周期性扫描,通过一个可设定的读入次数变量可以做到读入X次均为1(0),该按键当前状态就为1(0),作消抖之用。下面定义了一个转换格式用的共用体: typedef union { Digital_Input_Struct DIN_Struct; UINT32 UINT32_TYPE; }Digital_Input_Union; // 按键共用体声明(作为缓存,判定时用,定义+赋值部分省略) extern volatile Digital_Input_Union DIN_Temp[/*设定大小*/];
我在中断中要比较有无按键按下,只需要调用165读取函数,该函数自动将24个读入数据依次赋值给作缓存用的DIN_Temp[0]的X000~X007,X010~X017(8进制序号表示),X020~X027这24个成员中,【注意:在此处是以DIN_Temp[0].DIN_Struct.X000~DIN_Temp[0].DIN_Struct.X027作为被赋值对象这样的方式调用的】 然后在中断程序中,我只需要判定DIN_Temp[0].UINT32_TYPE(这一次的按键状态)以及DIN_Temp[1].UINT32_TYPE(上一次的按键状态)DIN_Temp[2].UINT32_TYPE(上上次的按键状态),以此类推...因为结构体整体无法比大小,各个成员拿来比,在我这个应用中会显得很麻烦,但共用体将结构体转化成的UINT32型自然就可以了,最后假设需要确认4次即认定按键状态改变的话【即DIN_Temp[0].UINT32_TYPE~DIN_Temp[3].UINT32_TYPE这4个周期扫到的按键值相等,且和DIN_Temp[4].UINT32_TYPE及之后几个值不等】就认定按键的值被改变了,只需要将这个按键值以如此方式赋值: DIN = DIN_Temp[0].DIN_Struct; //【结构体赋值给结构体,这类型要多匹配有多匹配】 ============================================下面是总结============================================ 肯定还有很多好用的方法,希望大家也能拿来共享一下让本菜鸟开开眼界...- - |