
本文共 2213 字,大约阅读时间需要 7 分钟。
前言
本文主要介绍了以位带操作为代表的F429寄存器的位操作方法。常见的寄存器位操作方法包括与或操作、位域操作和位带操作。本文将以GPIO输入输出寄存器(GPIO_ODR)为例,详细阐述三种方法的实现方式。
文章目录
- 与或操作
- Struct位域操作
- 位带操作
- 基本概念
- 地址转换
- 编程实现
- GPIO置位寄存器
与或操作
与或操作是最通用的寄存器位操作方式。该方法分为两种常见操作:设置目标位为1或清除目标位为0。
这种方法的优点是通用性强,适用于大多数寄存器。不过,当用于高效位操作时,其速度相对较低。这也是为其他方法(如Struct位域和位带操作)提供了基础。
Struct位域操作
Struct位域操作是C语言本身支持的一种高效位操作方法。这种方法通过定义一个包含每位描述的结构体,实现对寄存器每一位的独立操作。
例如,可以定义如下的结构体:
typedef struct{ unsigned int bit0 : 1; unsigned int bit1 : 1; ... unsigned int bit31 : 1; } BIT_TypeDef;
然后,将需要操作的寄存器地址与BIT_TypeDef强制类型转换,并通过结构体成员访问目标位。例如:
#define IOB ((BIT_TypeDef*)GPIOB_ODR_Addr) IOB->bit1 = 0;
这种方法的优点是编程简单,并且其速度和资源占用都很低。但是,它的缺点是语法复杂,且不支持位带操作的原子性访问。
位带操作
基本概念
位带操作是一种高效的位操作方式,通过特定的位带区域和位带别名,实现对寄存器单个位的快速访问。这种操作方式在外设中具有广泛应用。
位带操作的关键概念包括:
- 位带区域:支持位带操作的存储器区域
- 位带别名:提供对位带区域的高效访问方式
常见的位带区域和对应的其它信息如下:
位带区域 | 位带别名 |
---|---|
0x20000000-0x200FFFFF | 0x22000000-0x23FFFFFF |
0x40000000-0x400FFFFF | 0x42000000-0x43FFFFFF |
地址转换
位带操作需要将寄存器地址转换为位带所用的字节地址。转换公式如下:
$bit\_word\_addr = bit\_band\_base + ((address - bit\_band\_base) \times 32) + (bit\_number \times 4)$其中:
- $bit\_band\_base$:位带别名的起始地址
- $(address - bit\_band\_base)$:因子
- $bit\_number$:目标位在字节中的位置
例如,APB1和AHB1等外设的位带别名如下:
外设 | 位带别名 |
---|---|
APB1 | 0x22000000-0x23FFFFFF |
APB2 | 0x42000000-0x43FFFFFF |
编程实现
实现位带操作可以通过宏定义或特定关键字。常见的实现方法包括以下两种:
宏定义方式
#define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr &0xFFFFF) << 5) + (bitnum << 2))
该宏定义通过按位操作生成位带操作的字节地址。
属性属性方式
typedef struct{ unsigned int bit0 : 1; ... unsigned int bit31 : 1; } __attribute__((bitband)) BB;
定义一个带有“bitband”属性的结构体,用于实现高效位操作。例如,可以这样使用:
BB PBO __attribute__((at(GPIOB_ODR_Addr)));
GPIO置位寄存器
在GPIO中,常见的寄存器包括输入向量寄存器(IDR)和输出向量寄存器(ODR)。这些寄存器提供了对各个IO线的控制方式,通过与或操作、位域操作或位带操作实现高效的位管理。
例如,HAL库中的实现代码如下:
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) { assert_param(IS_GPIO_PIN(GPIO_Pin)); assert_param(IS_GPIO_PIN_ACTION(PinState)); if (PinState != GPIO_PIN_RESET) { GPIOx->BSRR = GPIO_Pin; } else { GPIOx->BSRR = (uint32_t)GPIO_Pin << 16U; } }
该函数通过访问GPIOx的BSRR寄存器,实现对目标位的高效操作。
发表评论
最新留言
关于作者
