【STM32G4】备战蓝桥杯嵌入式---模块配置---TIM_Output_Compare

文章目录

  • 前言
  • TIM_Output_Compare
    • 1.TIM_Output_Compare原理
      • 1.定时器通道的工作模式
      • 2.输出比较模式简介
      • 3.如何输出不同频率的方波
      • 4.如何输出不同频率的可调占空比的PWM波
      • 5.实例(1Hz和2Hz的方波)(由于细节过多,所以在下一节给出可调占空比的实例)
    • 2.Cubemx实现TIM的配置
    • 3.生成工程
      • 1.开启定时器中断
      • 2.更改HAL库TIM的中断总函数
      • 3、中断服务函数
  • 总结


前言

定时器输出比较模式(翻转模式)。
对于输出PWM波,在十一届考了个输出不同频率的可调占空比的PWM波。
对于此,用新板子的话可以采用TIM3、TIM17输出。(建议用新板子准备此题仍然用输出比较模式)
但是考点并不在这,考的是定时器的输出比较模式。

TIM_Output_Compare

1.TIM_Output_Compare原理

对于输出比较的使用,资料还是比较少,我也是查了参考手册。
可能有的地方理解有问题,欢迎指出,谢谢。

1.定时器通道的工作模式

A.输入捕获
B.输出比较
C.PWM 生成(边缘或中间对齐模式)
D.单脉冲模式输出

2.输出比较模式简介

此功能用于控制输出波形,或指示已经过某一时间段。
在输出比较模式下,更新事件 UEV 对 OCxREF 和 OCx 输出毫无影响。同步的精度可以达
到计数器的一个计数周期。
可通过软件随时更新 TIMx_CCRx 寄存器以控制输出波形,前提是未使能预加载寄存器
(OCxPE=“0”,否则仅当发生下一个更新事件 UEV 时,才会更新 TIMx_CCRx 影子寄存
器)。
【STM32G4】备战蓝桥杯嵌入式---模块配置---TIM_Output_Compare_第1张图片
通过上述介绍,可以这样理解,在TIMx的CCRx写入一个值,如果TIMx的CNT与它匹配(相同),会产生电平翻转,如果开启了中断,就会产生中断。

3.如何输出不同频率的方波

取计数周期为200的定时器(计数值从0到200 - 1循环),频率设为f = 80MHz/200/x。(主要看实例,可能文字描述不到位)
记输出PWM1,计数周期为100,频率即2f。
记输出PWM2,计数周期为50,频率即4f。
则令TIMx_CCR1 = 100 * 0.5 = 50,TIMx_CCR2 = 50 * 0.5 = 25。
当发生中断时,若是通道1,则将比较值加50,CCR1 += 50,若是通道2,则将比较值加 25, CCR2 += 25。
则可以得到如下方波。
【STM32G4】备战蓝桥杯嵌入式---模块配置---TIM_Output_Compare_第2张图片
通道2类似,读者可以自己画图检验

4.如何输出不同频率的可调占空比的PWM波

取计数周期为TIMx_Preiod的定时器(计数值从0到TIMx_Preiod - 1循环),频率设为f = 80MHz/TIMx_Preiod/x。(主要看实例,可能文字描述不到位)
记输出PWM1,计数周期为T1。
记输出PWM2,计数周期为T2。
则令初始值TIMx_CCR1 = T1 * PA6_Duty ,TIMx_CCR2 = T2 * PA7_Duty 。(此处是百分比)
当发生中断时,
(若计数周期值为0XFFFF时)
若是通道1,则将比较值CCR1 += T1PA6_Duty ;下一次CCR1 += T1(1 - PA6_Duty);以此循环
若是通道2,则将比较值CCR2 += T2PA7_Duty ;下一次CCR2 += T2(1 - PA7_Duty);以此循环
(由于CCRx的值一直加下去,会溢出,所以不用担心计数器达不到比较寄存器的值)
(若计数周期值不为0XFFFF时)
若是通道1,
则将比较值CCR1 += T1PA6_Duty ;CCR1 %= TIMx_Period;
下一次CCR1 += T1
(1 - PA6_Duty);CCR1 %= TIMx_Period;以此循环
若是通道2,
则将比较值CCR2 += T2PA7_Duty ;CCR2 %= TIMx_Period;
下一次CCR2 += T2
(1 - PA7_Duty);CCR2 %= TIMx_Period;以此循环

则可以得到如下PWM波。

【STM32G4】备战蓝桥杯嵌入式---模块配置---TIM_Output_Compare_第3张图片

5.实例(1Hz和2Hz的方波)(由于细节过多,所以在下一节给出可调占空比的实例)

