一、硬件
所用开发板为正点原子stm32f103rct6mini板
LED引脚为PA8和PD2,GPIO拉低导通
二、基础知识
因为LED电路有限流电阻和阳极连接3.3v电压,因此这里选择push-pull和open-drain都可以,如果要GPIO有输出高电平的需求则选择push-pull模式。由手册可知,点亮LED需要输出寄存器中的“0”激活 N-MOS 晶体管,将引脚拉至低电平状态(接地)。
三、代码实现
1、使能时钟
查询手册得知PortA和PortD挂载在APB2总线上
RCC宏定义
#define RCC_BASE (0x40021000) // Base address for Reset and Clock Control (RCC)
#define RCC_APB2ENR_OFFSET 0x18 // APB2 peripheral clock enable register
#define RCC_APB2ENR (*(volatile unsigned int *)(RCC_BASE + RCC_APB2ENR_OFFSET)) // RCC APB2 clock enable register
// RCC clock enable bits for GPIOA and GPIOD
#define RCC_APB2ENR_IOPAEN (1 << 2) // Enable clock for GPIOA
#define RCC_APB2ENR_IOPDEN (1 << 5) // Enable clock for GPIOD
时钟使能
// Enable clocks for GPIOA and GPIOD
RCC_APB2ENR |= RCC_APB2ENR_IOPAEN; // Enable clock for GPIOA
RCC_APB2ENR |= RCC_APB2ENR_IOPDEN; // Enable clock for GPIOD
调试
成功打开时钟
2、模式配置
地址宏定义
#define GPIOA_BASE (0x40010800)
#define GPIOD_BASE (0x40011400)
#define GPIO_CRL_OFFSET 0x00
#define GPIO_CRH_OFFSET 0X04
#define GPIO_BSRR_OFFSET 0X10
#define GPIOA_CRH (*(volatile unsigned int *)(GPIOA_BASE + GPIO_CRH_OFFSET))
#define GPIOA_BSRR (*(volatile unsigned int *)(GPIOA_BASE + GPIO_BSRR_OFFSET))
#define GPIOD_CRL (*(volatile unsigned int *)(GPIOD_BASE + GPIO_CRL_OFFSET))
#define GPIOD_BSRR (*(volatile unsigned int *)(GPIOD_BASE + GPIO_BSRR_OFFSET))
#define PA8_PIN 8
#define PD2_PIN 2
#define GPIO_MODE_OUTPUT_2MHZ_PP 0x2
#define GPIO_MODE_OUTPUT_2MHZ_OD 0x6
#define GPIO_PIN_SET(pin) (1 << (pin))
#define GPIO_PIN_RESET(pin) (1 << ((pin) + 16))
配置模式为push-pull(或open-drain),选择低速输出降低功耗
GPIOA_CRH &= ~(0xF << (PA8_PIN - 8) *4);
GPIOA_CRH |= (GPIO_MODE_OUTPUT_2MHZ_PP << (PA8_PIN - 8) * 4);
GPIOD_CRL &= ~(0xF << PD2_PIN * 4);
GPIOD_CRL |= (GPIO_MODE_OUTPUT_2MHZ_PP << PD2_PIN * 4);
或
GPIOA_CRH &= ~(0xF << (PA8_PIN - 8) *4);
GPIOA_CRH |= (GPIO_MODE_OUTPUT_2MHZ_OD << (PA8_PIN - 8) * 4);
GPIOD_CRL &= ~(0xF << PD2_PIN * 4);
GPIOD_CRL |= (GPIO_MODE_OUTPUT_2MHZ_OD << PD2_PIN * 4);
调试
模式配置成功
3、点灯
-
BSy
(位15:0):用于设置引脚。- 每一位(0到15)对应一个GPIO引脚(Px0到Px15)。
- 写入
1
到某个位会将对应引脚设置为高电平(1)。 - 写入
0
没有任何效果,不会改变引脚状态。
-
BRy
(位31:16):用于复位引脚。- 每一位(16到31)对应一个GPIO引脚(Px0到Px15)。
- 写入
1
到某个位会将对应引脚复位为低电平(0)。 - 写入
0
没有任何效果,不会改变引脚状态。
寄存器使用注意事项
- 同时设置和复位:如果同时设置
BSx
和BRx
,BSx
优先级更高。这意味着在同一次写入中,如果某一引脚既设置为高电平又复位为低电平,该引脚最终会被设置为高电平。 - 字模式访问:
BSRR
只能通过字(32位)模式写入,无法按字节或半字写入。 - 通过一个寄存器写入操作,可以在不影响其他引脚状态的情况下,快速改变单个或多个引脚的状态,这在中断等时间敏感的操作中非常有用。
void LED_ON(void) {
GPIOA_BSRR |= GPIO_PIN_RESET(PA8_PIN); // Reset PA8, turn on LED0
GPIOD_BSRR |= GPIO_PIN_RESET(PD2_PIN); // Reset PD2, turn on LED1
}
下载代码成功点亮