前言
定时器输出比较模式(翻转模式)。
对于输出PWM波,在十一届考了个输出不同频率的可调占空比的PWM波。
对于此,用新板子的话可以采用TIM3、TIM17输出。(建议用新板子准备此题仍然用输出比较模式)
但是考点并不在这,考的是定时器的输出比较模式。
输出不同频率100Hz、200Hz可调占空比的PWM波
1.取计数周期为100的定时器(计数值从0到100- 1循环),频率设为100Hz = 80MHz/100/8000。
记输出PWM1,计数周期为T1 = 100,f = 100Hz=80MHz/100/8000。
记输出PWM2,计数周期为T2 = 50,f = 200Hz=80MHz/50/8000。
则令初始值TIMx_CCR1 = T1 * PA6_Duty/100 ,TIMx_CCR2 = T2 * PA7_Duty/100 。(Duty是0-100的数)
当发生中断时,
若是通道1,
则将比较值CCR1 += T1PA6_Duty/100 ;CCR1 %= TIMx_Period;
下一次CCR1 += T1(1 - PA6_Duty/100);CCR1 %= TIMx_Period;以此循环
若是通道2,
则将比较值CCR2 += T2PA7_Duty/100 ;CCR2 %= TIMx_Period;
下一次CCR2 += T2(1 - PA7_Duty/100);CCR2 %= TIMx_Period;以此循环
(如果读者还是不能理解,可以画个波形看看哦)
2.Cubemx实现TIM的配置
由于在做这个实验的时候身边没有示波器,所以采用上升沿和下降沿个数来判断是否成功。
所以我们采用了串口(9600)和LCD帮助测试
TIM3配置如下:
开启定时器中断
3.生成工程
1.开启定时器中断
- 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);
- TIM3->CCR1 = 10;
- TIM3->CCR2 = 15;
- 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);
- LCD_DisplayStringLine(Line9, str);
复制代码
以上都是初始化和测试显示函数,不需要多讲
2.更改HAL库TIM的中断总函数
由于输出比较的真的比较少,而且对于用HAL做的资料,本人就没找到。。。
所以查了原子提供的参考手册,然后也是被HAL库的集成度坑了。
首先对于中断标志位:
TIMx_SR寄存器,第1.2位保存的通道1、2的捕获和比较中断标志,上面说的很清楚,当在输出比较模式下,计数值和比较值匹配时,该位会置1。
3、中断服务函数
- uint8_t state1 = 0, state2 = 0;
- void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
- {
- if((TIM3->DIER & (0x1 << 1)) && (TIM3->DIER & (0x1 << 2)))
- {
- HAL_TIM_OC_Stop_IT(&htim3,TIM_CHANNEL_1);
- HAL_TIM_OC_Stop_IT(&htim3,TIM_CHANNEL_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);
- if(state1)
- {
- TIM3->CCR1 = TIM3->CCR1 + (uint8_t)(T1*(double)PA6_Duty/100);
- state1 = 0;
- }
- else
- {
- TIM3->CCR1 = TIM3->CCR1 + T1 - (uint8_t)(T1*(double)PA6_Duty/100);
- state1 = 1;
- }
- TIM3->CCR1 = TIM3->CCR1 % TIM3_Period;
- 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);
- if(state2)
- {
- TIM3->CCR2 = TIM3->CCR2 + (uint8_t)(T2*(double)PA7_Duty/100);
- state2 = 0;
- }
- else
- {
- TIM3->CCR2 = TIM3->CCR2 + T2 - (uint8_t)(T2*(double)PA7_Duty/100);
- state2 = 1;
- }
- TIM3->CCR2 = TIM3->CCR2 % TIM3_Period;
- num2++;
- }
- }
- HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_1);
- HAL_TIM_OC_Start_IT(&htim3,TIM_CHANNEL_2);
- }
复制代码
在测试输出波形时,发现会一直产生中断,导致主函数没办法运行,所以在中断开启时关闭PWM中断,中断结束后再重新开启(虽然会有时间延迟,有一点波形误差,但肉眼是分不清的。)。
代码测试:
|