取计数周期为10000的定时器(计数值从0到10000- 1循环),频率设为1Hz = 80MHz/10000/8000。
记输出PWM1,计数周期为10000,f = 1Hz。
记输出PWM2,计数周期为5000,f = 2Hz。
则令初始值TIMx_CCR1 = 10000* 0.5 ,TIMx_CCR2 = 5000* 0.5 。
当发生中断时,
若是通道1,则将比较值CCR1 += 5000;CCR1 %= 10000;
若是通道2,则将比较值CCR2 += 5000;CCR2 %= 10000;

(如果读者还是不能理解,可以画个波形看看哦)

2.Cubemx实现TIM的配置

由于在做这个实验的时候身边没有示波器,所以采用上升沿和下降沿个数来判断是否成功。
所以我们采用了串口(9600)和LCD帮助测试
TIM3配置如下:
【STM32G4】备战蓝桥杯嵌入式---模块配置---TIM_Output_Compare_第4张图片

【STM32G4】备战蓝桥杯嵌入式---模块配置---TIM_Output_Compare_第5张图片

开启定时器中断
【STM32G4】备战蓝桥杯嵌入式---模块配置---TIM_Output_Compare_第6张图片

3.生成工程

1.开启定时器中断

【STM32G4】备战蓝桥杯嵌入式---模块配置---TIM_Output_Compare_第7张图片

	LCD_Init();
	LCD_Clear(White);
	LCD_SetTextColor(Red);
	
	HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_1);
	HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_2);//合并在一起有bug,我在调车的时候用编码电机也遇到过
	TIM3->CNT = 0;

		sprintf((char *)str, "num1 : %d", num1);
		LCD_DisplayStringLine(Line1, str);
		sprintf((char *)str, "num2 : %d", num2);
		LCD_DisplayStringLine(Line3, str);
		
		sprintf((char *)str, "CNT : %d", TIM3->CNT);
		LCD_DisplayStringLine(Line7, str);
		sprintf((char *)str, "CCR1: %d", TIM3->CCR1);
		LCD_DisplayStringLine(Line8, str);
		sprintf((char *)str, "CCR2: %d", TIM3->CCR2);

以上都是初始化和测试显示函数,不需要多讲

2.更改HAL库TIM的中断总函数

由于输出比较的真的比较少,而且对于用HAL做的资料,本人就没找到。。。
所以查了原子提供的参考手册,然后也是被HAL库的集成度坑了。
首先对于中断标志位:
【STM32G4】备战蓝桥杯嵌入式---模块配置---TIM_Output_Compare_第8张图片
TIMx_SR寄存器,第1.2位保存的通道1、2的捕获和比较中断标志,上面说的很清楚,当在输出比较模式下,计数值和比较值匹配时,该位会置1。

3、中断服务函数

HAL库不熟悉的情况下,本人建议可以记一些比较常用的的寄存器,比如CCRx,SR,CNT等等,以免找不到想要找的函数。
【STM32G4】备战蓝桥杯嵌入式---模块配置---TIM_Output_Compare_第9张图片

void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
	if((TIM3->DIER & (0x1 << 1)) && (TIM3->DIER & (0x1 << 2)))
	{
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)//(TIM3->SR & (0x1 << 1))
		{
			sprintf((char *)arr, "CNT: %d, CCR1: %d\r\n", TIM3->CNT,TIM3->CCR1);
			HAL_UART_Transmit(&huart1, arr,sizeof(arr),50);
			TIM3->CCR1 = TIM3->CCR1 + 5000;
			TIM3->CCR1 = TIM3->CCR1 % 10000;
			num1++;
		}
		
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)//(TIM3->SR & (0x1 << 2))
		{
			sprintf((char *)arr, "CNT: %d, CCR2: %d \r\n", TIM3->CNT,TIM3->CCR2);
			HAL_UART_Transmit(&huart1, arr,sizeof(arr),50);
			TIM3->CCR2 = TIM3->CCR2 + 2500;
			TIM3->CCR2 = TIM3->CCR2 % 10000;
			num2++;
		}

}

对于外条件判断,是因为本人在测试标志位的时候,打印过SR寄存器的显示值。3、4通道未开启中断,但是默认值是1,如果有操作不当可能使用的3、4的中断处理代码,会使程序卡死。所以外条件判断是判断1、2通道是否开启允许中断。
代码测试:
【STM32G4】备战蓝桥杯嵌入式---模块配置---TIM_Output_Compare_第10张图片
【STM32G4】备战蓝桥杯嵌入式---模块配置---TIM_Output_Compare_第11张图片
串口接收到的CNT值大于CCRx值是正常的,因为代码运行需要时间,产生了中断就表示有匹配。
图2可以看到2通道粗略是1通道的两倍,即1Hz和2Hz的方波。


总结

以上就是TIM的输出比较模式的配置以及测试代码。
(本文写了很久,主要资料真的少,点个赞,支持一下,谢谢)
骚年、点个赞再走吧!

在这里插入图片描述

你可能感兴趣的:(stm32,嵌入式)