本帖最后由 地瓜patch 于 2025-3-4 20:53 编辑
#申请原创# @21小跑堂
一、缘起
最近有个需求,需要产生频率和占空比可调的方波,手头上有STM32F407的板子,就用它做一下测试。
因为需求提的很高频率调节步进1%,占空比步进0.1%。测一下STM32F407定时器产生PWM的极限频率,并关注占空比调节情况。
STM32F407用的很多,用也就用了,也不是用到极致,满则亏总要留些余量。
二、说明
要测最高频率那当然要用速度最快的定时器,从芯片的结构框图中能够看到TIM1和TIM8都挂在APB2上。
从上边框图上看到APB2的频率是84MHz,但是其上的定时器是在此基础上倍频,达到168MHz。实测也是如此
顺便提一句,APB2的频率是42MHz,与其关联的TIM2,TIM3等等定时器也是在此基础上倍频,达到84MHz.
TIM1和TIM8都是16位高级定时器,可以产生pwm,功能和性能比其他定时器多一些。所以就用TIM1来进行测试。
pwm频率的计算公式 Fpwm = Fck / (ARR + 1)(CCR + 1 )
三、实测
用cubeMX配置了一个程序,但是这个程序是不能正常输出PWM波形的。
因为没有启动定时器和PWM。
在程序最后加上两条语句就可以了。
static void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* USER CODE BEGIN TIM1_Init 1 */
/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 1680-1;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 3-1;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */
/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);
HAL_TIM_Base_Start(&htim1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
}
1.显测试较小频率下的占空比。
初始化TIM1的时钟为168M,周期为10us,定义脉宽为10ns
htim1.Init.Prescaler = 0;//定义频率为168MHz,即Fck
htim1.Init.Period = 1680-1;//定义周期10us,即ARR
sConfigOC.Pulse = 3-1;/定义脉宽计算值为10ns,实际测量得到8ns,即CCR
实测周期10us,脉宽8ns如下图
其余参数不变,sConfigOC.Pulse = 5-1;//脉宽20ns如下图
sConfigOC.Pulse = 6-1;//实际测量得到28ns
sConfigOC.Pulse = 7-1;//脉宽30ns,实际32ns
从以上测量可以看到,在小占空比时,误差较大,能达到20%,当然这中极端占空比较少使用。
2.测试高频pwm下,占空比的变化
测试方法如上,先计算得到PWM频率和占空比,后进行测试量取其时间。测试结果如下
2.1
htim1.Init.Prescaler = 0;//168MHz
htim1.Init.Period = 2;//周期计算得到11.90ns,实测为18ns
sConfigOC.Pulse = 1;//实测为5ns
2.2,周期24ns不变实测占空比
htim1.Init.Prescaler = 0;//168MHz
htim1.Init.Period = 3;//周期计算得到17.857ns,实测24ns
sConfigOC.Pulse = 1;//脉宽计算得到6ns,实测7.5ns
sConfigOC.Pulse = 2;//脉宽计算得到12ns,实测7ns
sConfigOC.Pulse = 3;//脉宽计算得到17.8ns,实测7.5ns
2.3周期66ns不变实测占空比
htim1.Init.Prescaler = 0;//168MHz
htim1.Init.Period = 10;//周期3=59.5ns,实测66ns
sConfigOC.Pulse = 1;//脉宽ns,实测5ns
sConfigOC.Pulse = 2;//脉宽ns,实测8ns
sConfigOC.Pulse = 3;//脉宽ns,实测16ns
sConfigOC.Pulse = 4;//脉宽ns,实测21ns
sConfigOC.Pulse = 5;//脉宽ns,实测28ns
sConfigOC.Pulse = 6;//脉宽ns,实测34ns
sConfigOC.Pulse = 7;//脉宽ns,实测40ns
sConfigOC.Pulse = 8;//脉宽ns,实测45ns
sConfigOC.Pulse = 9;//脉宽ns,实测52ns
sConfigOC.Pulse = 10;//脉宽ns,实测57ns
在高频下,占空比与周期均有较大误差。频率误差达到10%,占空比误差可达50%,且并不是线性变化。
3.低频下pwm测试
3.1 50kHz
htim1.Init.Prescaler = 1;//84MHz
htim1.Init.Period = 1680-1;//周期计算得到20us,实测20us
sConfigOC.Pulse = 168-1;//脉宽计算得到2us,实测2us
sConfigOC.Pulse = 17;//脉宽计算得到202ns,实测200ns
sConfigOC.Pulse = 2;//脉宽计算得到23.8ns,实测20ns
3.2 10kHz
htim1.Init.Prescaler = 1;//84MHz
htim1.Init.Period = 8400-1;//周期计算得到100us,实测100us
sConfigOC.Pulse = 84-1;//脉宽计算得到1us,实测1us
sConfigOC.Pulse = 8;//脉宽计算得到95.2ns,实测98ns
在低频下,占空比与周期误差较小。
四、小结
经测试,在STM32F407中用TIM1实现PWM输出,
在高频时周期与占空比都存在较大误差,数据如上所示。
在低频时周期与占空比误差较小,数据如上所示。
在50kHz下,能够满足周期调整步进1%,占空比调整步进0.1%的要求。
以上数据,在配置参数或计算结果时都存在四舍五入。
以上测试可能存在错误,欢迎指正。
|