要求:
输出2-573Hz频率,输出频率步长小于1Hz
一、CubeMX配置
auto-reload preload在下个周期加载ARR
Output compare preload 在下个周期加载CCR
二、 程序
1.启动PWM输出
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
2.根据频率调整PSC、ARR、CCR
/**
* @brief 设置高精度PWM输出
* @param htim: 定时器句柄
* @param freq_hz: 目标频率(2.0~573.0Hz)
* @param duty_ratio: 占空比(0.0~1.0)
* @retval 无
*/
void Set_PWM_Precision(TIM_HandleTypeDef *htim, float freq_hz)
{
uint32_t arr, psc, ccr;
float duty_ratio = 0.5;
// float calc_freq;
// 参数安全检查
if(freq_hz < 2.0f) freq_hz = 2.0f;
if(freq_hz > 573.0f) freq_hz = 573.0f;
if(duty_ratio < 0.0f) duty_ratio = 0.0f;
if(duty_ratio > 1.0f) duty_ratio = 1.0f;
// 自动选择最优ARR值
if(freq_hz <= 300.1f)
{
// 低频模式
psc = 720-1; // ARR+1=720
arr = (uint32_t)(1e5/freq_hz) - 1;
ccr = (uint32_t)((arr + 1) >> 1);
}
else
{
// 高频模式
psc = 72-1; // ARR+1=1200
arr = (uint32_t)(1e6/freq_hz) - 1;
ccr = (uint32_t)((arr + 1) >> 1);
}
// 参数限幅保护
if(psc > 65535) psc = 65535;
if(psc < 1) psc = 1;
// 更新定时器配置
__HAL_TIM_SET_PRESCALER(htim, psc);
__HAL_TIM_SET_AUTORELOAD(htim, arr);
__HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, ccr);
// if(old != psc)
// {
// htim->Instance->EGR |= 1;
// }
// 调试输出(可选)
// printf("%d,%0.3f\r\n",psc,AS5600_info.PWM_out);
// calc_freq = 72000000.0f/((psc+1)*(arr+1));
// printf("Set %.1fHz: ARR=%lu, PSC=%lu, Actual=%.3fHz\n",
// freq_hz, arr, psc, calc_freq);
}
3.连续输出
for(int16_t a = 2;a<573;a++)
{
Set_PWM_Precision(&htim2,a);
HAL_Delay(500);
}
三、备注
1、注意点
1、若auto-reload preload配置为Enable,则ARR数据的修改发生在更新事件发生时;配置为Disable,则ARR数据的修改会立即影响TIMx_ARR的影子寄存器。
2、若Output compare preload配置为Enable,则CCR数据的修改发生在更新事件发生时;配置为Disable,则CCR数据的修改会立即影响TIMx_CCR的影子寄存器。
3、当需要同时修改PSC和ARR时,需要将两者使能,即将上一个周期发送完成后,更新事件触发,使两个影子寄存器同时更新,避免因两个影子寄存器更新不同步造成的问题。
2、定时器知识拓展
1、stm32的定时器中有4个带影子特性的寄存器组:TIMx_PSC(分频寄存器)、TIMx_ARR(自动重装载寄存器)、TIMx_CCR(捕获寄存器)、TIMx_RCR(重复计数寄存器)。
2、以上4个寄存器组分别由影子寄存器和预装载寄存器组成,影子寄存器是真正起作用的控制寄存器,但用户访问不到它。预装载寄存器是用户可以访问的,它为实际影子寄存器准备数据或指令。
3、TIMx_ARR、TIMx_CCR有预装载使能控制位。TIMx_PSC、TIMx_RCR不带预装载使能控制位,这两者影子寄存器的预装载功能始终开启。
4、当开启预装载功能时,此时影子寄存器的数据更新必须且只能通过更新事件(在TIMx_EGR寄存器中(通过软件方式或者使用从模式控制器)设置UG位也同样可以产生一个更
新事件。)实现从预装载寄存器到影子寄存器的数据拷贝;当关闭预装载功能时,用户修改预装载寄存器的数据会立即拷贝进影子寄存器。