本帖最后由 LIZARD925 于 2025-6-22 16:36 编辑
#申请原创# #技术资源#
APM32E030系列使用记录--基本定时器的使用与按键库的移植
此例程在前一个 GPIO使用基础上,加入基本定时器的使用,并整合定时器与GPIO,移植开源程序,通过事件驱动型按键模块,实现按键的长短按功能,开源链接找不到了,但有压缩包,可自行下载查看,部分介绍如图所示:
定时器操作之5ms定时器使用:
本次例程使用基本定时器(TMR6),产生5ms定时中断,定时器的初始化如下所示:- void timer_init(void)
- {
- RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR6); //打开定时器的时钟
- TMR_TimeBase_T TIM_TimeBaseInitStruct; //配置时基单元
- TIM_TimeBaseInitStruct.clockDivision=TMR_CKD_DIV1; //1分频,时钟为72M
- TIM_TimeBaseInitStruct.counterMode=TMR_COUNTER_MODE_UP; //只能向上计数
- TIM_TimeBaseInitStruct.div=50-1; //10k频率下记50个数=5ms
- TIM_TimeBaseInitStruct.period=7200-1; //72M进行7200的分频=10k 0.1ms
- TIM_TimeBaseInitStruct.repetitionCounter=0; //重复计数器,不用
- TMR_ConfigTimeBase(TMR6,&TIM_TimeBaseInitStruct);
- TMR_ClearStatusFlag(TMR6,TMR_COUNTER_MODE_UP);
- TMR_EnableInterrupt(TMR6, TMR_INT_UPDATE); //使能中断
- NVIC_EnableIRQRequest(TMR6_IRQn, 31); //配置NVIC 与优先级
- TMR_Enable(TMR6); //启动定时器
- }
在中断函数中添加IO口的翻转,测试定时器是否设置准确:
- void TMR6_IRQHandler(void)
- {
- if (TMR_ReadIntFlag(TMR6, TMR_INT_FLAG_UPDATE) == SET)
- {
- TMR_ClearIntFlag(TMR6, TMR_INT_FLAG_UPDATE);
- LED1_turn();
- }
- }
按键库的移植
在hardware文件夹下新建一个文件夹,将按键库文件添加进去,并新建一个app文件,存放自己的按键初始化、定时器等函数,如图:
在工程文件中添加此文件夹路径并添加这四个文件,其中,multi_button.c/.h文件暂时不需要修改,我们在 button_app.c 中,添加按键与定时器的初始化
- #include "button_app.h"
- /*初始化按键*/
- void button_key_init(void)
- {
- RCM_EnableAHBPeriphClock(KEY1_GPIO_RCC);
- RCM_EnableAHBPeriphClock(KEY2_GPIO_RCC);
- GPIO_Config_T GPIO_InitStructure;
- GPIO_InitStructure.mode = GPIO_MODE_IN;
- GPIO_InitStructure.pin = KEY1_Pin;
- GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
- GPIO_InitStructure.pupd = GPIO_PUPD_PU; //上拉输入
- GPIO_Config(KEY1_GPIO, &GPIO_InitStructure);
- GPIO_InitStructure.mode = GPIO_MODE_IN;
- GPIO_InitStructure.pin = KEY2_Pin;
- GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
- GPIO_InitStructure.pupd = GPIO_PUPD_PU; //上拉输入
- GPIO_Config(KEY2_GPIO, &GPIO_InitStructure);
- }
- /**读电平**/
- uint8_t read_button1_GPIO()
- {
- return GPIO_ReadInputBit(KEY1_GPIO, KEY1_Pin);
- }
- uint8_t read_button2_GPIO()
- {
- return GPIO_ReadInputBit(KEY2_GPIO, KEY2_Pin);
- }
- /**********/
- /**定时器初始化**/
- void button_timer_init(void)
- {
- RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR6); //打开定时器的时钟
- TMR_TimeBase_T TIM_TimeBaseInitStruct; //配置时基单元
- TIM_TimeBaseInitStruct.clockDivision=TMR_CKD_DIV1; //1分频,时钟为72M
- TIM_TimeBaseInitStruct.counterMode=TMR_COUNTER_MODE_UP; //只能向上计数
- TIM_TimeBaseInitStruct.div=50-1; //10k频率下记50个数=5ms
- TIM_TimeBaseInitStruct.period=7200-1; //72M进行7200的分频=10k 0.1ms
- TIM_TimeBaseInitStruct.repetitionCounter=0; //重复计数器,不用
- TMR_ConfigTimeBase(TMR6,&TIM_TimeBaseInitStruct);
- TMR_ClearStatusFlag(TMR6,TMR_COUNTER_MODE_UP);
- TMR_EnableInterrupt(TMR6, TMR_INT_UPDATE); //使能中断
- NVIC_EnableIRQRequest(TMR6_IRQn, 31); //配置NVIC 与优先级
- TMR_Enable(TMR6); //启动定时器
- }
- void button_timer_callback(void)
- {
- if (TMR_ReadIntFlag(TMR6, TMR_INT_FLAG_UPDATE) == SET)
- {
- TMR_ClearIntFlag(TMR6, TMR_INT_FLAG_UPDATE);
- button_ticks(); //需要周期调用按键处理函数
- }
- }
- /**********/
定时器的回调为自己定义的函数,此时硬件初始化完成;我们还需创建按键,并实现按键的回调函数,
- struct Button btn1; //创建第1个按键
- struct Button btn2; //创建第2个按键
- void button_Init(void)
- {
- button_key_init(); //按键硬件初始化
- button_timer_init(); //按键定时器初始化
- button_init(&btn1, read_button1_GPIO, 0); //初始化按键1按下电平读取状态
- button_init(&btn2, read_button2_GPIO, 0); //初始化按键2按下电平读取状态
- button_attach(&btn1, SINGLE_CLICK, BTN1_PRESS_DOWN_Handler); //短按一下
- button_attach(&btn1, DOUBLE_CLICK, BTN1_PRESS_REPEAT_Handler); //双击一下
- button_attach(&btn1, LONG_RRESS_START, BTN1_LONG_RRESS_START_Handler); //长按
- button_attach(&btn2, SINGLE_CLICK, BTN2_PRESS_DOWN_Handler); //短按一下
- button_attach(&btn2, DOUBLE_CLICK, BTN2_PRESS_REPEAT_Handler); //双击一下
- button_attach(&btn2, LONG_RRESS_START, BTN2_LONG_RRESS_START_Handler); //长按
- button_start(&btn1);
- button_start(&btn2);
-
- }
- void BTN1_PRESS_DOWN_Handler(void* btn)
- {
- LED1_on();
- }
- void BTN1_PRESS_REPEAT_Handler(void* btn)
- {
- LED1_off();
- }
- void BTN1_LONG_RRESS_START_Handler(void* btn)
- {
- LED1_turn();
- }
- void BTN2_PRESS_DOWN_Handler(void* btn)
- {
- LED2_on();
- }
- void BTN2_PRESS_REPEAT_Handler(void* btn)
- {
- LED2_off();
- }
- void BTN2_LONG_RRESS_START_Handler(void* btn)
- {
- LED2_turn();
- }
此时按键全部功能实现,只需在初始化中,调用 button_Init(); 函数,即可实现按键的长短按功能- #include "apm32e030.h" // Device header
- #include "Delay.h"
- #include "LED.h"
- #include "button_app.h"
- int main (void)
- {
- LED_init();
-
- /*按键初始化*/
- button_Init();
-
- while(1)
- {
- }
- }
此时,我们单机按键1,可实现LED的点亮,双击可实现LED的熄灭,长按可实现LED的翻转,按键2同理,此时我们的按键库基本移植完成,此库中还有其它的功能,可根据自己的需求进行相应的更改。
|