[APM32E0] APM32E030定时器使用与按键库的移植

[复制链接]
 楼主| LIZARD925 发表于 2025-6-18 23:57 | 显示全部楼层 |阅读模式
本帖最后由 LIZARD925 于 2025-6-22 16:36 编辑

#申请原创# #技术资源#

APM32E030系列使用记录--基本定时器的使用与按键库的移植
此例程在前一个 GPIO使用基础上,加入基本定时器的使用,并整合定时器与GPIO,移植开源程序,通过事件驱动型按键模块,实现按键的长短按功能,开源链接找不到了,但有压缩包,可自行下载查看,部分介绍如图所示:
116857aee964015.png

定时器操作之5ms定时器使用:
本次例程使用基本定时器(TMR6),产生5ms定时中断,定时器的初始化如下所示:
  1. void timer_init(void)
  2. {
  3.         RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR6);        //打开定时器的时钟
  4.         TMR_TimeBase_T TIM_TimeBaseInitStruct;                        //配置时基单元
  5.         TIM_TimeBaseInitStruct.clockDivision=TMR_CKD_DIV1;                //1分频,时钟为72M
  6.         TIM_TimeBaseInitStruct.counterMode=TMR_COUNTER_MODE_UP;        //只能向上计数
  7.         TIM_TimeBaseInitStruct.div=50-1;                                //10k频率下记50个数=5ms
  8.         TIM_TimeBaseInitStruct.period=7200-1;                        //72M进行7200的分频=10k 0.1ms
  9.         TIM_TimeBaseInitStruct.repetitionCounter=0;                //重复计数器,不用
  10.         TMR_ConfigTimeBase(TMR6,&TIM_TimeBaseInitStruct);                               

  11.         TMR_ClearStatusFlag(TMR6,TMR_COUNTER_MODE_UP);
  12.         TMR_EnableInterrupt(TMR6, TMR_INT_UPDATE);                //使能中断                                                                                               
  13.         NVIC_EnableIRQRequest(TMR6_IRQn, 31);                        //配置NVIC 与优先级
  14.         TMR_Enable(TMR6);                                                                //启动定时器
  15. }
在中断函数中添加IO口的翻转,测试定时器是否设置准确:
  1. void TMR6_IRQHandler(void)
  2. {
  3.         if (TMR_ReadIntFlag(TMR6, TMR_INT_FLAG_UPDATE) == SET)
  4.         {
  5.             TMR_ClearIntFlag(TMR6, TMR_INT_FLAG_UPDATE);
  6.             LED1_turn();     
  7.         }
  8. }
234826857b3fa0a18f.png

按键库的移植
在hardware文件夹下新建一个文件夹,将按键库文件添加进去,并新建一个app文件,存放自己的按键初始化、定时器等函数,如图:
69046857b597481f6.png
在工程文件中添加此文件夹路径并添加这四个文件,其中,multi_button.c/.h文件暂时不需要修改,我们在 button_app.c  中,添加按键与定时器的初始化
349436857b661261c1.png
  1. #include "button_app.h"
  2. /*初始化按键*/
  3. void button_key_init(void)
  4. {
  5.         RCM_EnableAHBPeriphClock(KEY1_GPIO_RCC);
  6.         RCM_EnableAHBPeriphClock(KEY2_GPIO_RCC);
  7.         GPIO_Config_T GPIO_InitStructure;
  8.         GPIO_InitStructure.mode = GPIO_MODE_IN;
  9.         GPIO_InitStructure.pin = KEY1_Pin;
  10.         GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
  11.         GPIO_InitStructure.pupd = GPIO_PUPD_PU;                        //上拉输入
  12.         GPIO_Config(KEY1_GPIO, &GPIO_InitStructure);
  13.         GPIO_InitStructure.mode = GPIO_MODE_IN;
  14.         GPIO_InitStructure.pin = KEY2_Pin;
  15.         GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
  16.         GPIO_InitStructure.pupd = GPIO_PUPD_PU;                        //上拉输入
  17.         GPIO_Config(KEY2_GPIO, &GPIO_InitStructure);
  18. }
  19. /**读电平**/
  20. uint8_t read_button1_GPIO()
  21. {
  22.         return GPIO_ReadInputBit(KEY1_GPIO, KEY1_Pin);
  23. }
  24. uint8_t read_button2_GPIO()
  25. {
  26.         return GPIO_ReadInputBit(KEY2_GPIO, KEY2_Pin);
  27. }
  28. /**********/
  29. /**定时器初始化**/
  30. void button_timer_init(void)
  31. {
  32.     RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR6);        //打开定时器的时钟
  33.         TMR_TimeBase_T TIM_TimeBaseInitStruct;                        //配置时基单元
  34.         TIM_TimeBaseInitStruct.clockDivision=TMR_CKD_DIV1;                //1分频,时钟为72M
  35.         TIM_TimeBaseInitStruct.counterMode=TMR_COUNTER_MODE_UP;        //只能向上计数
  36.         TIM_TimeBaseInitStruct.div=50-1;                                //10k频率下记50个数=5ms
  37.         TIM_TimeBaseInitStruct.period=7200-1;                        //72M进行7200的分频=10k 0.1ms
  38.         TIM_TimeBaseInitStruct.repetitionCounter=0;                //重复计数器,不用
  39.         TMR_ConfigTimeBase(TMR6,&TIM_TimeBaseInitStruct);                               

  40.         TMR_ClearStatusFlag(TMR6,TMR_COUNTER_MODE_UP);
  41.         TMR_EnableInterrupt(TMR6, TMR_INT_UPDATE);                //使能中断                                                                                               
  42.         NVIC_EnableIRQRequest(TMR6_IRQn, 31);                        //配置NVIC 与优先级
  43.         TMR_Enable(TMR6);                                                                //启动定时器                                                                                                                                       
  44. }

  45. void button_timer_callback(void)
  46. {
  47.         if (TMR_ReadIntFlag(TMR6, TMR_INT_FLAG_UPDATE) == SET)
  48.     {
  49.         TMR_ClearIntFlag(TMR6, TMR_INT_FLAG_UPDATE);
  50.                 button_ticks();     //需要周期调用按键处理函数
  51.     }                                                                                                               
  52. }
  53. /**********/
