[活动] 【极海APM32F407IG Tiny Board开发板测评】4.按键+定时器测试

[复制链接]
1692|9
 楼主| yuyy1989 发表于 2023-7-9 13:27 | 显示全部楼层 |阅读模式
本帖最后由 yuyy1989 于 2023-7-13 20:37 编辑

#申请原创# @21小跑堂
4.按键+定时器测试
先整理了一下开发板支持文件,因为工程只针对APM32F407IG Tiny Board,便将其它板子的文件都删掉了,目录结构变成了这样
QQ截图20230707204312.png
把目录下的几个bsp文件也都加到了工程中

QQ截图20230707204547.png
bsp的头文件有包含main.h,但是我自己创建的这个工程并没有这个文件,就都改成了Board_APM32F407_TINY.h,另外修改的时候发现Board_APM32F407_TINY中的bsp_usart.c中的串口初始化函数中写的还是APM_MINI_COMInit,应该是官方漏改了,不过也在这里给官方提个意见,这些开发板支持函数还是不要加什么MINI TINY的了,不然的话如果要把例程移植到其它板子上还要去替换这些函数名,一不小心就会有像前面提到的那样有漏掉的,如果能保持一致就省事多了

4.1 按键轮询
通过不断的查询按键电平状态来判断按键是否有按下,由于按下键时有可能会抖动所以延时一下再次判断电平,简单实现按键1 2控制LED2 3亮灭的代码

代码示例
  1. #include "Board_APM32F407_TINY.h"
  2. #include "bsp_delay.h"

  3. int main(void)
  4. {
  5.     APM_DelayInit();
  6.     APM_TINY_LEDInit(LED2);
  7.     APM_TINY_LEDInit(LED3);
  8.     APM_TINY_PBInit(BUTTON_KEY1,BUTTON_MODE_GPIO);
  9.     APM_TINY_PBInit(BUTTON_KEY2,BUTTON_MODE_GPIO);
  10.     while (1)
  11.     {
  12.         if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
  13.         {
  14.             APM_DelayMs(30);
  15.             if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
  16.             {
  17.                 while(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET);
  18.                 APM_TINY_LEDToggle(LED2);
  19.             }
  20.         }
  21.         if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
  22.         {
  23.             APM_DelayMs(30);
  24.             if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
  25.             {
  26.                 while(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET);
  27.                 APM_TINY_LEDToggle(LED3);
  28.             }
  29.         }
  30.     }
  31. }

  32. void SysTick_Handler(void)
  33. {
  34.     APM_DelayTickDec();
  35. }
编译烧录查看效果
WeChat_20230707214517 00_00_00-00_00_30.gif
4.2 按键中断
配置按键IO在下降沿时产生中断,由于按下键时有可能会抖动导致多次中断,还是需要延时判断一下按键电平

代码示例
  1. #include "Board_APM32F407_TINY.h"
  2. #include "bsp_delay.h"

  3. uint8_t key1down = 0;
  4. uint8_t key2down = 0;

  5. int main(void)
  6. {
  7.     APM_DelayInit();
  8.     APM_TINY_LEDInit(LED2);
  9.     APM_TINY_LEDInit(LED3);
  10.     APM_TINY_PBInit(BUTTON_KEY1,BUTTON_MODE_EINT);
  11.     APM_TINY_PBInit(BUTTON_KEY2,BUTTON_MODE_EINT);
  12.     while (1)
  13.     {
  14.         if(key1down > 0)
  15.         {
  16.             key1down = 0;
  17.             APM_DelayMs(30);
  18.             if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
  19.                 APM_TINY_LEDToggle(LED2);
  20.         }
  21.         if(key2down > 0)
  22.         {
  23.             key2down = 0;
  24.             APM_DelayMs(30);
  25.             if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
  26.                 APM_TINY_LEDToggle(LED3);
  27.         }
  28.     }
  29. }

  30. void EINT15_10_IRQHandler(void)
  31. {
  32.     if(EINT_ReadIntFlag(KEY1_BUTTON_EINT_LINE))
  33.     {
  34.         key1down = 1;
  35.         EINT_ClearIntFlag(KEY1_BUTTON_EINT_LINE);
  36.     }
  37.     if(EINT_ReadIntFlag(KEY2_BUTTON_EINT_LINE))
  38.     {
  39.         key2down = 1;
  40.         EINT_ClearIntFlag(KEY2_BUTTON_EINT_LINE);
  41.     }
  42. }

  43. void SysTick_Handler(void)
  44. {
  45.     APM_DelayTickDec();
  46. }
