[开发板] 【CW32L031CxTx StartKit评估板测评】4.按键与定时器的使用

[复制链接]
 楼主| yuyy1989 发表于 2023-9-25 15:43 | 显示全部楼层 |阅读模式
#申请原创# @21小跑堂  

按键检测
实现按键检测通常有2种方法:
轮询:通过不断的查询按键电平状态来判断按键是否有按下
中断:按键按下时IO电平变化触发中断,结合电平判断按键状态
接下来用2种方式分别实现按键检测,按键KEY1和KEY2分别控制LED1和LED2,查看原理图可以知道按键未按下时为高电平,按下后为低电平
QQ截图20230924161012.png
轮询方式,通常机械按键按下时不可避免地会有抖动情况发生,一般可以采用延时进行去抖
  1. void led_init()
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStruct = {0};
  4.     __RCC_GPIOB_CLK_ENABLE();
  5.     GPIO_InitStruct.IT = GPIO_IT_NONE;
  6.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  7.     GPIO_InitStruct.Pins = GPIO_PIN_8 | GPIO_PIN_9;
  8.     GPIO_Init(CW_GPIOB, &GPIO_InitStruct);
  9.     GPIO_WritePin(CW_GPIOB,GPIO_PIN_8 | GPIO_PIN_9,GPIO_Pin_RESET);
  10. }

  11. void key_init()
  12. {
  13.     GPIO_InitTypeDef GPIO_InitStruct = {0};
  14.     __RCC_GPIOA_CLK_ENABLE();
  15.     GPIO_InitStruct.IT = GPIO_IT_NONE;
  16.     GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  17.     GPIO_InitStruct.Pins = GPIO_PIN_1 | GPIO_PIN_2;
  18.     GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
  19. }

  20. int32_t main(void)
  21. {
  22.     RCC_HSI_48M_init();
  23.     RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
  24.     RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
  25.     led_init();
  26.     key_init();
  27.     while (1)
  28.     {
  29.         if(GPIO_ReadPin(CW_GPIOA,GPIO_PIN_1) == GPIO_Pin_RESET)
  30.         {
  31.             yuyy_delay_ms(10);
  32.             if(GPIO_ReadPin(CW_GPIOA,GPIO_PIN_1) == GPIO_Pin_RESET)
  33.             {
  34.                 while(GPIO_ReadPin(CW_GPIOA,GPIO_PIN_1) == GPIO_Pin_RESET);
  35.                 GPIO_TogglePin(CW_GPIOB, GPIO_PIN_8);
  36.             }
  37.         }
  38.         if(GPIO_ReadPin(CW_GPIOA,GPIO_PIN_2) == GPIO_Pin_RESET)
  39.         {
  40.             yuyy_delay_ms(10);
  41.             if(GPIO_ReadPin(CW_GPIOA,GPIO_PIN_2) == GPIO_Pin_RESET)
  42.             {
  43.                 while(GPIO_ReadPin(CW_GPIOA,GPIO_PIN_2) == GPIO_Pin_RESET);
  44.                 GPIO_TogglePin(CW_GPIOB, GPIO_PIN_9);
  45.             }
  46.         }
  47.     }
  48. }
运行效果
WeChat_20230925153254 00_00_00-00_00_30.gif
中断方式,CW32L031的GPIO中断可以配置为上升沿或下降沿触发(虽然cw32l031_gpio.h有高低电平的中断参数定义但并无效果,手册中也没写支持电平中断),按键按下时从高电平变为低电平时会触发下降沿中断,CW32L031的中断可以配置滤波功能,通过滤波实现去抖
  1. void key_init()
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStruct = {0};
  4.     __RCC_GPIOA_CLK_ENABLE();
  5.     GPIO_InitStruct.IT = GPIO_IT_FALLING;
  6.     GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  7.     GPIO_InitStruct.Pins = GPIO_PIN_1 | GPIO_PIN_2;
  8.     GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
  9.     GPIO_ConfigFilter(CW_GPIOA,GPIO_PIN_1 | GPIO_PIN_2,GPIO_FLTCLK_RC150K);
  10.     GPIOA_INTFLAG_CLR(bv1| bv2);
  11.     NVIC_EnableIRQ(GPIOA_IRQn);
  12. }

  13. void GPIOA_IRQHandler(void)
  14. {
  15.     if (CW_GPIOA->ISR_f.PIN1)
  16.     {
  17.         GPIOA_INTFLAG_CLR(bv1);
  18.         if(GPIO_ReadPin(CW_GPIOA,GPIO_PIN_1) == GPIO_Pin_RESET)
  19.             GPIO_TogglePin(CW_GPIOB, GPIO_PIN_8);
  20.     }

  21.     if (CW_GPIOA->ISR_f.PIN2)
  22.     {
  23.         GPIOA_INTFLAG_CLR(bv2);
  24.         if(GPIO_ReadPin(CW_GPIOA,GPIO_PIN_2) == GPIO_Pin_RESET)
  25.             GPIO_TogglePin(CW_GPIOB, GPIO_PIN_9);
  26.     }
  27. }

  28. int32_t main(void)
  29. {
  30.     RCC_HSI_48M_init();
  31.     RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
  32.     RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
  33.     led_init();
  34.     key_init();
  35.     while (1)
  36.     {
  37.     }
  38. }

