利用STM32的定时器输出PWM方波

        脉冲宽度调制 (PWM) ,是英文“ Pulse Width Modulation ”的缩写,简称脉宽调制,是利用
微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽
度的控制。
       
        图中,我们假定定时器工作在向上计数 PWM 模式,且当 CNT<CCRx 时,输出 0 ,当 CNT>=CCRx 时输出 1 。那么就可以得到如上的 PWM 示意图:当 CNT 值小于 CCRx 的时候, IO 输出低电平 (0) ,当 CNT 值大于等于 CCRx 的时候,IO 输出高电平 (1) ,当 CNT 达到 ARR 值的时候,重新归零,然后重新向上计数,依次循环。 改变 CCRx 的值,就可以改变 PWM 输出的占空比,改变 ARR 的值,就可以改变 PWM 输出的频率,这就是 PWM 输出的原理。(PS:操作寄存器请大家自行查阅手册,我这里还是只演示CubeMX+HAL库函数)。
      下面来操作CubeMX输出PWM,首先还是选择外部晶振开启总线调试接口;接下来有个关键点,配置挂载tim的时钟总线频率,我这里统一用了72M;
      然后是第二个关键点,选择时钟模式,时钟源选择Internal Clock,然后开启对应的通道并选择PWM生成模式。
       最后一个配置要点参数设置,首先明确一点,一组高低电平组成的PWM波形的周期计算公式如下:T=\frac{(Prescaler+1)*(Counter Period+1)}{Ftim},其中Prescaler是预分频系数,Counter Period是自动重装载寄存器里存储的计数周期,Ftim是挂载TIM的时钟总线上的时钟信号频率。计数模式一般习惯性选择向上计数(Count Mode选择UP),内部时钟预分频不用,影子寄存器可以使能一下。

     触发输出参数选择中触发事件选择复位Reset,主从模式选择disable。

    最后的PWM生成参数,PWM模式选择模式1,两者的区别是

  1. PWM mode 1
    • 在向上计数中,当计数值小于CCR(捕获/比较寄存器)值时,PWM输出高电平;当计数值大于CCR值时,PWM输出低电平。
    • 在向下计数中(如果存在中心对齐模式),当计数值小于CCR值时,PWM输出低电平;当计数值大于CCR值时,PWM输出高电平。
    • 这种模式下,PWM信号的输出逻辑在低电平和高电平之间切换,以控制PWM的占空比。
  2. PWM mode 2
    • 在向上计数中,当计数值小于CCR值时,PWM输出低电平;当计数值大于CCR值时,PWM输出高电平。
    • 在向下计数中(如果存在中心对齐模式),当计数值小于CCR值时,PWM输出高电平;当计数值大于CCR值时,PWM输出低电平。
    • 与PWM mode 1相反,这种模式下PWM信号的输出逻辑在高电平和低电平之间切换,以控制PWM的占空比。
     我们可以先试着用CubeMX配置固定占空比的PWM方波,这种需求只需要一行hal库代码就能实现。主要精力放在填写参数上,首先将预分频系数设置为7199,计数周期为4999,挂载在一个72Mhz的时钟线上,所以理论上一对高低电平组成的周期为0.5s。然后将PWM Generation Channel4中的Pulse设置为2000(理论占空比为2000/5000=0.4,它的范围是[0,Counter Period]),极性设置为低(我的开发板上的LED灯低电平点亮),随后生成代码。
在TIM初始化函数中直接开启PWM。
  /* USER CODE BEGIN TIM3_Init 2 */
  HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_4);
  /* USER CODE END TIM3_Init 2 */

观察示波器波形,可以看到高低电平周期为500ms,其中300ms输出高电平,200ms输出低电平,和理论值相符合。LED灯只是不停地闪烁,并没有实现呼吸灯效果。

当然更多时候占空比需要可调,我来演示一下pluse占空比选择0,输出比较预装载寄存器需要使能,快速模式可以关闭,极性选择高。

生成代码至IDE开始调参。
①命名一个占空比变量
  /* USER CODE BEGIN 1 */
  uint16_t pwm=0;      //调控占空比
  /* USER CODE END 1 */

②主循环里写逻辑功能

    /* USER CODE BEGIN 3 */
		while(pwm<499)
	  {
		  pwm++;
		  __HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_4, pwm);    //通过修改比较值来改变占空比
	  }
	  while(pwm)
	  {
		  pwm--;
		  __HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_4, pwm);    //通过修改比较值来改变占空比
		  HAL_Delay(1);
	  }
	  HAL_Delay(200);
  }
  /* USER CODE END 3 */

观察示波器波形论证结果

宏观来讲,每个循环最后延时200ms已经实现。

每个高低电平组成的周期实测500us,理论值(71+1)*(499+1)/72000000=0.0005s基本符合。

占空比大致为80%,输出400us低电平之后输出100us高电平,也符合理论范围。占空比调制成功实现了呼吸灯效果。

要在 STM32输出 PWM ,你需要执行以下步骤: 1. 设置引脚为 PWM 模式:选择一个支持 PWM 输出的引脚,并将其配置为复用功能。具体的引脚和配置方法取决于你使用的 STM32 型号和开发环境。通常,你可以使用 GPIO 初始化函数来设置引脚功能。 2. 配置定时器:选择一个可用的定时器,并设置它的时钟源、预分频因子和计数器周期。这些设置将决定 PWM 的频率和分辨率。你可以使用定时器初始化函数来完成这些配置。 3. 配置 PWM 通道:选择一个通道,并设置其比较值和工作模式。比较值决定了 PWM 的占空比。工作模式可以是输出比较模式或输入捕获模式,具体取决于你的需求。你可以使用 PWM 初始化函数来配置 PWM 通道。 4. 启动定时器PWM 输出:启动定时器以开始计数,并使能 PWM 输出。你可以使用相应的函数来实现这些操作。 下面是一个简单的示例代码,演示如何在 STM32输出 PWM : ```c #include "stm32f4xx.h" void PWM_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; // 使能定时器时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIMX, ENABLE); // 使能引脚时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOX, ENABLE); // 配置引脚为复用功能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_X; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOX, &GPIO_InitStructure); // 配置引脚复用映射 GPIO_PinAFConfig(GPIOX, GPIO_PinSourceX, GPIO_AF_TIMX); // 配置定时器基本参数 TIM_TimeBaseStructure.TIM_Period = PeriodValue; TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIMX, &TIM_TimeBaseStructure); // 配置 PWM 模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_Pulse = PulseValue; TIM_OCXInit(TIMX, &TIM_OCInitStructure); // 启动定时器PWM 输出 TIM_Cmd(TIMX, ENABLE); TIM_CtrlPWMOutputs(TIMX, ENABLE); } int main(void) { // 初始化相关硬件和外设 // 配置 PWM PWM_Config(); while (1) { // 执行其他任务 } } ``` 请根据你的具体需求修改代码中的参数和引脚配置。这只是一个简单示例,你可能需要根据你的应用场景进行更多的配置和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值