一、实验要求
- 了解 STM32F103C8T6 最小系统核心板的基本引脚及 GPIO 资源。
- 使用 GPIOA、GPIOB、GPIOC 三个端口分别控制 3 个 LED,LED 轮流闪烁,每个状态保持约 1 秒。
- 采用寄存器方式完成 GPIO 初始化和 LED 控制。
- 使用 Keil 建立工程并完成编译、下载和板级验证。
- 将开发板自带 PC13 LED 加入流水灯效果。
二、硬件与引脚选择
| LED | MCU 引脚 | GPIO 配置 | 点亮逻辑 |
|---|---|---|---|
| LED1 | PA0 | 推挽输出 | 高电平亮 |
| LED2 | PB0 | 推挽输出 | 高电平亮 |
| LED3 | PC13(板载) | 推挽输出 | 低电平亮 |
常见 STM32F103C8T6 Blue Pill 开发板的板载 LED 连接在 PC13,并且通常采用低电平点亮。
三、主要寄存器说明
1. RCC_APB2ENR
用于开启 GPIO 外设时钟。
- bit2:IOPAEN,GPIOA 时钟使能
- bit3:IOPBEN,GPIOB 时钟使能
- bit4:IOPCEN,GPIOC 时钟使能
RCC->APB2ENR|=(1U<<2)|(1U<<3)|(1U<<4);2. GPIOA->CRL
PA0 位于 GPIOA 低 8 位,因此使用 CRL 配置。PA0 对应 bit0~bit3。
设置 MODE0=01、CNF0=00,即 10 MHz 通用推挽输出。
3. GPIOB->CRL
PB0 同样使用 CRL:
GPIOB->CRL&=~(0xFU<<0);GPIOB->CRL|=(0x1U<<0);4. GPIOC->CRH
PC13 属于 GPIOC 高 8 位,因此使用 CRH。PC13 对应 CRH 的 bit20~bit23:
GPIOC->CRH&=~(0xFU<<20);GPIOC->CRH|=(0x1U<<20);5. BSRR 和 BRR
BSRR 用于将 GPIO 位置高,BRR 用于将 GPIO 位置低。
四、程序运行流程
开始 ↓ 开启 GPIOA/B/C 时钟 ↓ 配置 PA0、PB0、PC13 为推挽输出 ↓ 初始化 SysTick,产生 1 ms 节拍 ↓ PA0 LED 点亮 1 秒 ↓ PB0 LED 点亮 1 秒 ↓ PC13 LED 点亮 1 秒 ↓ 返回 PA0 ↓ 循环运行五、代码实现
#include"stm32f10x.h"/* * STM32F103C8T6 寄存器方式三色流水灯 * * LED1 : PA0 -> 外接LED,高电平亮 * LED2 : PB0 -> 外接LED,高电平亮 * LED3 : PC13 -> Blue Pill板载LED,低电平亮 * * 流水顺序: * PA0亮1秒 -> PB0亮1秒 -> PC13亮1秒 -> 循环 *//* LED引脚定义 */#defineLED1_PIN(1U<<0)/* PA0 */#defineLED2_PIN(1U<<0)/* PB0 */#defineLED3_PIN(1U<<13)/* PC13 *//* 毫秒计数 */volatileuint32_tg_ms=0;/* SysTick中断 */voidSysTick_Handler(void){g_ms++;}/* 毫秒延时 */voidDelay_ms(uint32_tms){uint32_tstart=g_ms;while((g_ms-start)<ms){/* 等待 */}}/* GPIO初始化 */voidGPIO_Init(void){/* * 开启GPIOA、GPIOB、GPIOC时钟 * * APB2ENR: * bit2 = IOPAEN * bit3 = IOPBEN * bit4 = IOPCEN */RCC->APB2ENR|=(1U<<2)|(1U<<3)|(1U<<4);/* * PA0配置 * * CRL bit0~3控制PA0 * * MODE0 = 01 * CNF0 = 00 * * 即: * 10MHz通用推挽输出 */GPIOA->CRL&=~(0xFU<<0);GPIOA->CRL|=(0x1U<<0);/* * PB0配置 * * CRL bit0~3控制PB0 */GPIOB->CRL&=~(0xFU<<0);GPIOB->CRL|=(0x1U<<0);/* * PC13配置 * * CRH bit20~23控制PC13 * * MODE13 = 01 * CNF13 = 00 * * 即: * 10MHz通用推挽输出 */GPIOC->CRH&=~(0xFU<<20);GPIOC->CRH|=(0x1U<<20);/* * 上电后全部熄灭 *//* PA0输出高电平 */GPIOA->BSRR=LED1_PIN;/* PB0输出高电平 */GPIOB->BSRR=LED2_PIN;/* PC13输出高电平,板载LED熄灭 */GPIOC->BSRR=LED3_PIN;}/* 三个LED全部熄灭 */voidLED_All_Off(void){/* PA0高电平 */GPIOA->BSRR=LED1_PIN;/* PB0高电平 */GPIOB->BSRR=LED2_PIN;/* PC13高电平 */GPIOC->BSRR=LED3_PIN;}/* LED1亮 */voidLED1_On(void){LED_All_Off();/* PA0低电平 */GPIOA->BRR=LED1_PIN;}/* LED2亮 */voidLED2_On(void){LED_All_Off();/* PB0低电平 */GPIOB->BRR=LED2_PIN;}/* LED3亮 */voidLED3_On(void){LED_All_Off();/* * PC13板载LED低电平点亮 */GPIOC->BRR=LED3_PIN;}/* 主函数 */intmain(void){/* GPIO初始化 */GPIO_Init();/* * SysTick配置 * * 每1ms产生一次中断 */SysTick_Config(SystemCoreClock/1000U);while(1){/* PA0 LED亮1秒 */LED1_On();Delay_ms(1000);/* PB0 LED亮1秒 */LED2_On();Delay_ms(1000);/* PC13 LED亮1秒 */LED3_On();Delay_ms(1000);}}六、板级验证
程序下载成功后:
- PA0 对应 LED 点亮约 1 秒。
- PA0 熄灭,PB0 LED 点亮约 1 秒。
- PB0 熄灭,PC13 板载 LED 点亮约 1 秒。
- PC13 熄灭,重新回到 PA0。
- 程序持续循环。
七、实验总结
通过本实验熟悉了 STM32F103C8T6 GPIO 的寄存器操作流程。程序从 RCC 时钟开启、GPIO 模式配置到输出电平控制逐步完成 LED 控制,没有依赖 HAL GPIO 接口。
实验中比较重要的一点是不同 LED 的有效电平可能不同。普通外接 LED 根据实际接线确定亮灭逻辑,而 Blue Pill 常见的 PC13 板载 LED 通常为低电平点亮,因此程序需要单独处理 PC13。
使用 SysTick 建立 1 ms 时间基准,再通过毫秒计数实现 1 秒切换,可以避免单纯使用空循环造成的延时不稳定,也方便后续扩展不同流水速度和显示模式。