蓝桥杯嵌入式——按键控制LED
一.按键功能简介
M4开发板包含五个按键,其中一个是Reset按键,另外四个是一般的按键。
从原理图可以知道,按键B0-B4都是外接上拉电阻到VDD,在按下时接通GND,所以按键弹出时读取到1,按下读取到0;
使用时只需要将按键相关GPIO初始化,然后读取电平进行操作即可。
二.使用cubeMx做按键初始化
(直接初始化为输入模式,No pull)
void Key_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin : PA0 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pins : PB0 PB1 PB2 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); }
接着需要使用函数读取按键信号,一般来说,需要做按键消抖,但是测试发现不消抖也没有产生问题,这里还是将消抖加上。
unsigned char Key_Scan(void) { if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) { //Key_Delay(10); Key_Val = 8; } else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_RESET) { //Key_Delay(10); Key_Val = 1; } else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET) { //Key_Delay(10); Key_Val = 2; } else if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET) { //Key_Delay(10); Key_Val = 4; } else Key_Val = 0; return Key_Val; } //Key_Delay函数适用于80MHz,实现一次循环延时1ms; void Key_Delay(unsigned int ms) { unsigned int i,j; for(i=0;i<ms;i++) for(j=0;j<8000;j++); }
最后在main函数调用Key_Scan函数即可,这里需要注意按键长按和短按我们赋予其不同的功能,因此逻辑上要做一些判断。
函数入口进来之后,首先读取一个当前的key值,然后再一段时间之后读取新的key'值,这样就能判断出是长按还是短按;
在此基础上,利用par做判断,去分别执行长按和短按的功能。
但是如果直接这样思考,会发现LED在按下(一直按着)能实现长按功能,但是一弹起就会跳跃到实现短按功能;所以需要使用一种锁存的想法
将长按信号确定获取之后,就不允许变到短按信号上。
void Key_Get(void) { unsigned i; Key_Currentval = Key_Scan(); if(Key_Currentval == 0 || (Key_Currentval == ucLed>>4)) goto loop; Key_Delay(1000); Key_Pastval = Key_Scan(); if((Key_Pastval == Key_Currentval)&&(Key_Pastval!=0)) { par = 1; } else if(Key_Pastval != Key_Currentval) par = 0; //按键短按 if(par==0) { if(Key_Currentval==1) ucLed = 0x01; else if(Key_Currentval==2) ucLed = 0x02; else if(Key_Currentval==4) ucLed = 0x04; else if(Key_Currentval==8) ucLed = 0x08; } else if(par==1) { if(Key_Pastval==1) ucLed = 0x10; else if(Key_Pastval==2) ucLed = 0x20; else if(Key_Pastval==4) ucLed = 0x40; else if(Key_Pastval==8) ucLed = 0x80; } loop: { i = i; } }
//Ps:作为新手,我加入了一些不必要的判断语句,认为这样可以在空闲时占用少一点的cpu资源,不知这样是否合理,欢迎讨论。
END
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)