编译烧录查看效果
WeChat_20230707214541 00_00_00-00_00_30.gif
4.3 定时器
APM32F407有很多定时器定时器可用
QQ截图20230707215128.png
用timer3做一个闪灯程序,按键切换闪烁速度
timer3是一个16位的定时器,从这张图中可以看到timer3的最大时钟是42M
QQ截图20230708103028.png
之前对定时器时钟理解有误,对于定时器的频率还有额外描述
QQ截图20230713202755.png
再来看看系统初始化时APB1和2的分频系数
QQ截图20230713202821.png
所以timer3的时钟频率为84MHz,将timer3的时钟设置为1分频,预分频系数设置为42,计数周期设置为,1000就能得到一个每0.5ms触发一次的定时器
代码示例
  1. #include "Board_APM32F407_TINY.h"
  2. #include "bsp_delay.h"
  3. #include "apm32f4xx_tmr.h"

  4. volatile uint16_t tim3count = 0;
  5. volatile uint16_t tim3countmax = 200;

  6. void tim3_init()
  7. {
  8.     TMR_BaseConfig_T TMR_TimeBaseStruct;
  9.     RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR3);
  10.     TMR_TimeBaseStruct.clockDivision = TMR_CLOCK_DIV_1;
  11.     TMR_TimeBaseStruct.countMode = TMR_COUNTER_MODE_UP;
  12.     TMR_TimeBaseStruct.division = 41;
  13.     TMR_TimeBaseStruct.repetitionCounter = 0;
  14.     TMR_TimeBaseStruct.period = 999;
  15.     TMR_ConfigTimeBase(TMR3, &TMR_TimeBaseStruct);
  16.     TMR_EnableInterrupt(TMR3,TMR_INT_UPDATE);
  17.     NVIC_EnableIRQRequest(TMR3_IRQn, 0, 0);
  18.     TMR_Enable(TMR3);
  19. }

  20. int main(void)
  21. {
  22.     APM_DelayInit();
  23.     APM_TINY_PBInit(BUTTON_KEY1,BUTTON_MODE_GPIO);
  24.     APM_TINY_PBInit(BUTTON_KEY2,BUTTON_MODE_GPIO);
  25.     tim3_init();
  26.     while (1)
  27.     {
  28.         if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
  29.         {
  30.             APM_DelayMs(30);
  31.             if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
  32.             {
  33.                 while(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET);
  34.                 tim3countmax = 500;
  35.             }
  36.         }
  37.         if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
  38.         {
  39.             APM_DelayMs(30);
  40.             if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
  41.             {
  42.                 while(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET);
  43.                 tim3countmax = 200;
  44.             }
  45.         }
  46.     }
  47. }

  48. void SysTick_Handler(void)
  49. {
  50.     APM_DelayTickDec();
  51. }

  52. void TMR3_IRQHandler(void)
  53. {
  54.     if(TMR_ReadIntFlag(TMR3, TMR_INT_UPDATE) == SET)
  55.     {
  56.         if(tim3count < tim3countmax)
  57.             tim3count++;
  58.         else
  59.         {
  60.             tim3count = 0;
  61.             APM_TINY_LEDToggle(LED2);
  62.             APM_TINY_LEDToggle(LED3);
  63.         }
  64.         TMR_ClearIntFlag(TMR3, TMR_INT_UPDATE);
  65.     }
  66. }
编译烧录查看效果
WeChat_20230708135611 00_00_00-00_00_30.gif
4.4 PWM输出
板子上的2个LED接的是PE5 PE6,可以使用timer9来实现pwm输出
QQ截图20230708140315.png
写个程序两个按键分别控制LED的不同亮度,注意LED是低电平点亮,所以PWM要设置为低电平有效

