1. 结构体定义:位域打包
c
typedef struct
{
uint8_t num:4, /*!< 引脚号 (0~15) */
port:4; /*!< 端口号 (0~15) */
} gpio_port_pin_t;
- 使用位域将两个4位信息压缩到一个字节中。
- 内存布局:低位4位存放
num,高位4位存放port(取决于编译器,通常如此)。 - 结构体大小 = 1字节。
2. 典型用法:从 uint8_t 解析出端口和引脚
c
void gpio_ana_func1_init(uint8_t pin)
{
// 将 pin 的地址强制转换为结构体指针
gpio_port_pin_t *x = (gpio_port_pin_t *)&pin;
// 使用 x->port 和 x->num 访问对应字段
SYSC_AWO->IO[x->port].AE |= 1 << (16 + x->num);
}
关键点:
&pin取得变量pin的地址(uint8_t*)。- 强制转换为
gpio_port_pin_t*,将同一个字节重新解释为结构体。 - 之后通过
x->port和x->num即可获得编码时存入的高4位和低4位。
3. 调用约定
通常调用者将端口和引脚编码为一个字节:
c
// 假设端口=2, 引脚=5 → 编码为 (2<<4) | 5 = 0x25
gpio_ana_func1_init(0x25);
函数内部通过上述转换自然拆解出 port=2, num=5。
4. 注意事项
- 必须使用 **&**取地址 :
(gpio_port_pin_t *)pin是错误的,它会将pin的数值当作内存地址,导致非法访问。 - 内存布局一致性:位域的内存分布可能因编译器而异,但在大多数嵌入式环境中此用法稳定。
- 对齐安全 :
uint8_t与结构体大小均为1字节,对齐无问题。 - 此技巧适用于函数内临时解析,不应用于长期存储或跨模块传递。
5. 优点
- 代码简洁,无需手动移位和掩码。
- 提高可读性,直接使用
x->port、x->num表达意图。