定时器输出比较模式(翻转模式)。
对于输出PWM波,在十一届考了个输出不同频率的可调占空比的PWM波。
对于此,用新板子的话可以采用TIM3、TIM17输出。(建议用新板子准备此题仍然用输出比较模式)
但是考点并不在这,考的是定时器的输出比较模式。
对于输出比较的使用,资料还是比较少,我也是查了参考手册。
可能有的地方理解有问题,欢迎指出,谢谢。
A.输入捕获
B.输出比较
C.PWM 生成(边缘或中间对齐模式)
D.单脉冲模式输出
此功能用于控制输出波形,或指示已经过某一时间段。
在输出比较模式下,更新事件 UEV 对 OCxREF 和 OCx 输出毫无影响。同步的精度可以达
到计数器的一个计数周期。
可通过软件随时更新 TIMx_CCRx 寄存器以控制输出波形,前提是未使能预加载寄存器
(OCxPE=“0”,否则仅当发生下一个更新事件 UEV 时,才会更新 TIMx_CCRx 影子寄存
器)。
通过上述介绍,可以这样理解,在TIMx的CCRx写入一个值,如果TIMx的CNT与它匹配(相同),会产生电平翻转,如果开启了中断,就会产生中断。
取计数周期为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。
则可以得到如下方波。
通道2类似,读者可以自己画图检验
取计数周期为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波。
取计数周期为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;
(如果读者还是不能理解,可以画个波形看看哦)
由于在做这个实验的时候身边没有示波器,所以采用上升沿和下降沿个数来判断是否成功。
所以我们采用了串口(9600)和LCD帮助测试
TIM3配置如下:
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);
以上都是初始化和测试显示函数,不需要多讲
由于输出比较的真的比较少,而且对于用HAL做的资料,本人就没找到。。。
所以查了原子提供的参考手册,然后也是被HAL库的集成度坑了。
首先对于中断标志位:
TIMx_SR寄存器,第1.2位保存的通道1、2的捕获和比较中断标志,上面说的很清楚,当在输出比较模式下,计数值和比较值匹配时,该位会置1。
HAL库不熟悉的情况下,本人建议可以记一些比较常用的的寄存器,比如CCRx,SR,CNT等等,以免找不到想要找的函数。
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通道是否开启允许中断。
代码测试:
串口接收到的CNT值大于CCRx值是正常的,因为代码运行需要时间,产生了中断就表示有匹配。
图2可以看到2通道粗略是1通道的两倍,即1Hz和2Hz的方波。
以上就是TIM的输出比较模式的配置以及测试代码。
(本文写了很久,主要资料真的少,点个赞,支持一下,谢谢)
骚年、点个赞再走吧!