3. 按键控制LED
任务说明
本案例基于中微CMS32系列车规MCU,实现按键控制LED的功能。核心任务是将一个GPIO引脚配置为输入模式(连接按键),另一个GPIO引脚配置为推挽输出(连接LED),通过轮询方式读取按键电平状态,当按键按下时点亮LED,松开时熄灭LED。代码采用寄存器直接操作方式,不依赖厂商库函数,便于理解底层GPIO工作原理。
硬件连接
- 按键:一端接PB0引脚,另一端接GND(按下为低电平)
- LED:正极经限流电阻(约330Ω)接PB1引脚,负极接GND
- MCU:CMS32L051(中微车规级MCU)
GPIO寄存器配置说明
CMS32L051的GPIO相关寄存器包括:端口模式控制寄存器(PMC)、端口输出寄存器(P)、端口输入寄存器(PI)、端口驱动能力寄存器(PDR)等。PB0和PB1属于端口B,其控制寄存器基地址为0x4004_0000。配置流程为:先将PMC寄存器对应位清零设为端口模式,再通过PDR寄存器配置输入/输出方向,最后通过P寄存器输出或PI寄存器读取状态。
代码实现
// main.c
#include "CMS32L051.h"
// 寄存器地址定义(基于CMS32L051用户手册)
#define PB_BASE 0x40040000UL
#define PB_PMC (*(volatile unsigned int *)(PB_BASE + 0x00))
#define PB_PDR (*(volatile unsigned int *)(PB_BASE + 0x04))
#define PB_P (*(volatile unsigned int *)(PB_BASE + 0x08))
#define PB_PI (*(volatile unsigned int *)(PB_BASE + 0x0C))
// 引脚位定义
#define KEY_PIN (1U << 0) // PB0 - 按键输入
#define LED_PIN (1U << 1) // PB1 - LED输出
// 系统时钟初始化(内部RC 8MHz)
static void SystemClock_Init(void)
{
// 使用默认内部高速时钟,无需额外配置
}
// GPIO初始化
static void GPIO_Init(void)
{
// 1. 将PB0和PB1设为端口模式(PMC=0)
PB_PMC &= ~(KEY_PIN | LED_PIN);
// 2. 配置方向:PB0输入(PDR=0),PB1输出(PDR=1)
PB_PDR &= ~KEY_PIN; // PB0设为输入
PB_PDR |= LED_PIN; // PB1设为输出
// 3. 初始状态:LED熄灭(输出高电平,LED负极接GND)
PB_P |= LED_PIN;
}
// 主函数
int main(void)
{
unsigned int key_state;
SystemClock_Init();
GPIO_Init();
while (1)
{
// 读取按键状态(按下为低电平)
key_state = (PB_PI & KEY_PIN) ? 1 : 0;
if (key_state == 0) // 按键按下
{
PB_P &= ~LED_PIN; // 输出低电平,LED点亮
}
else // 按键松开
{
PB_P |= LED_PIN; // 输出高电平,LED熄灭
}
}
}
代码说明
代码首先定义了端口B相关寄存器的地址映射,通过指针方式直接访问。GPIO_Init函数完成端口模式、方向配置,并设置LED初始熄灭状态。主循环中持续读取PB0引脚电平,当检测到低电平时(按键按下),将PB1输出低电平点亮LED;否则输出高电平熄灭LED。由于按键按下时引脚被拉低,松开时通过内部上拉恢复高电平,因此无需额外配置上拉电阻。
编译与烧录
- 使用IAR Embedded Workbench或Keil MDK创建工程,芯片选择CMS32L051;
- 将上述代码保存为main.c并加入工程;
- 编译工程生成HEX文件;
- 使用中微提供的CMS-ICE仿真器或CMS32Prog烧录工具,将HEX文件下载至MCU。
验证方法
完成烧录后,按下按键并观察LED状态。判定标准:
- 按键按下时,LED应立即点亮;
- 松开按键后,LED应立即熄灭;
- 反复按下/松开按键,LED状态跟随按键动作稳定切换,无闪烁或延迟。
若LED状态与按键动作相反,检查按键连接是否接至GND而非VCC;若LED始终不亮,检查限流电阻及LED极性连接。
关键寄存器映射
| 寄存器 | 地址 | 功能 |
|---|---|---|
| PMC | 0x4004_0000 | 端口模式控制(0=端口,1=复用) |
| PDR | 0x4004_0004 | 端口方向(0=输入,1=输出) |
| P | 0x4004_0008 | 输出数据寄存器 |
| PI | 0x4004_000C | 输入电平寄存器 |
本案例通过轮询方式读取按键状态,适用于按键数量少、实时性要求不高的场景。若需多按键或中断响应,可在此基础上扩展为外部中断或定时扫描方式。