运行效果
WeChat_20230925153304 00_00_00-00_00_30.gif
定时器的使用
CW32L031拥有三个基本定时器(BTIM)两个通用定时器(GTIM)和一个高级定时器(ATIM),先用BTIM做一个控制LED以1Hz闪烁的定时器
  1. void btim1_init()
  2. {
  3.     BTIM_TimeBaseInitTypeDef BTIM_InitStruct = {0};
  4.     __RCC_BTIM_CLK_ENABLE();
  5.     BTIM_InitStruct.BTIM_Mode = BTIM_Mode_TIMER;
  6.     BTIM_InitStruct.BTIM_Period = 50000 - 1;
  7.     BTIM_InitStruct.BTIM_Prescaler = 480 - 1;
  8.     BTIM_TimeBaseInit(CW_BTIM1, &BTIM_InitStruct);
  9.     BTIM_ITConfig(CW_BTIM1, BTIM_IT_OV, ENABLE);
  10.     BTIM_Cmd(CW_BTIM1, ENABLE);
  11.     NVIC_EnableIRQ(BTIM1_IRQn);
  12. }

  13. void BTIM1_IRQHandler(void)
  14. {
  15.     if (BTIM_GetITStatus(CW_BTIM1, BTIM_IT_OV))
  16.     {
  17.         BTIM_ClearITPendingBit(CW_BTIM1, BTIM_IT_OV);
  18.         GPIO_TogglePin(CW_GPIOB, GPIO_PIN_8);
  19.         GPIO_TogglePin(CW_GPIOB, GPIO_PIN_9);
  20.     }
  21. }

  22. int32_t main(void)
  23. {
  24.    
  25.     RCC_HSI_48M_init();
  26.     RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
  27.     RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
  28.     led_init();
  29.     btim1_init();
  30.     while (1)
  31.     {
  32.     }
  33. }
