我目前正在为 STM32F446RE(ARM 编译器)编写 C 语言,由于我想获得嵌入式编程的经验,所以我没有使用任何库。对于我的初始化,我想知道通过将一个指针增加该寄存器与外设基址的偏移量来访问寄存器是否是一个好主意。
void I2C_Init(void)
{
volatile uint32_t *reg_ptr = (uint32_t *) GPIOB_LOC;
*(reg_ptr + GPIOB_MODE_OFFSET) &= ~((0xFU<<16) | (0xFU<<20)); //clear before updating
*(reg_ptr + GPIOB_MODE_OFFSET) |= ((0xAU<<16) | (0xAU<<20)); //set pins 8, 9, 10, 11 to alt func
*(reg_ptr + GPIOB_OTYPE_OFFSET) &= ~(0xFU<<8); //no types
*(reg_ptr + GPIOB_OSPEED_OFFSET) &= ~((0xFU<<16) | (0xFU<<20)); //clear before updating
*(reg_ptr + GPIOB_OSPEED_OFFSET) |= ((0x5U<<16) | (0x5U<<20)); //set to normal speed (will get overriden by alt func)
*(reg_ptr + GPIOB_PUPD_OFFSET) &= ~((0xFU<<16) | (0xFU<<20)); //no pull up or pull down
*(reg_ptr + GPIOB_AFH_OFFSET) &= ~0xFFFFU; //clear before updating
*(reg_ptr + GPIOB_AFH_OFFSET) |= 0x4444U; //set pins 8, 9, 10, 11 to alt func 4 (i2c1 & i2c2 SCL and SDA respectively)
}
在我的头文件中:
#define GPIOB_LOC 0x40020400UL //base
#define GPIOB_MODE_OFFSET (0x00)
#define GPIOB_OTYPE_OFFSET (0x04)
#define GPIOB_OSPEED_OFFSET (0x08)
#define GPIOB_PUPD_OFFSET (0x0C)
#define GPIOB_AFH_OFFSET (0x24)
这种做法不安全吗?是否有更好、更普遍接受的方法来访问多个设备寄存器,而无需为每个特定寄存器创建指针?
谢谢大家!这是我的第一篇文章,所以如果我可以做些什么来改进我的问题或有任何更多有用的信息,请告诉我。
最佳答案
如果偏移量是基于字节的,则它不安全。
向 uint32_t *reg_ptr
添加类似 0x04
的内容将导致生成的地址引用比实际值大四个 uint32_t
值的偏移量在 reg_ptr
中 - 不大于四个字节。
例如,将 0x04
添加到 uint32_t *
指针值 0x40020400UL
将得到实际的指针值 0x40020410UL
> 并且不是预期的0x40020404UL
。
关于我可以/应该通过单个指针访问多个设备寄存器吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42306438/