目录
原理说明:
CUBMAX初始化:
代码实现:
问题和注意事项:
引用的文章:
输出比较模式下: CCR = CNT 时,翻转输出电平。
PWM模式下: CNT < CCR时输出一种电平,CNT > CCR时输出相反的电平。
通过图片来直观的看看这两种模式的区别。
PWM模式下: ARR 决定输出频率 ,CCR决定输出占空比。
输出比较模式下: ARR 决定输出频率 CCRx 决定每个通道的初始相位。
一般使用输出比较都是想要去输出一个频率可变的pwm信号,那怎么通过输出比较改变频率呢。
比如我想输出这些信号
以第一路为例:先将CCRx设为2,到达之后我们进入中断然后把CCRx设为7,这样一直循环,就可输出第一路。
第四路则可以直接使用pwm模式输出。
这里说明一下频率怎么计算:
影响PWM占空比跟频率的参数这主要是 Pulse、Prescaler、Period 这3个;
Pulse:我们设置的CCRx的值
Prescaler:PSC分频系数
Period:我们自己计算的一个计数周期
占空比 = (Pulse/Period)*100%;
频率: f = 80MHZ/Prescaler/Period;
频率跟占空比都与Period(计数周期)有关,只要我们把计数周期定下来,修改Prescaler、跟Pulse这两个值,就可以直接修改PWM的频率跟占空比了。具体要多少的占空比跟频率,就自己计算一下就可以了。举个例子说明一下:这里Period周期数设为100,如果我要设定一个频率为100Hz、占空比50%的PWM波,只需要传入参数Pulse=50(占空比 = Pulse / Period * 100% =(50/100) * 100%=50%)、Prescaler=8000(f = 系统频率 / 分频 / 计数周期 = 80MHZ/8000/100 = 100Hz)
80Mhz/8000=10Khz=0.1ms一个计数周期,我们需要的是100HZ的频率,也就是10ms一个计数脉冲,所以我们需要100个0.1ms的计数周期才输出1个频率为100HZ的PWM波
Prescaler 预分频器,可以将计数器时钟频率除以1到65536之间的任何因子,是一个16bit的值。设置的值写入单片机定时器的TIMx_PSC寄存器中,设置值 =(预期值-1);
Counter Mode 计数模式,设置向上计数(计数器从小到大递增计数 0-1-0)、向下计数(计数器从大到小递减计数 1-0-1)和居中对齐1~3(计数器先递增再递减 0-1-1-0或者先递减在递增1-0-0-1等 );
Count Period 计数周期,决定定时器周期,是一个16bit的值。设置的值写入单片机定时器的TIMx_ARR寄存器中,设置值=(预期值-1);
Internal Clock Division 内部时钟分割,表示由数字滤波器(TIx)使用的时钟(CK_INT)频率和采样时钟之间的分割比率(什么乱七八糟的,不管);
auto-reload preload 自动重载预加载,使能就启动预加载,不使能就不启动预加载。设置的值写入单片机定时器的TIMx_CR1寄存器的ARPE位,具体作用如下图所示:
在定时器工作中,当不启动预加载,改变ARR的值,会立即生效,如下图所示:
在定时器工作中,当启动预加载,改变ARR的值,会等待下一次计数生效,而在当前计数周期会由影子自动重加载寄存器的值决定,如下图所示:
Trigger Output Parameters:这里用不到,暂时不介绍,默认即可。
Output Compare Channel n:
打开定时器中断,如果没要求优先级默认即可。
HAL_TIM_OC_Start_IT(&htim4,TIM_CHANNEL_2);//开启输出比较
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
uint8_t CCR_value;//用来放读取到的CCRx的值
if(GPIO_PIN_RESET==HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7))//判断电平翻转后是不是低电平
{
CCR_value=HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);//读取CCRx的值
if(CCR_value+Period*((100-duty_PA6)/100)-9949>=0)//判断有没有计时溢出,我这里设置的ARR的值是9999,
{
xxx=(Period*(100-duty_PA6))/100;定义的一个用来方便调试的时候,观察每次加CCRx加多少的变量
Pulse[1]=CCR_value+xxx-9999;//Pulse[1]是新的CCRx的值
__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_2,Pulse[1]);//设置定时器4通道2的CCRx的值
}
else
{
xxx=(Period*(100-duty_PA6))/100;
Pulse[1]=CCR_value+xxx;
__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_2,Pulse[1]);
}
}
else
{
CCR_value=HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
if(CCR_value+Period*duty_PA6/100-9949>=0)
{
xxx=(Period*duty_PA6)/100;
Pulse[1]=CCR_value+xxx-9999;
__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_2,Pulse[1]);
}
else
{
xxx=(Period*duty_PA6)/100;
Pulse[1]=CCR_value+xxx;
__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_2,Pulse[1]);
}
}
}
我的代码中间CCR_value+Period*((100-duty_PA6)/100)-9949>=0判断下一次的CCRx的值是不是超出了ARR的值,我的ARR是9999,不应该是CCR_value+Period*((100-duty_PA6)/100)-9999>=0才对吗?但是我写成9999的话就会多加一次,CCRx的值会超过9999?求解惑。
STM32输出比较模式和PWM模式 比较https://blog.csdn.net/qq_20222919/article/details/106564957?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164821054016780269885760%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164821054016780269885760&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-106564957.142^v5^pc_search_result_cache,143^v6^control&utm_term=%E8%BE%93%E5%87%BA%E6%AF%94%E8%BE%83%E5%92%8Cpwm%E5%8C%BA%E5%88%AB&spm=1018.2226.3001.4187STM32定时器比较输出切换模式之应用实例https://www.sohu.com/a/318112433_807475http://STM32 Cubemx 输出可调频率与占空比的PWMhttps://blog.csdn.net/weixin_30826761/article/details/99339820?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164864328416780274146991%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164864328416780274146991&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-21-99339820.142^v5^pc_search_result_cache,143^v6^control&utm_term=cubmax%E9%85%8D%E7%BD%AEhal%E5%BA%93%E8%BE%93%E5%87%BA%E6%AF%94%E8%BE%83pwm&spm=1018.2226.3001.4187