1. GPIO输出控制LED闪烁
任务说明
本案例要求在ARM嵌入式开发板上,通过配置GPIO输出寄存器,控制板载LED以1Hz频率闪烁(即每500ms翻转一次电平)。你需要完成从寄存器配置到延时控制的完整代码编写,并能在开发板上观察到LED的亮灭变化。
硬件连接与寄存器映射
以STM32F407开发板为例,板载LED通常连接在GPIOF的Pin9(或根据实际板卡调整)。本案例使用GPIOF端口,输出引脚为Pin9,低电平点亮LED。系统时钟配置为168MHz,APB2外设时钟为84MHz。
代码实现
以下代码直接操作寄存器完成GPIO配置与LED闪烁控制,不依赖HAL库。延时函数使用简单的循环计数实现,系统时钟168MHz下,内层循环约耗时1μs。
// main.c
#include "stm32f4xx.h"
// 简单延时函数:约延时 ms 毫秒(168MHz主频)
void delay_ms(uint32_t ms) {
uint32_t i, j;
for (i = 0; i < ms; i++) {
// 约168次循环 ≈ 1μs,168000次 ≈ 1ms
for (j = 0; j < 168000; j++) {
__NOP();
}
}
}
void GPIO_Init(void) {
// 1. 使能GPIOF时钟(AHB1总线)
RCC->AHB1ENR |= (1U << 5); // Bit5: GPIOFEN
// 2. 配置PF9为输出模式
GPIOF->MODER &= ~(3U << 18); // 先清零Bits[19:18]
GPIOF->MODER |= (1U << 18); // 设置为01:通用输出模式
// 3. 设置输出类型为推挽(默认即可,此处显式配置)
GPIOF->OTYPER &= ~(1U << 9); // Bit9=0:推挽输出
// 4. 设置输出速度(可选,默认即可)
GPIOF->OSPEEDR &= ~(3U << 18);
GPIOF->OSPEEDR |= (2U << 18); // 50MHz速度
// 5. 无上下拉
GPIOF->PUPDR &= ~(3U << 18);
}
int main(void) {
GPIO_Init();
while (1) {
// 点亮LED:PF9输出低电平
GPIOF->BSRR = (1U << (9 + 16)); // BR9=1,复位Pin9
delay_ms(500);
// 熄灭LED:PF9输出高电平
GPIOF->BSRR = (1U << 9); // BS9=1,置位Pin9
delay_ms(500);
}
}
代码说明
代码首先通过RCC->AHB1ENR的Bit5使能GPIOF端口时钟。然后配置GPIOF->MODER寄存器,将Pin9对应的模式位(Bits[19:18])设置为01,即通用输出模式。在main函数的循环中,通过GPIOF->BSRR寄存器操作Pin9:向BR9写入1使引脚输出低电平(LED点亮),向BS9写入1使引脚输出高电平(LED熄灭)。每次状态切换后调用delay_ms(500)延时500ms,从而实现1Hz的闪烁频率。
编译与烧录
使用ARM Compiler或GCC工具链编译,生成HEX文件后通过ST-Link烧录到开发板。以Keil MDK为例:
// 工程配置要点
1. Device: STM32F407VG
2. 在Options for Target → C/C++ → Define 中添加 USE_STDPERIPH_DRIVER
3. 选择 "Use MicroLIB" 以减小代码体积
4. 编译后点击 LOAD 烧录程序
验证方法
烧录程序后,观察开发板上的LED(PF9连接)是否以1Hz频率闪烁。使用秒表计时10秒,LED应完成约10次完整亮灭循环(允许±1次误差)。若LED常亮或常灭,检查GPIOF时钟使能位是否正确、MODER寄存器配置是否冲突,以及BSRR操作位是否对应Pin9。
判定标准:LED以稳定周期闪烁,亮灭时间各约500ms,且通过示波器测量PF9引脚波形时,高电平持续约500ms,低电平持续约500ms,频率约为1Hz。