2. LED闪烁
任务说明
本案例基于寄存器直接操作方式,使用延时函数控制LED交替亮灭,实现LED闪烁效果。核心目标是掌握循环结构在延时控制中的应用,以及通过寄存器地址操作GPIO输出电平的方法。案例以STM32F103系列单片机为硬件平台,LED接在PC13引脚(板上LED),低电平点亮。
硬件连接
PC13通过330Ω限流电阻连接LED阳极,LED阴极接地。当PC13输出低电平时LED点亮,输出高电平时LED熄灭。
寄存器配置
操作PC13需要配置两个寄存器:GPIOC_CRH(端口配置高寄存器,控制PC8~PC15)和GPIOC_ODR(端口输出数据寄存器)。PC13对应CRH的bit20~23,将其设置为通用推挽输出(CNF=00,MODE=01,即0x1),输出模式为2MHz。ODR寄存器的bit13控制PC13输出电平。
代码实现
以下代码通过寄存器地址直接操作,实现LED以约1秒周期闪烁(亮500ms,灭500ms)。延时函数使用简单的循环递减实现,便于理解循环在延时控制中的作用。
#include "stm32f10x.h"
// 寄存器地址定义
#define GPIOC_CRH (*(volatile unsigned long *)0x40011004)
#define GPIOC_ODR (*(volatile unsigned long *)0x4001100C)
#define RCC_APB2ENR (*(volatile unsigned long *)0x40021018)
// 简单延时函数:循环递减
void delay(unsigned int count)
{
while(count--)
{
// 空循环体,仅消耗CPU周期
}
}
int main(void)
{
// 1. 使能GPIOC时钟(APB2总线)
RCC_APB2ENR |= (1 << 4); // IOPCEN位置1
// 2. 配置PC13为推挽输出,2MHz
GPIOC_CRH &= ~(0xF << 20); // 先清除CNF13和MODE13位
GPIOC_CRH |= (0x1 << 20); // MODE13=01(输出2MHz),CNF13=00(推挽)
// 3. 主循环:LED交替亮灭
while(1)
{
GPIOC_ODR &= ~(1 << 13); // PC13输出低电平 → LED点亮
delay(500000); // 延时约500ms
GPIOC_ODR |= (1 << 13); // PC13输出高电平 → LED熄灭
delay(500000); // 延时约500ms
}
}
代码说明
代码首先通过RCC_APB2ENR寄存器使能GPIOC端口时钟,这是使用GPIO前必须完成的步骤。然后配置GPIOC_CRH寄存器,将PC13设置为推挽输出模式。主循环中通过操作GPIOC_ODR寄存器的bit13来控制LED状态:清零该位输出低电平点亮LED,置位该位输出高电平熄灭LED。每次切换后调用delay函数延时,形成闪烁效果。
编译与烧录
使用Keil MDK或arm-none-eabi-gcc工具链编译。若使用arm-none-eabi-gcc,编译命令如下:
arm-none-eabi-gcc -c -mcpu=cortex-m3 -mthumb led_blink.c -o led_blink.o
arm-none-eabi-ld -T stm32f103.ld led_blink.o -o led_blink.elf
arm-none-eabi-objcopy -O binary led_blink.elf led_blink.bin
其中stm32f103.ld为链接脚本,需根据具体开发板配置Flash和RAM起始地址。烧录时使用ST-Link或J-Link工具将生成的bin文件写入单片机Flash。
验证方法
将程序烧录至开发板后,观察板上LED(PC13)是否以约1秒周期闪烁。若LED正常闪烁,说明寄存器配置和延时函数工作正常。可通过修改delay函数的参数值来改变闪烁频率,例如将参数改为1000000,闪烁周期应变为约2秒,以此验证延时函数对闪烁速度的控制作用。
判定标准
满足以下条件即判定案例通过:
- LED以稳定周期交替亮灭,周期约1秒(允许因主频差异有±30%偏差);
- 修改delay参数后闪烁频率随之变化;
- 代码中所有寄存器地址与STM32F103数据手册一致,无编译错误。