赞
踩
定时器原理简单说明:
如上图所示,定时器存在3个寄存器,分别是:
计数器寄存器(CNT)
预分频器寄存器(PSC)
自动重载寄存器(ARR)
预分频寄存器的输入频率是时钟树配置的频率,比如输入频率是60MHz,设置预分频器寄存器的值为600-1,则预分频器寄存器输出的频率60MHz/(600-1)=100KHz。
计数器寄存器的输入频率是经过预分频器寄存器分频后的频率。比如输入频率是100KHz,则计数器寄存器每经过(1/100KHz)s计数一次,可以是递增计数也可以是递减计数。如果是递增计数,则当递增到自动重载寄存器所设置的值时,计数器寄存器就会重新清0,再重新计数。
这里PSC为60-1,ARR为1000-1,则每隔1/(60MHz/(60-1)/(1000-1))=1ms中断一次
HAL_TIM_BASE_START_IT(&htim3);
/* 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周期的设置和定时器中断周期设置一样,上面我们设置了定时器的中断周期为1ms,如按上面设置PSC和ARR,则PWM周期也为1ms。
设置占空比有两种方法:cubemx设置,代码实现
通过cubemx设置pulse值。pulse的取值范围大于0小于等于ARR的值,比如上图的pulse值设置为500,则占空比为(500/1000)=50%。pulse的值其实就是比较寄存器CCRx的值。
如上图所示,当CCRx=4且计数器寄存器小于4时,OCXREF输出高电平,从这里我们可以知道为什么CCRx的值最大为ARR,若CCRx的值大于ARR,则计数器寄存器的值永远小于CCRx,则定时器一直输出高电平。高电平所占时间也可以这样计算:pulse乘于(预分频器输出频率的倒数),因为计数器是每隔 (预分频器输出频率的倒数) 秒计数的。
__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,500);//设置TIM2时钟通道2pwm输出的pulse值为500
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
这里建议设置为(60MHz/6)=10MHz。
HAL_TIM_IC_Start_IT(&htim4,TIM_CHANNEL_1);/使能定时器4通道一捕获
系统时钟频率为60MHz,PSC为6-1,则计数器寄存器CNT每隔1/(60MHz/(6-1))秒计数一次。这里的PWM和输入捕获的各种数据按照上文配置。
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;
}
}
}
}
运行后得到如下结果
从上文可以看出,所输出的周期为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))】秒。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。