我目前正在用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)
,这种做法不安全?有没有更好的,更普遍接受的访问多个器件寄存器的方法,而无需为每个特定的寄存器创建指针?
谢谢你们!这是我的第一篇文章,所以也请告诉我是否有任何事情可以改善我的问题或任何可能有用的信息。
当然。通常的方案是定义一个匹配寄存器布局的结构,并设置一个指向其基地址的指针,虽然这个指针相当于类型安全,并且更好用。 – doynax
在向C中的地址(指针?)添加偏移量时必须小心。如果将4添加到指针32位值,则编译器将添加16.指针算法与数组元素索引的工作方式相同,也就是说,它考虑了元素的大小。 –
你为什么要这样做,而不是使用ST提供的stm32f4xx.h头?更少的错误倾向,完整和简单。 – Clifford