目录

STM32定时器

STM32——定时器

定时器有 捕获脉冲宽度、计算PWM占空比、输出PWM波形以及编码器计数等各种功能。

定时器又能分为

  • 基本定时器:TIM6和TIM7
  • 通用定时器:TIM2、TIM3、TIM4和TIM5
  • 高级定时器:TIM1、TIM8

一、计数和分频

每当一个方波信号的上升沿经过寄存器,计数器就会+1。

对于APB1先进外设总线上的定时器时钟线连接给了基本定时器和通用定时器。APB2则提供给了高级定时器。

我们可以通过修改 APB1 上定时器时钟,来实现恒定波形频率。

例如设置 APB1 时钟频率为 72MHz,也就是当计数器计数到72000 000 次时,1秒钟就过去了。

但是计数器的寄存器有的仅有16bit,也就是做多计数65535个数。

STM32提供了预分配器(PSC)来进行分频,例如:

当预分频器设置为1时,将每两个脉冲分频成一个脉冲,也就是2分频,36Hz;同样的设置为2,就是三分频,24Hz。预分频器也是16bit,能够进行65536分频。

那么对于 72MHz 的时钟频率,最多能够计数约59秒多:

https://i-blog.csdnimg.cn/direct/d3cea55ff9ef408d9a9d453c7d9677a8.png

当然定时器不止一个,能够计数的量就更多。

二、定时原理

自动重装载寄存器(ARR)

当计数器到达与自己的值,会将计数器的值重置为0,此时可以触发一次定时器更新中断。有个细节问题,计数是从0开始的,计数总和要+1。

捕获/比较寄存器值 (CCRx)

用于捕获输入信号的边沿时间或者生成输出信号。

计数器输出频率

https://i-blog.csdnimg.cn/direct/325b2eea8d0b45a397eea95073d8b2a1.png

计数器占空比

https://i-blog.csdnimg.cn/direct/b61135bdab724ee3844a0355ab218ceb.png

三、输出频率、占空比

1. 定时器配置

时钟频率为80:

https://i-blog.csdnimg.cn/direct/7f811031f83e4253af08153c06c76ff8.png

分频器和重装载器分别为4000和100。

https://i-blog.csdnimg.cn/direct/5616ed0a6f514b87ab3319e018558a4d.png

2. 示例

要求 PA6 通道占空比 10%,PA7 通道占空比 10%。

PA6 通道输出频率为 100Hz,PA7 通道输出频率为 200Hz。

B2:按下B2按键,PA6手动模式占空比参数加10%,占空比可调整范围:10%~90%,占空比参数增加到90%后,再次按下B2按键,返回10%。

B3:按下B3按键,PA7手动模式占空比参数加10%,占空比可调整范围:10%~90%,占空比参数增加到90%后,再次按下B3按键,返回10%。

2.1 引脚设置

https://i-blog.csdnimg.cn/direct/5ea5a42d68d944a48d21f3d0a126f20e.png

PA6的频率为100Hz,那么

https://latex.csdn.net/eq?100Hz%3D%5Cfrac%7B80MHz%7D%7B8000*100%7D ,即时钟80M,8000分频,捕获为100.

https://i-blog.csdnimg.cn/direct/8ff0eee57ad548f6aad5206761522550.png

PA7频率为200Hz,分频改 4000就行了,其他不变。

https://i-blog.csdnimg.cn/direct/149d7be5236a4cd9b145b5ea8bd27d10.png

2.2 代码

定义变量输出频率和占空比

//TIM
uint16_t PA6_frq,PA7_frq;
uint8_t PA6_duty=10,PA7_duty=10;

主函数部分,输出频率和占空比的计算。

	HAL_TIM_PWM_Start(&htim16,TIM_CHANNEL_1);
	HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1);
	
    //频率计算
	PA6_frq=80000000/8000/(TIM16->ARR+1);
	PA7_frq=80000000/4000/(TIM17->ARR+1);
    //占空比
	TIM16->CCR1=PA6_duty;
	TIM17->CCR1=PA7_duty;
  /* USER CODE END 2 */

