stm32cubemx HAL库之定时器

定时器原理简单说明:
在这里插入图片描述
如上图所示,定时器存在3个寄存器,分别是:
计数器寄存器(CNT)
预分频器寄存器(PSC)
自动重载寄存器(ARR)

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

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

一、定时器中断

1、选择内部时钟

在这里插入图片描述

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

在这里插入图片描述
这里PSC为60-1,ARR为1000-1,则每隔1/(60MHz/(60-1)/(1000-1))=1ms中断一次

3、设置中断

在这里插入图片描述

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设置pulse值。pulse的取值范围大于0小于等于ARR的值,比如上图的pulse值设置为500,则占空比为(500/1000)=50%。pulse的值其实就是比较寄存器CCRx的值。
在这里插入图片描述
如上图所示,当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

在这里插入图片描述

2、设置PSC的值

在这里插入图片描述这里建议设置为(60MHz/6)=10MHz。

3、设置为上升沿捕获

在这里插入图片描述

3、设置中断

在这里插入图片描述

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;
							}
				}
	}
}

运行后得到如下结果
在这里插入图片描述
从上文可以看出,所输出的周期为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))】秒。

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用STM32F103HAL库中的定时器中断时,可以通过以下步骤来设置中断回调函数: 1. 首先,需要在CubeMX中配置定时器的中断使能。 2. 在生成代码后,打开生成的工程,在`stm32f1xx_hal_conf.h`文件中找到相应的定时器中断宏定义,比如`TIMx_IRQn`和`TIMx_IRQHandler`,其中`x`表示定时器的编号。 3. 找到生成的工程中的`stm32f1xx_it.c`文件,这是用来处理中断的文件。 4. 在`stm32f1xx_it.c`文件中,找到对应定时器的中断处理函数,这个函数的命名通常是`TIMx_IRQHandler`,其中`x`表示定时器的编号。 5. 在中断处理函数中,可以编写你自己的逻辑代码。 具体来说,你可以按照以下步骤进行设置: 1. 在主函数中初始化定时器,并启动定时器。 ```c /* 初始化定时器 */ HAL_TIM_Base_Start_IT(&htimx); // htimx定时器句柄 ``` 2. 在`stm32f1xx_it.c`文件中找到对应定时器的中断处理函数。 ```c void TIMx_IRQHandler(void) { HAL_TIM_IRQHandler(&htimx); // htimx定时器句柄 } ``` 3. 在中断处理函数中添加你的逻辑代码。 ```c void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim == &htimx) { // 在这里添加你的逻辑代码 } } ``` 在上面的代码片段中,`HAL_TIM_PeriodElapsedCallback`是HAL库提供的定时器中断回调函数,当定时器溢出时会自动调用该函数。你可以在这个函数中添加你的逻辑代码来处理定时器中断事件。 注意,上述代码中的`TIMx`需要替换成你使用的定时器的编号,比如`TIM2`、`TIM3`等。另外,还需要根据你的需求进行相应的修改。 希望以上信息对你有帮助!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值