基于cumbmx的定时器介绍与实例
前言:本篇将介绍定时器的基本功能与使用方法,并以超声波传感器作为实例来展示它的应用
所需材料:stm32单片机,stm32cumbmx软件,HC_SR04,CH340
关于串口通信USART的使用方法,这里不再论述
1.什么是定时器?
顾名思义,它的功能是定时。比如可以用它来输入捕获,定时采集AD数据等。
stm32的定时器2和5是高级定时器,有32位,即可以数^32-1个数。
而普通寄存器只有16位,可以数2^16-1G个数
2.三个寄存器的介绍
寄存器的功能是存储二进制代码,它是由具有存储功能的[触发器](https:/组合起来构成的。
-
PSC:预分频器寄存器,可以将时钟频率进行分频,只能取整数(1-65535)
-
CNT:计数器寄存器,每个周期增加一位,从0开始递增,当CNT的值等于ARR时,便会生成事件,并把CNT寄存器清零,完成一次循环过程
-
ARR:自动重载寄存器,告诉CNT应该计数到多少,当CNT计数到ARR时将重新开始计数
补充:CCR是捕获比较寄存器,它是一个数
3.工作原理介绍
f = f c l k ( A R R + 1 ) ( P S C + 1 ) f=\frac{fclk}{(ARR+1)(PSC+1)} f=(ARR+1)(PSC+1)fclk
fclk代表的是单片机的时钟频率,fclk除以(PSC+1)表示分频后的单片机时钟频率,之所以加一是因为PSC从0开始计数。
f代表的是一秒钟内数完ARR的次数。
当定时器启动后,计数寄存器的初值是0,每过一次分频后的时钟周期之后,计数寄存器的值就加1。
4.在cumbmx上的具体操作
- 外部高速晶振,时钟树等基本配置不再赘述
- 打开定时器2,开启输入捕获
- 使能中断
- 开启USART1,便于将采集到的数据显示在电脑上
-
生成代码
-
定义一些变量
uint8_t RxData[2]; uint16_t AD_Value = 0; float Temp = 0; uint8_t cTemp[20]; uint32_t capture_cnt = 0; uint32_t capture_value1, capture_value2; uint32_t pwm_cycle,hightime; uint64_t duty; float distance = 0; double high_time; double low_time; double time; float freq; uint32_t cnt_buf[3];
-
在while(1)中加入这段代码
-
HAL_UART_Receive_IT(&huart1,(uint8_t *)RxData,sizeof(RxData));//串口接收 switch(capture_cnt) { case 0: capture_cnt++; //设置TIM3通道1捕获上升沿 __HAL_TIM_SET_CAPTUREPOLARITY( &htim2 , TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); //开启TIM3捕获中断模式 HAL_TIM_IC_Start_IT( &htim2 , TIM_CHANNEL_1 ); break; case 3: //计算高电平计数值(TIM3计数器频率1MHz) if(capture_value2 >= capture_value1) hightime = capture_value2 - capture_value1; if(capture_value2 < capture_value1) { hightime = capture_value2 + (0xffff- capture_value1); } //根据公式计算距离 hightime/1000000.0为高电平时间 distance = hightime/10000.0*340/2.0; printf("%8.3f",distance); capture_cnt = 0; break; } //当接收到00命令时,进行测距,给trig一个高电平 if(RxData[0]=='0'&&RxData[1]=='0'){ HAL_GPIO_WritePin( GPIOA, GPIO_PIN_7,GPIO_PIN_SET); HAL_Delay(1); HAL_GPIO_WritePin( GPIOA, GPIO_PIN_7,0); RxData[1]='1'; }
-
写下定时器中断
void HAL_TIM_IC_CaptureCallback( TIM_HandleTypeDef *htim ) { if( TIM2 == htim->Instance ) { if(HAL_TIM_ACTIVE_CHANNEL_1 == htim->Channel) { switch(capture_cnt){ case 1: //获取当前计数值 capture_value1 = __HAL_TIM_GET_COMPARE( htim, TIM_CHANNEL_1 ); //设置捕获下降沿 // TIM_SET_CAPTUREPOLARITY( htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); __HAL_TIM_SET_CAPTUREPOLARITY( htim, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); capture_cnt++; break; case 2: //获取当前计数值 capture_value2 = __HAL_TIM_GET_COMPARE( htim, TIM_CHANNEL_1 ); //停止输入捕获模式 HAL_TIM_IC_Stop_IT( htim, TIM_CHANNEL_1); capture_cnt++; break; default: break; } } } }
- 烧录即可利用超声波测距