代码示例
  1. #include "Board_APM32F407_TINY.h"
  2. #include "bsp_delay.h"
  3. #include "apm32f4xx_tmr.h"

  4. void pwm_init()
  5. {
  6.     TMR_BaseConfig_T TMR_TimeBaseStruct;
  7.     TMR_OCConfig_T OCcongigStruct;
  8.     GPIO_Config_T GPIO_ConfigStruct;
  9.    
  10.     RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOE);
  11.    
  12.     GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_5, GPIO_AF_TMR9);
  13.     GPIO_ConfigPinAF(GPIOE, GPIO_PIN_SOURCE_6, GPIO_AF_TMR9);
  14.    
  15.     GPIO_ConfigStruct.pin = GPIO_PIN_5 | GPIO_PIN_6;
  16.     GPIO_ConfigStruct.mode = GPIO_MODE_AF;
  17.     GPIO_ConfigStruct.otype = GPIO_OTYPE_PP;
  18.     GPIO_ConfigStruct.speed = GPIO_SPEED_100MHz;
  19.     GPIO_Config(GPIOE, &GPIO_ConfigStruct);
  20.    
  21.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_TMR9);
  22.     TMR_TimeBaseStruct.clockDivision = TMR_CLOCK_DIV_1;
  23.     TMR_TimeBaseStruct.countMode = TMR_COUNTER_MODE_UP;
  24.     TMR_TimeBaseStruct.division = 83;
  25.     TMR_TimeBaseStruct.repetitionCounter = 0;
  26.     TMR_TimeBaseStruct.period = 999; //频率1k 占空比调节0-1000
  27.     TMR_ConfigTimeBase(TMR9, &TMR_TimeBaseStruct);
  28.    
  29.     OCcongigStruct.mode = TMR_OC_MODE_PWM1;              //PWM模式1,计数小于比较值时输出有效电平
  30.     OCcongigStruct.outputState = TMR_OC_STATE_ENABLE;    //通道使能
  31.     OCcongigStruct.idleState = TMR_OC_IDLE_STATE_SET;    //空闲高电平
  32.     OCcongigStruct.polarity = TMR_OC_POLARITY_LOW;       //有效电平为低电平
  33.     OCcongigStruct.outputNState = TMR_OC_NSTATE_DISABLE; //互补通道失能
  34.     OCcongigStruct.nIdleState = TMR_OC_NIDLE_STATE_RESET;//互补通道空闲电平
  35.     OCcongigStruct.nPolarity = TMR_OC_NPOLARITY_HIGH;    //互补通道有效电平
  36.     OCcongigStruct.pulse = 500;                          //初始50%
  37.     TMR_ConfigOC1(TMR9, &OCcongigStruct);
  38.     TMR_ConfigOC2(TMR9, &OCcongigStruct);
  39.    
  40.     TMR_ConfigOC1Preload(TMR9, TMR_OC_PRELOAD_ENABLE);
  41.     TMR_EnableAutoReload(TMR9);
  42.     TMR_Enable(TMR9);
  43.     TMR_EnablePWMOutputs(TMR9);
  44. }

  45. int main(void)
  46. {
  47.     APM_DelayInit();
  48.     APM_TINY_LEDInit(LED2);
  49.     APM_TINY_LEDInit(LED3);
  50.     APM_TINY_PBInit(BUTTON_KEY1,BUTTON_MODE_GPIO);
  51.     APM_TINY_PBInit(BUTTON_KEY2,BUTTON_MODE_GPIO);
  52.     pwm_init();
  53.     while (1)
  54.     {
  55.         if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
  56.         {
  57.             APM_DelayMs(30);
  58.             if(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET)
  59.             {
  60.                 while(APM_TINY_PBGetState(BUTTON_KEY1) == BIT_RESET);
  61.                 TMR_ConfigCompare1(TMR9,900);
  62.                 TMR_ConfigCompare2(TMR9,900);
  63.             }
  64.         }
  65.         if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
  66.         {
  67.             APM_DelayMs(30);
  68.             if(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET)
  69.             {
  70.                 while(APM_TINY_PBGetState(BUTTON_KEY2) == BIT_RESET);
  71.                 TMR_ConfigCompare1(TMR9,100);
  72.                 TMR_ConfigCompare2(TMR9,100);
  73.             }
  74.         }
  75.     }
  76. }

  77. void SysTick_Handler(void)
  78. {
  79.     APM_DelayTickDec();
  80. }
编译烧录,查看效果
WeChat_20230708170934 00_00_00-00_00_30.gif




tpgf 发表于 2023-8-1 13:13 | 显示全部楼层
这个按键的延时时间是根据经验来的吗
 楼主| yuyy1989 发表于 2023-8-1 13:26 | 显示全部楼层
tpgf 发表于 2023-8-1 13:13
这个按键的延时时间是根据经验来的吗

习惯了,以前前看某个教程是延时的30ms
nawu 发表于 2023-8-1 16:52 | 显示全部楼层
这个是使用的中断模式进行检测的吗
aoyi 发表于 2023-8-1 17:33 | 显示全部楼层
如果是用轮询模式 会不会导致漏掉信号啊
zljiu 发表于 2023-8-2 08:22 | 显示全部楼层
while循环中的时间间隔设定的依据是什么
gwsan 发表于 2023-8-2 09:43 | 显示全部楼层
按键信号没有检测到的概率大不大呢?
 楼主| yuyy1989 发表于 2023-8-2 09:55 | 显示全部楼层
gwsan 发表于 2023-8-2 09:43
按键信号没有检测到的概率大不大呢?

如果按按键的速度超过了每秒30次或者每次按下保持时间短于30毫秒,那漏掉的概率很大,想要精准些的话可以用示波器看一下实际抖动的时间有多长,或者硬件设计加上去抖
tfqi 发表于 2023-8-3 10:48 | 显示全部楼层
为什么我们常用的触摸按键会用着用着就不好用了呢
 楼主| yuyy1989 发表于 2023-8-3 11:26 | 显示全部楼层
tfqi 发表于 2023-8-3 10:48
为什么我们常用的触摸按键会用着用着就不好用了呢

触摸按键应该没那么容易失灵吧,倒是这种机械按键按压次数多了后,触点部分会氧化发黑再按的时候就会接触不良
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

168

主题

826

帖子

10

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