定时器的回调为自己定义的函数,此时硬件初始化完成;我们还需创建按键,并实现按键的回调函数,
  1. struct Button btn1;                //创建第1个按键
  2. struct Button btn2;                //创建第2个按键

  3. void button_Init(void)
  4. {
  5.         button_key_init();                //按键硬件初始化
  6.         button_timer_init();        //按键定时器初始化
  7.         button_init(&btn1, read_button1_GPIO, 0);        //初始化按键1按下电平读取状态
  8.         button_init(&btn2, read_button2_GPIO, 0);        //初始化按键2按下电平读取状态
  9.         button_attach(&btn1, SINGLE_CLICK,        BTN1_PRESS_DOWN_Handler);        //短按一下
  10.         button_attach(&btn1, DOUBLE_CLICK,        BTN1_PRESS_REPEAT_Handler);        //双击一下
  11.         button_attach(&btn1, LONG_RRESS_START, BTN1_LONG_RRESS_START_Handler);        //长按
  12.         button_attach(&btn2, SINGLE_CLICK,        BTN2_PRESS_DOWN_Handler);        //短按一下
  13.         button_attach(&btn2, DOUBLE_CLICK,        BTN2_PRESS_REPEAT_Handler);        //双击一下
  14.         button_attach(&btn2, LONG_RRESS_START, BTN2_LONG_RRESS_START_Handler);        //长按
  15.         button_start(&btn1);
  16.         button_start(&btn2);
  17.          
  18. }

  19. void BTN1_PRESS_DOWN_Handler(void* btn)
  20. {
  21.         LED1_on();
  22. }
  23. void BTN1_PRESS_REPEAT_Handler(void* btn)
  24. {
  25.         LED1_off();
  26. }
  27. void BTN1_LONG_RRESS_START_Handler(void* btn)
  28. {
  29.         LED1_turn();
  30. }

  31. void BTN2_PRESS_DOWN_Handler(void* btn)
  32. {
  33.         LED2_on();
  34. }
  35. void BTN2_PRESS_REPEAT_Handler(void* btn)
  36. {
  37.         LED2_off();
  38. }
  39. void BTN2_LONG_RRESS_START_Handler(void* btn)
  40. {
  41.         LED2_turn();
  42. }
此时按键全部功能实现,只需在初始化中,调用 button_Init(); 函数,即可实现按键的长短按功能
  1. #include "apm32e030.h"                  // Device header
  2. #include "Delay.h"
  3. #include "LED.h"
  4. #include "button_app.h"

  5. int main (void)
  6. {
  7.         LED_init();
  8.         
  9.         /*按键初始化*/
  10.         button_Init();
  11.         
  12.         while(1)
  13.         {

  14.         }
  15. }
此时,我们单机按键1,可实现LED的点亮,双击可实现LED的熄灭,长按可实现LED的翻转,按键2同理,此时我们的按键库基本移植完成,此库中还有其它的功能,可根据自己的需求进行相应的更改。
443006857be3fed4c6.png


04.按键处理库.zip

4.22 KB, 下载次数: 1

3-3 APM32E030-定时器-按键库的移植.zip

177.77 KB, 下载次数: 2

雾里闲逛 发表于 2025-6-20 10:02 | 显示全部楼层
按键采集与响应上面,我其实挺犹豫是不是使用中断方式。
感觉使用中断有点浪费,另一方面,中断也在那,不用它也在那。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

19

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部