本文衔接上文要求,新增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- 0x0c ABC_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位为1 reg.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为0x0F printf("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- 0x0c ABC_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 1 reg.Bytes[1].bits.b7 = 1; // Set bit 7 to 1 // 读取并打印结果 printf("Byte 0: 0x%02X\n", reg.Bytes[0].byte); // 输出 0xA5 printf("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 binary reg.Bytes[8].byte = 0x6A; // 0xA5 in hex is 10100101 in binary unsigned char* ptr = (unsigned char*)®.Bytes; //print_struct_values(®); //联合体读8个,实际物理地址才偏移1,相对于基地址地偏移量,都一个BYTE才偏移1 for (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); } }