前言: stm23寄存器的地址是由 基地址 和 偏移量 构成,偏移就在寄存器说明的位置,基地址在STM32F4xx参考手册的2.3节可以查找
用公式表示就是:寄存器地址 = 基地址 + 偏移量
下面用操作IO口点亮一个LED为例,写出需要的步骤:
一、查看原理图
可看出,点亮D1,需要控制PF9引脚,即需要对IO的F端口的9号引脚进行操作。
二、为IO端口提供时钟
在stm23中,任何的硬件要正常工作,必须提供时
例如,在IO端口输出配置和输入配置中,输入数据寄存器每隔1个AHB1时钟周期对I/O引脚上的数据进行一次采样,不设置时钟,IO无法正常工作。
这里就要用到RCC AHB1外设时钟使能寄存器(RCC_AHBIENR)
GPIOxEN :IO 端口 x 时钟使能 (IO port x clock enable)
由软件置 1 和清零。
0:禁止 IO 端口 G 时钟
1:使能 IO 端口 G 时钟
三、查找要操作的寄存器的基地址
查找参考手册的2.3节,可以找到时钟控制的寄存器的基地址为0x4002 3800, IO端口的基地址为0x4002 1400.
四、代码
地址宏定义
#define GPIO_F_BASE 0x40021400
#define GPIO_E_BASE 0x40021000
#define RCC_BASE 0x40023800
#define MODER_OFFSET 0x00
#define OTYPER_OFFSET 0x04
#define OSPEEDR_OFFSET 0x08
#define BSRR_OFFSET 0x18
#define PUPDR_OFFSET 0x0c
#define RCC__OFFSET 0x30
寄存器地址定义
volatile unsigned int *F_moder = (unsigned int *)(GPIO_F_BASE + MODER_OFFSET);
volatile unsigned int *F_otyper = (unsigned int *)(GPIO_F_BASE + OTYPER_OFFSET);
volatile unsigned int *F_ospeedr = (unsigned int *)(GPIO_F_BASE + OSPEEDR_OFFSET);
volatile unsigned int *F_pupdr = (unsigned int *)(GPIO_F_BASE + PUPDR_OFFSET);
volatile unsigned int *F_bsrr = (unsigned int *)(GPIO_F_BASE + BSRR_OFFSET);
volatile unsigned int *rcc_ctl = (unsigned int *)(RCC_BASE + RCC__OFFSET);
端口初始化
void PORTF_configuration(void)
{
// 时钟E F使能
*rcc_ctl = 0x3<<4;
// 使PORTF的PF9和PF10输出
*F_moder &= ~(0xf<<18);
*F_moder |= (0x5<<18); // 01为通用输出模式,两个引脚为0101即0x5
// 设为推挽输出,因为0为推挽,该寄存器的复位值也是0,所以直接进行复位
*F_otyper = 0x00;
// 设置端口输出速度
*F_ospeedr &= ~(0xf<<18);
*F_ospeedr |= (0xa<<18); // 1010
// 设置为无上下拉,直接复位
*F_pupdr &= ~(0xf<<18);
}
灯闪烁:
void run_led(void)
{
while(1) {
// 输出
*F_bsrr = 0x3<<25; // reset 复位
delay(500);
*F_bsrr = 0x3<<9; // set 置位
delay(500);
}
}