定时器原理简单说明:

cubemx 计时功能 cubemx 定时器_cubemx 计时功能


如上图所示,定时器存在3个寄存器,分别是:

计数器寄存器(CNT)

预分频器寄存器(PSC)

自动重载寄存器(ARR)

预分频寄存器的输入频率是时钟树配置的频率,比如输入频率是60MHz,设置预分频器寄存器的值为600-1,则预分频器寄存器输出的频率60MHz/(600-1)=100KHz。

计数器寄存器的输入频率是经过预分频器寄存器分频后的频率。比如输入频率是100KHz,则计数器寄存器每经过(1/100KHz)s计数一次,可以是递增计数也可以是递减计数。如果是递增计数,则当递增到自动重载寄存器所设置的值时,计数器寄存器就会重新清0,再重新计数。

一、定时器中断

1、选择内部时钟

cubemx 计时功能 cubemx 定时器_单片机_02

2、设置预分频寄存器PSC值和自动重载寄存器ARR的值

cubemx 计时功能 cubemx 定时器_arm_03


这里PSC为60-1,ARR为1000-1,则每隔1/(60MHz/(60-1)/(1000-1))=1ms中断一次

3、设置中断

cubemx 计时功能 cubemx 定时器_stm32_04

4、使能中断

HAL_TIM_BASE_START_IT(&htim3);

5、重写中断回调函数

/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
	if(htim->Instance==TIM1){
		HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);//这里的代码根据项目自行修改
	}
}
/* USER CODE END 4 */

二、定时器PWM输出

1、PWM周期设置

PWM周期的设置和定时器中断周期设置一样,上面我们设置了定时器的中断周期为1ms,如按上面设置PSC和ARR,则PWM周期也为1ms。

2、设置PWM占空比(即高电平所占时间/周期)

设置占空比有两种方法:cubemx设置,代码实现

2.1 cubemx设置

cubemx 计时功能 cubemx 定时器_stm32_05


通过cubemx设置pulse值。pulse的取值范围大于0小于等于ARR的值,比如上图的pulse值设置为500,则占空比为(500/1000)=50%。pulse的值其实就是比较寄存器CCRx的值。

cubemx 计时功能 cubemx 定时器_单片机_06


如上图所示,当CCRx=4且计数器寄存器小于4时,OCXREF输出高电平,从这里我们可以知道为什么CCRx的值最大为ARR,若CCRx的值大于ARR,则计数器寄存器的值永远小于CCRx,则定时器一直输出高电平。高电平所占时间也可以这样计算:pulse乘于(预分频器输出频率的倒数),因为计数器是每隔 (预分频器输出频率的倒数) 秒计数的。

2.2代码设置PWM占空比

__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,500);//设置TIM2时钟通道2pwm输出的pulse值为500

3、使能PWM输出

HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);

三、定时器输入捕获

1、选择Input Capture direct mode

cubemx 计时功能 cubemx 定时器_arm_07

2、设置PSC的值

cubemx 计时功能 cubemx 定时器_arm_08

这里建议设置为(60MHz/6)=10MHz。

3、设置为上升沿捕获

cubemx 计时功能 cubemx 定时器_cubemx 计时功能_09

3、设置中断

cubemx 计时功能 cubemx 定时器_寄存器_10

4、使能捕获中断

HAL_TIM_IC_Start_IT(&htim4,TIM_CHANNEL_1);/使能定时器4通道一捕获

5、输入捕获测PWM的周期,高电平所占时间,占空比

系统时钟频率为60MHz,PSC为6-1,则计数器寄存器CNT每隔1/(60MHz/(6-1))秒计数一次。这里的PWM和输入捕获的各种数据按照上文配置。

while循环里的代码

while(1){
	switch(capture_cnt){
			case 0:
				capture_cnt++;
			  __HAL_TIM_SET_CAPTUREPOLARITY(&htim4,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);//设置为高电平捕获
			  HAL_TIM_IC_Start_IT(&htim4,TIM_CHANNEL_1);使能捕获中断
				break;
			case 4:
				pwm_cycle=capture_buf[2]-capture_buf[0];
				printf("Cycle:%.4fms\r\n",pwm_cycle/10000.0); //此处的printf已重定向到串口
			
				high_time=capture_buf[1]-capture_buf[0];
				printf("high_time:%.4fms\r\n",high_time/10000.0);
			
			  duty = (high_time/10000.0)/(pwm_cycle/10000.0);
				printf("duty:%.2f%%\r\n",duty*100);
			
				HAL_Delay(1000);
				capture_cnt=0;
				break;
		}
}

捕获中断函数

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
	if(htim->Instance==TIM4){
				if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){
							switch(capture_cnt){
								case 1:
									capture_buf[0]=__HAL_TIM_GET_COMPARE(htim,	TIM_CHANNEL_1);//获取计数器CNT的值
									__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);
									capture_cnt++;
									break;
								case 2:
									capture_buf[1]=__HAL_TIM_GET_COMPARE(htim,	TIM_CHANNEL_1);
									__HAL_TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);
									capture_cnt++;
									break;
								case 3:
									capture_buf[2]=__HAL_TIM_GET_COMPARE(htim,	TIM_CHANNEL_1);
									HAL_TIM_IC_Stop_IT(htim,TIM_CHANNEL_1);//停止中断
									capture_cnt++;
									break;
								default:
									break;
							}
				}
	}
}

运行后得到如下结果

cubemx 计时功能 cubemx 定时器_stm32_11


从上文可以看出,所输出的周期为1ms,高电平所占时间为0.5ms,占空比为50%,与上文的PWM输出的配置一样。

测量基本思路是:
1.设置TIM4 CH1为输入捕获功能;
2.设置上升沿捕获;
3.使能TIM4 CH1捕获功能;
4.捕获到上升沿后,将此时计数器寄存器的值存入capture_ buf[0] ,改为捕获上升沿;
5.捕获到下降沿后,将此时计数器寄存器的值存入capture
buf[1] ,改为捕获上升沿;
6.捕获到上升沿后,将此时计数器寄存器的值存入capture_ buf[2] ,关闭TIM4 CH1捕获功能;
7.计算: 由于计数器寄存器每隔1/(60MHz/(6-1))秒计数一次,故周期为【(capture
buf[2] - capture_ buf[0])乘于(1/(60MHz/(6-1))】秒,高电平所占时间为【(capture_ buf[1] - capture_ buf[0])乘于(1/(60MHz/(6-1))】秒。