本帖最后由 野机工程师 于 2025-12-17 14:10 编辑
注:文章结尾附本文章源码、原理图 资料链接
概述:本文介绍了gokit3的板载按键、按键原理,以及移植官方GOkit3 HAL库的驱动按键状态机实现长短按的功能
一、key按键的原理
Key原理图:
截取《gokit3功能板原理图V3.0.PDF》第3页的 The Key 部分。
上拉电阻(R25, R26,R27):讲解 R25 (1K) 的作用。说明默认状态下按键引脚是 高电平 (3.3V),按下后接地变为 低电平 (0V) —— 即“低电平有效”。
如果STM32的GPIO口检测是 0 (RESET) -> 代表按键被按下。
如果STM32的GPIO口检测是 1 (SET) -> 代表按键松开。
二、Gokit3板载的按键介绍
原理图如上:因为这里按键是放在SOC功能板上,然后又通过排针与MCU核心板相连,所以可以得到这三个按键响应的GPIO口
Key1 -- PA8
Key2 -- PB10
Key3 -- PA1
实物图
三、机智云按键驱动移植
我们选择用官方的按键驱动源码移植到我们自己的工程。官方的驱动按键代码方便好用,直接拿来用就可以了
1、把官方key源码添加进自己的工程文件(这里官方的源码可以从机智云官网生成数据点后下载MCU源码,也可以直接看我的链接里面的资料直接下载即可)
为了实现长短按功能,我们不重复造轮子,直接移植机智云官方提供的高质量按键驱动。该驱动采用状态机 (Finite State Machine) 思想,通过定时器轮询按键状态,效率极高
2、打开keil工程添加进工程
这里注意添加一下头文件引用路径
3、因为此驱动主要逻辑是状态机检测按键,所以这里要先配置一个Tim2定时器中断作为时钟源
打开CubeMx然后开始配置定时器
这里配置1ms的定时器中断驱动需要一个精准的时间基准来判断“按下了多久”。我们使用 TIM2。 Clock Source: Internal Clock。 Prescaler (预分频): 72 - 1 (假设主频72MHz)。 Counter Period (重装载值): 1000 - 1。
计算公式:72MHz / 72 / 1000 = 1000Hz = 1ms
记得打开定时器的NVIC中断配置
在 NVIC Settings 选项卡中,勾选 TIM2 global interrupt,开启中断!
4、配置按键用到的GPIO
这里GOkit3板载的按键可以通过原理图看到所用的3个按键用到的GPIO口
Key1 -- PA8
Key2 -- PB10
Key3 -- PA1
5、通过CubeMX配置对应按键GPIO口
为输入模式根据前面的引脚关系,在 CubeMX 中将 PA8, PB10, PA1 配置为 GPIO_Input。 Pull-up/Pull-down:选择 No Pull(因为板子上已经有外部上拉电阻了,如果板子没电阻则需选 Pull-up)
点击生成代码,打开工程
四、实验:长短按实现切换RGB灯的效果
这里分别对这个代码驱动的三个按键的长按短按进行驱动测试
1、先封装一个函数,用于开启定时器的计时与溢出中断void timerInit(void) { HAL_TIM_Base_Start_IT(&htim2); }
2、编写定时器2的中断回调函数,给key实现长短按提供时钟时基
在里面添加keyHandle(); 这个驱动提供的函数,在内部会计算按键的长短时间
//编写定时器中断回调函数 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim==&htim2) { keyHandle(); } }
在此处定义和**即可
3、定义各按键的短按长按回调函数,这样想要的实现的逻辑就可以在此回调函数中编写代码即可,非常方便
这是本驱动最方便的部分,你不需要在主循环里写 if(key==0),只需要定义好“按下去要干什么”的函数(回调函数)即可。
Key1短按回调函数 void key1ShortPress(void) { } Key1长按回调函数 void key1LongPress(void) { } Key2短按回调函数 void key2ShortPress(void) { } Key2长按回调函数 void key2LongPress(void) { } void key3ShortPress(void) { } void key3LongPress(void) { }
写在此处即可
4、key初始化函数与调用keyinit来创建按键与定义对应的按键
也就是说
我们需要告诉驱动,KEY1 对应哪个引脚,以及它对应的回调函数是谁
void keyInit(void) { /* Key parameter initialization*/ keyCategory_t keys[KEY_NUM]={ [KEY1] = { .fsm.keyGpio.keyPort = KEY1_GPIO_Port, .fsm.keyGpio.keyPin = KEY1_Pin, //Key1 State Machine Init .fsm.keyShield = ENABLE, .fsm.keyDownLevel = Bit_RESET, //Key1 Callback function init .func.ShortPressCb = key1ShortPress, .func.longPressCb = key1LongPress, }, [KEY2] = { .fsm.keyGpio.keyPort = KEY2_GPIO_Port, .fsm.keyGpio.keyPin = KEY2_Pin, //Key2 State Machine Init .fsm.keyShield = ENABLE, .fsm.keyDownLevel = Bit_RESET, //Key2 Callback function init .func.ShortPressCb = key2ShortPress, .func.longPressCb = key2LongPress, }, [KEY3] = { .fsm.keyGpio.keyPort = KEY3_GPIO_Port, .fsm.keyGpio.keyPin = KEY3_Pin, //Key2 State Machine Init .fsm.keyShield = ENABLE, .fsm.keyDownLevel = Bit_RESET, //Key2 Callback function init .func.ShortPressCb = key3ShortPress, .func.longPressCb = key3LongPress, }, }; keyParaInit(keys); }
5、主函数调用定时器初始化函数与按键key初始化函数
6、实现想要的逻辑,例如我想要短按key1,实现亮RGB红灯,长按key1,亮绿灯,短按key2,亮绿灯,长按key2,亮白灯,短按key3关闭灯光;
在对应按键的回调函数里写逻辑即可,非常方便
void key1ShortPress(void) { ledRgbControl(255,0,0); //亮红灯 }
7、编译烧录之后
通过本实验,我们不仅掌握了Gokit3的按键硬件原理,更重要的是学会了“注册回调”这种高级的编程思维。这种方式将“按键检测”和“业务逻辑”完全解耦,以后想修改按键功能,只需要改回调函数里的代码,完全不用动驱动层,非常适合后续接入机智云复杂的配网逻辑。
本文到此结束,谢谢大家!
源码、原理图资料链接
原理图:
链接: https://pan.baidu.com/s/19mmg4zj4c9RA-ejn64NxfQ?pwd=WPC1 提取码: WPC1
源码:
链接: https://pan.baidu.com/s/1wqErf1tXGLQYLwW7y4UNww?pwd=WPC1 提取码: WPC1
|