STM32独立按键控制LED流水灯详细解析
创作时间:
作者:
@小白创作中心
STM32独立按键控制LED流水灯详细解析
引用
CSDN
1.
https://blog.csdn.net/caoyang158332/article/details/146243006
在嵌入式开发中,按键控制LED进行不同的显示效果是一个常见的实验。本项目基于STM32单片机,实现四个独立按键控制LED进行不同的灯效变化。
1. 项目背景
在嵌入式开发中,按键控制LED进行不同的显示效果是一个常见的实验。本项目基于STM32单片机,实现四个独立按键控制LED进行不同的灯效变化。
2. 硬件设计
2.1 按键电路原理
从按键电路图来看,每个按键(KEY1-KEY4)都与GPIO端口(PC0-PC3)相连,同时通过220Ω的限流电阻接地。
- 按键按下时,GPIO读取为低电平(0)。
- 按键释放时,GPIO读取为高电平(1)。
2.2 LED控制电路
LED电路由8颗LED(LED1-LED8)组成,每个LED通过510Ω的限流电阻连接到VCC,并受PNP型三极管S8550控制。
- 三极管Q1的基极由LED_SW控制,当LED_SW置低时,三极管导通,LED获得驱动电流。
- 通过LED1至LED8对应的GPIO控制各个LED的亮灭状态。
3. 代码实现
3.1 按键扫描函数
uint8_t key_status(void)
{
if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 0)
{
key_flag = 1;
}
if (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == 0)
{
key_flag = 2;
}
if (HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin) == 0)
{
key_flag = 3;
}
if (HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin) == 0)
{
key_flag = 4;
}
if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1 &&
HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == 1 &&
HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin) == 1 &&
HAL_GPIO_ReadPin(KEY4_GPIO_Port, KEY4_Pin) == 1)
{
if (key_flag == 3 || key_flag == 4)
{
key_flag = 0;
}
}
return key_flag;
}
3.2 LED控制函数
单个LED控制
void led_on(uint8_t led) {
HAL_GPIO_WritePin(LED_SW_GPIO_Port, LED_SW_Pin, GPIO_PIN_RESET);
switch (led) {
case 1: HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); break;
case 2: HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET); break;
case 3: HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); break;
case 4: HAL_GPIO_WritePin(LED4_GPIO_Port, LED4_Pin, GPIO_PIN_RESET); break;
case 5: HAL_GPIO_WritePin(LED5_GPIO_Port, LED5_Pin, GPIO_PIN_RESET); break;
case 6: HAL_GPIO_WritePin(LED6_GPIO_Port, LED6_Pin, GPIO_PIN_RESET); break;
case 7: HAL_GPIO_WritePin(LED7_GPIO_Port, LED7_Pin, GPIO_PIN_RESET); break;
case 8: HAL_GPIO_WritePin(LED8_GPIO_Port, LED8_Pin, GPIO_PIN_RESET); break;
}
}
全部LED控制
void led_all_on(){
HAL_GPIO_WritePin(LED_SW_GPIO_Port,LED_SW_Pin,GPIO_PIN_RESET);
for (int i = 1; i <= 8; i++) {
led_on(i);
}
}
void led_all_off(){
HAL_GPIO_WritePin(LED_SW_GPIO_Port,LED_SW_Pin,GPIO_PIN_RESET);
for (int i = 1; i <= 8; i++) {
led_off(i);
}
}
3.3 流水灯功能
左移流水灯
void led_left(void){
uint8_t j;
HAL_GPIO_WritePin(LED_SW_GPIO_Port, LED_SW_Pin, GPIO_PIN_RESET);
for(uint8_t i = 1; i <= 8; i++){
led_on(i);
HAL_Delay(DELAY_MS);
led_off(i-1);
for (j = 0; j < DELAY_MS / 10; j++) {
HAL_Delay(10);
key_status();
if (key_flag != 1) return;
}
}
}
右移流水灯
void led_right(void){
uint8_t j;
HAL_GPIO_WritePin(LED_SW_GPIO_Port, LED_SW_Pin, GPIO_PIN_RESET);
for(uint8_t i = 8; i > 0; i--){
led_on(i);
HAL_Delay(DELAY_MS);
led_off(i+1);
for (j = 0; j < DELAY_MS / 10; j++) {
HAL_Delay(10);
key_status();
if (key_flag != 2) return;
}
}
}
3.4 红绿灯控制
void led_red(){
HAL_GPIO_WritePin(LED_SW_GPIO_Port,LED_SW_Pin,GPIO_PIN_RESET);
led_on(1); led_on(3); led_on(5); led_on(7);
}
void led_green(){
HAL_GPIO_WritePin(LED_SW_GPIO_Port,LED_SW_Pin,GPIO_PIN_RESET);
led_on(2); led_on(4); led_on(6); led_on(8);
}
4. 主循环
while(1){
key_status();
switch(key_flag){
case 0: led_all_off(); break;
case 1: led_left(); break;
case 2: led_right(); break;
case 3: led_red(); break;
case 4: led_green(); break;
}
}
目前led_left()和led_right()使用for循环逐个点亮LED,并在HAL_Delay过程中不断轮询按键状态。可以优化为:仅当key_flag仍为1或2时继续循环
避免多次调用HAL_GPIO_WritePin(LED_SW_GPIO_Port, LED_SW_Pin, GPIO_PIN_RESET);
void led_left(void) {
uint8_t i = 1;
while (key_flag == 1) {
led_on(i);
HAL_Delay(DELAY_MS);
led_off(i);
i = (i % 8) + 1; // 让LED依次点亮
}
}
使用数组优化LED控制
目前led_on()和led_off()代码冗余,可用数组优化:
GPIO_TypeDef* LED_PORTS[] = {LED1_GPIO_Port, LED2_GPIO_Port, LED3_GPIO_Port, LED4_GPIO_Port,
LED5_GPIO_Port, LED6_GPIO_Port, LED7_GPIO_Port, LED8_GPIO_Port};
uint16_t LED_PINS[] = {LED1_Pin, LED2_Pin, LED3_Pin, LED4_Pin,
LED5_Pin, LED6_Pin, LED7_Pin, LED8_Pin};
void led_on(uint8_t led) {
if (led >= 1 && led <= 8) {
HAL_GPIO_WritePin(LED_PORTS[led - 1], LED_PINS[led - 1], GPIO_PIN_RESET);
}
}
5. 结论
本项目实现了按键控制LED的不同显示模式,涵盖流水灯、红绿灯控制等。整个程序逻辑清晰,能够用于STM32的按键与LED控制实验。希望对大家有所帮助!
6. 优化
增加调试技巧
- 按键消抖
当前代码没有进行按键消抖,可能会导致误触发。可以使用简单的软件消抖,例如:
uint8_t read_key(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
if (HAL_GPIO_ReadPin(GPIOx, GPIO_Pin) == GPIO_PIN_RESET) {
HAL_Delay(10); // 简单消抖
if (HAL_GPIO_ReadPin(GPIOx, GPIO_Pin) == GPIO_PIN_RESET) {
return 1;
}
}
return 0;
}
然后在key_status()中使用read_key(KEY1_GPIO_Port, KEY1_Pin)代替HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)。
添加串口调试信息
在关键位置加入printf输出,有助于调试:
热门推荐
怎样知道狗狗喜不喜欢你?狗狗这些特征都是喜欢你的表现!
小症状不当回事?全科医生为您解析
环境控制系统如何改善建筑健康
石英砂滤料的过滤原理及填充结构详解
活性炭过滤器主要去除水中的什么
福盛隆翡翠教你辨别真假墨翠
福盛隆翡翠专家解读:墨翠的神秘形成过程
红曲红在食品工业中的安全应用:从标准到实践
红曲红降脂效果获科学证实,但安全性问题不容忽视
红曲:天然“血脂清道夫”的功效与风险
红曲红:千年传承与现代科学的完美融合
红曲:家庭健康的秘密武器
《陈情令》魏无羡小纸人揭秘:一个道具的多重魅力
《七日世界》小纸人收容攻略:获取方法与使用技巧详解
洁修哥教你如何检查燃气灶安全隐患
燃气灶故障频发,你还在傻傻叫售后?
燃气灶安全使用全攻略:从选购到日常使用
方太燃气灶打不着火?这两根针是关键!
水蚤养殖方法和注意事项
鱼缸蛋白棉有什么用?
水族箱维护秘籍曝光!养出健康生态水世界!
老广的味道,肇庆独有的裹蒸粽
都说蜂蜜水能止咳,五个常见搭档,还要选择正确的喝法
《黑神话:悟空》电影级叙事揭秘:经典与创新的完美融合
《黑神话·悟空》角色设计爆红:动漫风解析
探索正方形的制作与应用:从手绘到电脑设计的多样技巧
掌握平板绘画技巧,开启数字艺术创作的新篇章
原来镜头也可以戴“眼镜”,作用还千奇百怪呢!
摄影构图技巧:对比构图的原理、应用与误区
兰德曼纳劳卡:冰岛最神秘的地质奇观