HAL_TIM_PWM_Start() 函数用于启动定时器的PWM(脉冲宽度调制)输出

HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
    TIM_HandleTypeDef *htim: 指向定时器句柄的指针,该句柄包含了定时器的配置信息。
    uint32_t Channel: 定时器的PWM通道,用于指定哪个通道将开始PWM输出

按键实现逻辑:

void Key_Proc(void)
{
	key_val=Key_Scan();
	key_down = key_val &(key_val^key_old);
	key_up = ~key_val &(key_val^key_old); 
	key_old=key_val;
	
	if(key_down==1)
	{
		LCD_Clear(Black);
		LCD_SetBackColor(Black);
		LCD_SetTextColor(White);
		if(++lcd_page==3) lcd_page=0;
	}
	if(key_down==2)
	{    
        //B2使占空比增加10%
		PA6_duty+=10;
        //参数增加到90%时,占空比返回10%
		if(PA6_duty==100) PA6_duty=10;
		TIM16->CCR1=PA6_duty;
	}
	if(key_down==3)
	{
		PA7_duty+=10;
		if(PA7_duty==100) PA7_duty=10;
		TIM17->CCR1=PA7_duty;
	}
		
}

四、输入捕获频率、占空比

1. 原理图

https://i-blog.csdnimg.cn/direct/2b9bfc85f9dc4a30b2265c931f15786c.png

R39和R40两个滑动变阻器,能够调整555定时器的频率。让PA15和PB4设置为了定时器的输入捕获模式。

3. 捕获原理

在输入捕获模式下,当检测到ICx信号上相应的边沿(如上升沿或下降沿)后,定时器的当前计数器值(CNT)被锁存到捕获/比较寄存器(TIMx_CCRx)中。然后根据CCR的值与时钟,计算出频率。

3.1 捕获频率

而学过信号的都知道,频率都是算一个周期的,对于方波信号,就是捕获连续两个上升沿的时间差值即可。

https://latex.csdn.net/eq?T%3D%28CCRx2-CCRx1%29*ARR/CLK

https://latex.csdn.net/eq?f%3D1/T%3DCLK/ARR/%28CCRx2-CCRx1%29

3.2 捕获占空比

要先捕获一个周期的时间差,作为分母。然后捕获一个电平变化的时间差,作为分子。

设 CCRx1 为第一个上升沿,CCRx3 为第二个上升沿,那么周期为 CCRx3-CCRx1。

设 CCRx2 为第一个下降沿,那么电平变化时间差为 CCRx2-CCRx1。

占空比为: https://latex.csdn.net/eq?%5Cfrac%7BCCRx3-CCRx1%7D%7BCCRx2-CCRx1%7D

当然需要两个通道,分别获取上升沿和下降沿。

4. 程序编写

4.1 捕获频率

https://i-blog.csdnimg.cn/direct/e04dee4499874e8f9c6a1dbbde34bdb7.png

TIM2的配置,当然TIM3也是一样的。

https://i-blog.csdnimg.cn/direct/5bd744afec0c460d83215d1adec46461.png

uint32_t cap1,cap2,R39_frq,R40_frq;

HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
/* USER CODE END 2 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM2)
	{
        //获取CCR捕获值
		cap1 = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
		TIM2->CNT=0;
        //计算频率
		R40_frq = 80000000/80/cap1;
		HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);
	}
	if(htim->Instance==TIM3)
	{
		cap2 = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
		TIM3->CNT=0;
		R39_frq = 80000000/80/cap2;
		HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
	}
}

4.2 捕获占空比

https://i-blog.csdnimg.cn/direct/60da12441bd14f46b6110ef6b7418e99.png

设置两个通道,分别上升和下降沿。

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM2)
	{
		if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1)
		{
			cap1 = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);
			cap1_2 = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_2);
			TIM2->CNT=0;
			R40_frq = 80000000/80/cap1;
			R40_duty= (1.0*cap1_2)/(1.0*cap1)*100;
			HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1);
			HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);
		}
		
	}
}