C语言数据结构笔记3:Union联合体+结构体取8位Bool量

本文衔接上文要求,新增8位bool量的获取方式。

目录

问题提出:

Union联合体+struct结构体(方式1):

Union联合体+struct结构体(方式2):

BYTE方式读取:


问题提出:

在STM32单片机的编程中,无法定义Bool或者bit类型

但有时候,比如modbus通信时,需要把bool量八个八个地组合读取,少于8个的部分填充0

Union联合体+struct结构体(方式1):

这里是考虑到超过8位的使用场景,因此定义了超过3字节的定义方式

这种方式适合那种喜欢一个一个列出所有寄存器位名称的情况。

cpp 复制代码
#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;
cpp 复制代码
#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):

这种方式不一个一个列出寄存器名称,直接通过地址偏移操作:

cpp 复制代码
#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方式读取:

cpp 复制代码
#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*)&reg.Bytes;

    //print_struct_values(&reg);

     //联合体读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);
    }
}
相关推荐
星轨初途31 分钟前
数据结构二叉树之链式结构(3)(下)
c语言·网络·数据结构·经验分享·笔记·后端
智者知已应修善业2 小时前
【51单片机LED贪吃蛇】2023-3-27
c语言·c++·经验分享·笔记·嵌入式硬件·51单片机
charlie1145141915 小时前
从 0 开始:在 WSL + VSCode 上利用 Maven 构建 Java Spring Boot 工程
java·笔记·vscode·后端·学习·maven·springboot
思成不止于此12 小时前
【C++ 数据结构】二叉搜索树:原理、实现与核心操作全解析
开发语言·数据结构·c++·笔记·学习·搜索二叉树·c++40周年
碧海潮生_CC13 小时前
【CUDA笔记】03 CUDA GPU 架构与一般的程序优化思路(下)
笔记·架构·cuda
钟屿13 小时前
Back to Basics: Let Denoising Generative Models Denoise 论文阅读学习
论文阅读·人工智能·笔记·学习·计算机视觉
d111111111d13 小时前
SPI通信协议--在STM32中介绍(学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习
愚昧之山绝望之谷开悟之坡14 小时前
业务接待-公务接待-商务接待
笔记
大数据追光猿15 小时前
LangChain / LangGraph / AutoGPT / CrewAI / AutoGen 五大框架对比
经验分享·笔记·python·langchain·agent
✎ ﹏梦醒͜ღ҉繁华落℘16 小时前
freeRTOS学习笔记(十四)--内存
笔记·学习