本文銜接上文要求,新增8位bool量的獲取方式。
目錄
問題提出:
Union聯合體+struct結構體(方式1):
Union聯合體+struct結構體(方式2):
BYTE方式讀取:
問題提出:
在STM32單片機的編程中,無法定義Bool或者bit類型
但有時候,比如modbus通信時,需要把bool量八個八個地組合讀取,少于8個的部分填充0
Union聯合體+struct結構體(方式1):
這里是考慮到超過8位的使用場景,因此定義了超過3字節的定義方式
這種方式適合那種喜歡一個一個列出所有寄存器位名稱的情況。
#define BITS_PER_BYTE 8 #define BYTES_FOR_BITS 3 //// 定義3字節的位字段結構 typedef union {uint8_t bytes[BYTES_FOR_BITS]; // 整個字節數組訪問struct {// 每個字節單獨定義位字段struct {uint8_t b0 : 1;uint8_t b1 : 1;uint8_t b2 : 1;uint8_t b3 : 1;uint8_t b4 : 1;uint8_t b5 : 1;uint8_t b6 : 1;uint8_t b7 : 1;} byte0;struct {uint8_t b0 : 1;uint8_t b1 : 1;uint8_t b2 : 1;uint8_t b3 : 1;uint8_t b4 : 1;uint8_t b5 : 1;uint8_t b6 : 1;uint8_t b7 : 1;} byte1;struct {uint8_t b0 : 1;uint8_t b1 : 1;uint8_t b2 : 1;uint8_t b3 : 1;uint8_t b4 : 1;uint8_t b5 : 1;uint8_t b6 : 1;uint8_t b7 : 1;} byte2;} bits; } LargeBitField;
#include <stdio.h>typedef unsigned char uint8_t; typedef unsigned short int uint16_t; typedef signed short int int16_t;#pragma pack(push, 1) //:將結構體的對齊方式設置為 1 字節,并將當前對齊設置保存到堆棧中。//0x03e8 - 0x03ee typedef struct ABC_regs1 {uint16_t A1;uint16_t B1;int16_t C1;int16_t D1;uint16_t E1;int16_t F1;int16_t G1; }ABC_regs_1;//0x177B - 0x1781 typedef struct ABC_regs2 {uint16_t A2;uint16_t B2;int16_t C2;int16_t D2;uint16_t E2;int16_t F2;int16_t G2; }ABC_regs_2;#define BITS_PER_BYTE 8 #define BYTES_FOR_BITS 3 //// 定義15字節的位字段結構 typedef union {uint8_t bytes[BYTES_FOR_BITS]; // 整個字節數組訪問struct {// 每個字節單獨定義位字段struct {uint8_t b0 : 1;uint8_t b1 : 1;uint8_t b2 : 1;uint8_t b3 : 1;uint8_t b4 : 1;uint8_t b5 : 1;uint8_t b6 : 1;uint8_t b7 : 1;} byte0;struct {uint8_t b0 : 1;uint8_t b1 : 1;uint8_t b2 : 1;uint8_t b3 : 1;uint8_t b4 : 1;uint8_t b5 : 1;uint8_t b6 : 1;uint8_t b7 : 1;} byte1;struct {uint8_t b0 : 1;uint8_t b1 : 1;uint8_t b2 : 1;uint8_t b3 : 1;uint8_t b4 : 1;uint8_t b5 : 1;uint8_t b6 : 1;uint8_t b7 : 1;} byte2;} bits; } LargeBitField;typedef struct Letter_regs {ABC_regs_1 ABC1; //0x03e8 - 0x03f1 //7成員 14字節 //偏移量 0x00- 0x0cABC_regs_2 ABC2; //0x177B - 0x1781 //7成員 14字節 //BOOL_1 Bool1; //LargeBitField Bytes; }letter_regs;int main(void) {letter_regs reg;// 設置位reg.Bytes.bits.byte0.b0 = 1; // 設置byte0的第0位為1reg.Bytes.bits.byte1.b7 = 1; // 設置byte1的第7位為1// 讀取位uint8_t bit0 = reg.Bytes.bits.byte0.b0;uint8_t bit7 = reg.Bytes.bits.byte1.b7;printf("Bit 0 of byte0: %d\n", bit0);printf("Bit 7 of byte1: %d\n", bit7);// 通過字節數組訪問reg.Bytes.bytes[0] = 0x0F; // 設置byte0為0x0Fprintf("Byte 0: 0x%02X\n", reg.Bytes.bytes[0]);}
Union聯合體+struct結構體(方式2):
這種方式不一個一個列出寄存器名稱,直接通過地址偏移操作:
#include <stdio.h>typedef unsigned char uint8_t; typedef unsigned short int uint16_t; typedef signed short int int16_t;#pragma pack(push, 1) //:將結構體的對齊方式設置為 1 字節,并將當前對齊設置保存到堆棧中。//0x03e8 - 0x03ee typedef struct ABC_regs1 {uint16_t A1;uint16_t B1;int16_t C1;int16_t D1;uint16_t E1;int16_t F1;int16_t G1; }ABC_regs_1;//0x177B - 0x1781 typedef struct ABC_regs2 {uint16_t A2;uint16_t B2;int16_t C2;int16_t D2;uint16_t E2;int16_t F2;int16_t G2; }ABC_regs_2;// 定義字節的位字段結構 typedef union {uint8_t byte; // 整個字節數組訪問struct {uint8_t b0 : 1;uint8_t b1 : 1;uint8_t b2 : 1;uint8_t b3 : 1;uint8_t b4 : 1;uint8_t b5 : 1;uint8_t b6 : 1;uint8_t b7 : 1;} bits; }BitField;typedef struct Letter_regs {ABC_regs_1 ABC1; //0x03e8 - 0x03f1 //7成員 14字節 //偏移量 0x00- 0x0cABC_regs_2 ABC2; //0x177B - 0x1781 //7成員 14字節 BitField Bytes[10]; }letter_regs;int main(void) {letter_regs reg;// 通過直接賦值給聯合體的字節reg.Bytes[0].byte = 0xA5; // 0xA5 in hex is 10100101 in binary// 通過位域賦值reg.Bytes[1].bits.b0 = 1; // Set bit 0 to 1reg.Bytes[1].bits.b7 = 1; // Set bit 7 to 1// 讀取并打印結果printf("Byte 0: 0x%02X\n", reg.Bytes[0].byte); // 輸出 0xA5printf("Byte 1: 0x%02X\n", reg.Bytes[1].byte); // 輸出 0x81 (因為 b7 和 b0 被設置為1)}
BYTE方式讀取:
#include <stdio.h>typedef unsigned char uint8_t; typedef unsigned short int uint16_t; typedef signed short int int16_t; #pragma pack(push, 1) //:將結構體的對齊方式設置為 1 字節,并將當前對齊設置保存到堆棧中。//0x03e8 - 0x03ee typedef struct ABC_regs1 {uint16_t A1;uint16_t B1;int16_t C1;int16_t D1;uint16_t E1;int16_t F1;int16_t G1; }ABC_regs_1;//0x177B - 0x1781 typedef struct ABC_regs2 {uint16_t A2;uint16_t B2;int16_t C2;int16_t D2;uint16_t E2;int16_t F2;int16_t G2; }ABC_regs_2;// 定義字節的位字段結構 typedef union {uint8_t byte; // 整個字節數組訪問struct {uint8_t b0 : 1;uint8_t b1 : 1;uint8_t b2 : 1;uint8_t b3 : 1;uint8_t b4 : 1;uint8_t b5 : 1;uint8_t b6 : 1;uint8_t b7 : 1;} bits; }BitField;typedef struct Letter_regs {ABC_regs_1 ABC1; //0x03e8 - 0x03f1 //7成員 14字節ABC_regs_2 ABC2; //0x177B - 0x1781 //7成員 14字節 BitField Bytes[10]; //0x0400 - 0x0450 //80 成員 }letter_regs;int main(void) {letter_regs reg;// 通過直接賦值給聯合體的字節reg.Bytes[0].byte = 0xAA; // 0xA5 in hex is 10100101 in binaryreg.Bytes[8].byte = 0x6A; // 0xA5 in hex is 10100101 in binaryunsigned char* ptr = (unsigned char*)®.Bytes;//print_struct_values(®);//聯合體讀8個,實際物理地址才偏移1,相對于基地址地偏移量,都一個BYTE才偏移1for (int j = 0; j < 10; j++) //讀10個BYTE 整個聯合體{unsigned char offset = j; // 計算偏移量uint8_t value = *(const uint8_t*)(ptr + offset);printf("Byte %d: 0x%02X\n",j,value);} }