豌豆爹 发表于 2023-5-18 10:35

基于STM32F1外部触发脉冲计数定时器实验经验分享

STM32F1定时器实验-外部触发脉冲计数
之前我们用外部中断测量了PWM的频率,而外部触发是设置2个定时器,利用按键触发,一个定时器2用来接受外部触发信号并计数,另一个定时器6实时检测按键。
按照这样的思路,我们的按键读取用状态机思想去读取,使定时器6产生10ms的定时中断来实时检测按键并利用状态机设计思想处理按键信号,将PA1设置成输出引脚,设置定时器2的PA0引脚来接收信号,通过按键触发改变标志位来发送电平信号,再定义全局数存放PA0接收脉冲信号次数,最后串口配置。

说实话,状态机思想可以清晰把你的代码逻辑弄清楚,这个是我自己写按键时画的草图:

https://shequ.stmicroelectronics.cn/data/attachment/forum/202305/17/172201vlgjjthsjlilqhvq.jpg

画的只要你自己可以看懂就行


代码讲解
首先我们需要按键的状态,它的状态分为检测,按下,释放,所以定义枚举类型的结构体

[*]/* USER CODE BEGIN PTD */
[*]typedef enum
[*]{
[*]      KEY_CHECK=0,
[*]      KEY_CONFRIM,
[*]      KEY_RELAESE
[*]}KEY_STATE;
[*]/* USER CODE END PTD */
[*]

复制代码

状态变量的定义以及标志位,计数值

[*]/* USER CODE BEGIN PV */
[*]KEY_STATEkeyState=KEY_CHECK;
[*]int Result=0;
[*]uint8_t keyvalue=0;
[*]
[*]/* USER CODE END PV */
[*]

复制代码

对于按键检测,是在TIM6里处理的,选用KEY1即PE3

https://shequ.stmicroelectronics.cn/data/attachment/forum/202305/17/172155mzcnsdns5vydns4s.pngc310f614ea674bd7a36bab52fe7556e9.png (29.32 KB, 下载次数: 0)下载附件昨天 17:21 上传




https://shequ.stmicroelectronics.cn/data/attachment/forum/202305/17/172155vr4rddcicrq2evdi.png

豌豆爹 发表于 2023-5-18 10:35

而之间的状态转移是通过判断电平实现的,按下时为低电平,未按下为高电平,根据我们按下的一个完整过程,我们可以通过switch语句实现我们的整个过程

[*]/* USER CODE BEGIN 4 */
[*]void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
[*]{
[*]      if(htim->Instance==TIM6)//判断是否为TIM6中断
[*]      {
[*]                switch(keyState)
[*]                {
[*]                        case KEY_CHECK://检测状态下
[*]                        {
[*]                              if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//检测按键为低电平
[*]                              {
[*]                                        keyState=KEY_CONFRIM;//确认按下状态
[*]                              }
[*]                              break;
[*]                        }
[*]                        case KEY_CONFRIM://确认按下状态下
[*]                        {
[*]      if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//再次判断
[*]                              {
[*]            keyvalue=1;//改变标志位用于触发脉冲信号
[*]            keyState=KEY_RELAESE;//按下后释放
[*]                              }
[*]         else
[*]                                 {
[*]                                          keyState=KEY_CHECK;//排除抖动干扰或者误判,回到检测
[*]                                 }
[*]                                 break;
[*]                         }
[*]                        case KEY_RELAESE://释放状态下
[*]                        {
[*]                              if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_SET)      //判断按键未按下
[*]                              {
[*]                                        keyState=KEY_CHECK;//回到检测状态
[*]                              //      keyvalue=1;
[*]                              }
[*]                              break;
[*]                        }
[*]                        default: break;
[*]}
[*]                }
[*]      }
[*]/* USER CODE END 4 */
[*]

复制代码

主函数内

[*]/* USER CODE BEGIN 2 */
[*]      HAL_TIM_Base_Start(&htim2);//开启TIM2用于计数
[*]      HAL_TIM_Base_Start_IT(&htim6);//开启TIM6用于按键检测
[*]      printf("Timer counter founction test: \n");//串口起始提示
[*]/* USER CODE END 2 */
[*]
[*]/* Infinite loop */
[*]/* USER CODE BEGIN WHILE */
[*]while (1)
[*]{
[*]    /* USER CODE END WHILE */
[*]
[*]    /* USER CODE BEGIN 3 */
[*]                if(keyvalue==1)//如果为按下状态
[*]                {
[*]                        keyvalue=0;
[*]                        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
[*]                        HAL_Delay(1);
[*]                        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
[*]                        HAL_Delay(1);//发出周期为2ms的脉冲
[*]                        Result=__HAL_TIM_GET_COUNTER(&htim2);//读取计数值
[*]                        printf("Counter:%d.\n",Result);
[*]                }
[*]}
[*]/* USER CODE END 3 */
[*]

复制代码

CUBEMX配置
1.时钟配置外部晶振,主时钟为72MHz

https://shequ.stmicroelectronics.cn/data/attachment/forum/202305/17/172157pasqshqgaxg1rqah.png

https://shequ.stmicroelectronics.cn/data/attachment/forum/202305/17/172158q9fpc9k7qdj67wd9.png

豌豆爹 发表于 2023-5-18 10:36

2.GPIO:选择PA1输出,PE3输入

https://shequ.stmicroelectronics.cn/data/attachment/forum/202305/17/172200a737lw3l7t2n7tsn.png

3.TIM:
TIM2:Clock Source:外部触发

https://shequ.stmicroelectronics.cn/data/attachment/forum/202305/17/172201fz7tymmkb9hyy9xe.png

这时PA0为你的触发引脚

https://shequ.stmicroelectronics.cn/data/attachment/forum/202305/17/172201yvdatvboj3j9hat1.png

TIM6:激活并生成10ms中断

https://shequ.stmicroelectronics.cn/data/attachment/forum/202305/17/172201vawptf4pazzim3z4.png

4.usart设置

https://shequ.stmicroelectronics.cn/data/attachment/forum/202305/17/172202gjtt7t3o8zftdu5j.png

5.Project的设置,

https://shequ.stmicroelectronics.cn/data/attachment/forum/202305/17/172202i7nrnrur7nqnb377.png

还有一个之前没注意,就是在Code Generator一栏中第一个方框里选择第二个:Copy only the necessary library files,要不一个工程就是百八十MB,占内存。

https://shequ.stmicroelectronics.cn/data/attachment/forum/202305/17/172202lklxxpfii0yrrf7i.png
页: [1]
查看完整版本: 基于STM32F1外部触发脉冲计数定时器实验经验分享