在嵌入式系统开发中,LED 指示与按键输入是最常见也是最基础的功能模块。通过这类模块的实践,不仅能掌握 GPIO 控制、定时器/PWM 输出、外部中断与 ADC 输入等外设的应用,还能为后续的复杂系统开发打下坚实基础。
以 MM32F0140 为核心控制器,深入讲解如何实现多种 LED 效果与不同类型的按键检测方法,并分析其各自的适用场景与实现要点。
一、LED 功能实现详解1. 简单 LED 闪烁最基础的 GPIO 输出功能,适用于验证系统运行状态。 c
void LED_Init(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; // 使能 GPIOC 时钟 GPIOC->CRH &= ~(0xF << 20); // 清除 PC13 设置 GPIOC->CRH |= (0x1 << 20); // 推挽输出}void LED_Blink(void) { while (1) { GPIOC->ODR ^= (1 << 13); // 翻转 PC13 delay_ms(500); }}
2. LED 流水灯效果控制多个 LED 按顺序点亮,可结合位运算或数组管理。 c
uint8_t led_pins[] = {1 << 0, 1 << 1, 1 << 2, 1 << 3}; // 假设使用 PC0~PC3void Flow_LED(void) { for (int i = 0; i < 4; i++) { GPIOC->ODR = led_pins; delay_ms(100); }}
3. PWM 控制 LED 亮度使用定时器输出 PWM 波形控制 LED 灯的亮暗变化,实现呼吸灯等效果。 c
void TIM_PWM_Init(void) { RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; GPIOA->CRL &= ~(0xF << 24); // PA6 复用推挽输出 GPIOA->CRL |= (0xB << 24); TIM1->PSC = 72 - 1; // 分频 TIM1->ARR = 1000 - 1; // 周期 TIM1->CCR1 = 500; // 占空比 TIM1->CCMR1 = (6 << 4); // PWM mode 1 TIM1->CCER |= TIM_CCER_CC1E; TIM1->CR1 |= TIM_CR1_CEN;}
二、按键功能实现对比分析1. 独立按键(GPIO 检测)最常见方式,将按键一端接地,另一端接 GPIO 输入口,通过电平判断按下状态。 c
void Key_Init(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; GPIOA->CRL &= ~(0xF << 4); // PA1 输入 GPIOA->CRL |= (0x8 << 4); // 上拉输入}uint8_t Key_Read(void) { return (GPIOA->IDR & (1 << 1)) ? 0 : 1; // 低电平表示按下}
优点:实现简单;
缺点:按键数多时占用 GPIO 多;需做防抖处理。 2. 矩阵按键多个行列组合节省 IO 数量,适用于 4×4 键盘等输入场景。 行连接为输出; 列连接为输入,轮流扫描判断按键位置。
优点:节省引脚;
缺点:代码略复杂、识别效率较低,需扫描逻辑。 3. 基于 ADC 的按键识别多个按键通过不同阻值的电阻电压分压,共用一个 ADC 通道。 c
uint16_t Read_ADC_Key(void) { uint16_t val = ADC_Read(); // 参考前面 ADC 实现 if (val > 100 && val < 200) return 1; // 按键1 else if (val > 300 && val < 400) return 2; // 按键2 return 0;}
优点:节省大量 IO;
缺点:对精度、电源稳定性要求较高;易受温漂、电阻误差影响。
开发建议与实战应用
|