运行效果
WeChat_20230925153312 00_00_00-00_00_30.gif
通用定时器和高级定时器都有PWM输出功能,可以通过调节PWM占空比来调节LED亮度,评估板上的2个LED分别对应GTIM1的CH3和CH4,接下来写个程序使用按键调节LED亮度
  1. void led_init()
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStruct = {0};
  4.     __RCC_GPIOB_CLK_ENABLE();
  5.     PB08_AFx_GTIM1CH3();
  6.     PB09_AFx_GTIM1CH4();
  7.     GPIO_InitStruct.IT = GPIO_IT_NONE;
  8.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  9.     GPIO_InitStruct.Pins = GPIO_PIN_8 | GPIO_PIN_9;
  10.     GPIO_Init(CW_GPIOB, &GPIO_InitStruct);
  11. }
  12. void gtim1_pwm_init()
  13. {
  14.     GTIM_InitTypeDef GTIM_InitStruct = {0};
  15.     __RCC_GTIM1_CLK_ENABLE();
  16.     GTIM_InitStruct.Mode = GTIM_MODE_TIME;
  17.     GTIM_InitStruct.OneShotMode = GTIM_COUNT_CONTINUE;
  18.     GTIM_InitStruct.Prescaler = 48 - 1;
  19.     GTIM_InitStruct.ReloadValue = 1000 - 1;
  20.     GTIM_InitStruct.ToggleOutState = DISABLE;
  21.     GTIM_TimeBaseInit(CW_GTIM1, >IM_InitStruct);
  22.     GTIM_OCInit(CW_GTIM1, GTIM_CHANNEL3, GTIM_OC_OUTPUT_PWM_LOW);
  23.     GTIM_OCInit(CW_GTIM1, GTIM_CHANNEL4, GTIM_OC_OUTPUT_PWM_LOW);
  24.     GTIM_SetCompare3(CW_GTIM1, 0);
  25.     GTIM_SetCompare4(CW_GTIM1, 0);
  26.     GTIM_Cmd(CW_GTIM1, ENABLE);
  27. }
  28. uint16_t pwm = 0;
  29. void GPIOA_IRQHandler(void)
  30. {
  31.     if (CW_GPIOA->ISR_f.PIN1)
  32.     {
  33.         GPIOA_INTFLAG_CLR(bv1);
  34.         if(GPIO_ReadPin(CW_GPIOA,GPIO_PIN_1) == GPIO_Pin_RESET)
  35.         {
  36.             if(pwm<1000-100)
  37.                 pwm += 100;
  38.             else
  39.                 pwm = 1000;
  40.             GTIM_SetCompare3(CW_GTIM1, pwm);
  41.             GTIM_SetCompare4(CW_GTIM1, pwm);
  42.         }
  43.     }

  44.     if (CW_GPIOA->ISR_f.PIN2)
  45.     {
  46.         GPIOA_INTFLAG_CLR(bv2);
  47.         if(GPIO_ReadPin(CW_GPIOA,GPIO_PIN_2) == GPIO_Pin_RESET)
  48.         {
  49.             if(pwm > 100)
  50.                 pwm -= 100;
  51.             else
  52.                 pwm = 0;
  53.             GTIM_SetCompare3(CW_GTIM1, pwm);
  54.             GTIM_SetCompare4(CW_GTIM1, pwm);
  55.         }
  56.     }
  57. }
编译又有2处优先级警告,找到相关代码处加上括号就好了
QQ截图20230925130151.png QQ截图20230923170936.png
运行效果
WeChat_20230925153342 00_00_00-00_00_30.gif
定时器还可以级联使用来实现更长时间幅度的定时,下面尝试用BTIM和GTIM级联实现1秒的定时器,用BTIM的溢出信号作为GTIM的时钟源
  1. void btim1_init()
  2. {
  3.     BTIM_TimeBaseInitTypeDef BTIM_InitStruct = {0};
  4.     __RCC_BTIM_CLK_ENABLE();
  5.     BTIM_InitStruct.BTIM_Mode = BTIM_Mode_TIMER;
  6.     BTIM_InitStruct.BTIM_Period = 1000 - 1;
  7.     BTIM_InitStruct.BTIM_Prescaler = 48 - 1;
  8.     BTIM_TimeBaseInit(CW_BTIM1, &BTIM_InitStruct);
  9.     BTIM_Cmd(CW_BTIM1, ENABLE);
  10. }

  11. void gtim1_counter_init()
  12. {
  13.     GTIM_InitTypeDef GTIM_InitStruct = {0};
  14.     __RCC_GTIM1_CLK_ENABLE();
  15.     GTIM_InitStruct.Mode = GTIM_MODE_COUNTER;
  16.     GTIM_InitStruct.OneShotMode = GTIM_COUNT_CONTINUE;
  17.     GTIM_InitStruct.Prescaler = 1;
  18.     GTIM_InitStruct.ReloadValue = 1000 - 1;
  19.     GTIM_InitStruct.ToggleOutState = DISABLE;
  20.     GTIM_TimeBaseInit(CW_GTIM1, >IM_InitStruct);
  21.     GTIM1_ITRConfig(ITR_SOURCE_BTIM1);   
  22.     GTIM_ITConfig(CW_GTIM1, GTIM_IT_OV, ENABLE);
  23.     GTIM_Cmd(CW_GTIM1, ENABLE);
  24.     NVIC_EnableIRQ(GTIM1_IRQn);
  25. }

  26. void GTIM1_IRQHandler(void)
  27. {
  28.     if (GTIM_GetITStatus(CW_GTIM1, GTIM_IT_OV))
  29.     {
  30.         GTIM_ClearITPendingBit(CW_GTIM1, GTIM_IT_OV);
  31.         GPIO_TogglePin(CW_GPIOB, GPIO_PIN_8);
  32.         GPIO_TogglePin(CW_GPIOB, GPIO_PIN_9);
  33.     }
  34. }
运行效果
WeChat_20230925153356 00_00_00-00_00_30.gif

您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

161

主题

815

帖子

10

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