蓝桥杯嵌入式 的pwm问题

这里的PWM频率调整 没有考虑到ARR取值范围会溢出的问题 比如说你需要设置1000hz 按理来说 ARR应该是79999 但是实际上TIM-ARR是14463 是因为上限是65535之后溢出所导致的 所以我们要对溢出的ARR进行分频处理

// 原始代码的频率计算
uint32_t arr = clk / Frequency - 1;

没有考虑ARR溢出
ARR寄存器是16位,最大值65535
当频率较低时,arr值会超过65535
例如:80MHz/1000Hz = 80000 > 65535

定时器频率计算公式:f = clk/((PSC+1)*(ARR+1))
预分频器实际值 = 寄存器值 + 1
避免多次除法运算引入误差
直接用目标频率反推ARR值更准确

void pwm_set_frequency(int Frequency)
{
	// 获取定时器的时钟频率(假设TIM3使用的时钟频率为TIM3_CLK)
	uint32_t TIM3_CLK = HAL_RCC_GetPCLK2Freq(); // 例如80MHz, 需要根据实际情况调整
	// 初始化变量
	float duty = 0;
	uint32_t prescaler = 1;
	uint32_t arr;
	// 计算ARR和预分频器
	arr = TIM3_CLK / (Frequency * prescaler) - 1;
	// 如果ARR超出范围,调整预分频器
	if (arr > 65535)
	{
		prescaler = (arr + 65535) / 65535;
		arr = TIM3_CLK / (Frequency * prescaler) - 1;
	}
	// 保存原占空比
	duty = (float)TIM3->CCR2 / (TIM3->ARR + 1);
	// 设置新的预分频值和ARR
	__HAL_TIM_SET_PRESCALER(&htim3, prescaler - 1);
	TIM3->ARR = arr;
	// 保持占空比不变
	TIM3->CCR2 = (arr + 1) * duty;
	// 更新寄存器
	TIM3->EGR = TIM_EGR_UG;
}

  1. 获取定时器时钟频率:

    • uint32_t TIM3_CLK = HAL_RCC_GetPCLK2Freq(); 获取 PCLK2 的时钟频率。
  2. 计算 ARR 和预分频器:

    • arr = TIM3_CLK / (Frequency * prescaler) - 1; 计算 ARR 值。
    • 如果 ARR 超出范围,调整预分频器 prescaler 并重新计算 ARR
  3. 保存原占空比:

    • duty = (float)TIM3->CCR2 / (TIM3->ARR + 1); 计算当前占空比。
  4. 设置新的预分频值和 ARR:

    • __HAL_TIM_SET_PRESCALER(&htim3, prescaler - 1); 设置新的预分频值。
    • TIM3->ARR = arr; 设置新的 ARR 值。
  5. 保持占空比不变:

    • TIM3->CCR2 = (arr + 1) * duty; 计算新的 CCR2 值。
  6. 触发更新事件,刷新寄存器:

    • TIM3->EGR = TIM_EGR_UG; 触发更新事件,使新的 ARR 和 CCR2 生效。

可能还是比较难以理解举个例子

假设我们有一个系统使用 80 MHz 的系统时钟,并且我们希望将 TIM3 的 PWM 频率设置为 100 Hz,但初始计算出的 ARR 超过了 65535。

初始计算
  • TIM3_CLK = 80000000
  • Frequency = 100 Hz
  • 初始 prescaler = 1
  • arr = 80000000 / (100 * 1) - 1 = 800000 - 1 = 799999 (超过了 65535)
调整预分频器
  • prescaler = (799999 + 65535) / 65535 = 865534 / 65535 ≈ 13.21,取整后得到 prescaler = 14
  • 重新计算 arr:
    • arr = 80000000 / (100 * 14) - 1 = 80000000 / 1400 - 1 = 57142 - 1 = 57141 (现在在有效范围内)
设置新的 ARR 和 PSC
  • __HAL_TIM_SET_PRESCALER(&htim3, 14 - 1); 设置预分频器为 13
  • TIM3->ARR = 57141; 设置新的 ARR 值
  1. 计算新的预分频器:

    • prescaler = (arr + 65535) / 65535;
    • 这行代码的作用是确定最小的整数倍数,使得调整后的 ARR 值小于或等于 65535
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值