STM32学习笔记(4) 高级定时器-两路互补的PWM输出(带死区和刹车控制)

目录

1.实验目的

2.实验效果

3.理论部分

3.1时钟源

3.2时基单元

3.3输入捕获

4.程序流程

4.1GPIO初始化结构体

4.2时基初始化结构体

4.3输出比较结构体

4.4刹车和死区结构体的初始化

5.程序源码


1.实验目的

使用高级定时器,输出两路互补的PWM输出,需要有带死区和不带死区两种情况

2.实验效果

图1:不带死区的两路互补的PWM输出

图2 :带死区的两路互补的PWM输出

3.理论部分

3.1时钟源

内部时钟(基本定时器,通用定时器时钟源来自PCLK1,但高级定时器的时钟源来自PCLK2(72M))

实践中几乎无需使用:外部时钟模式1、外部时钟模式2

3.2时基单元

组成:

  • 16bit预分频PSC

16bit计数器CNT

8bit重复计数器RCR(高级定时器独有)

16bit自动重装载寄存器ARR

3.3输入捕获

作用:对输入信号的上升沿/下降沿/双边沿进行捕获,测量输入信号的脉宽,和测量PWM的频率,占空比
原理:当捕捉到信号的跳变沿时,将CNT的值所存到捕获寄存器CCR中,然后把两次的值相减,就可以得到脉宽或者频率。
若脉宽时长超过你定时的时长,那么就溢出,此时我们就需要作额外的处理

PWM输入的情况下,只有CH1,CH2可以同时测量周期和占空比,因为只有TI1FP1,TI2FP2可以触发从模式控制器。选谁作从模式控制器的触发测量的就是周期,剩下的一个寄存器就测量占空比。但是单纯测量PWM的一个周期或占空比,可用四路

4.程序流程

4.1GPIO初始化结构体

输出PWM需用复用推挽输出(GPIO_AF_PP

   1、浮空输入GPIO_IN_FLOATING ——浮空输入,可以做KEY识别,RX1
   2、带上拉输入GPIO_IPU——IO内部上拉电阻输入
   3、带下拉输入GPIO_IPD—— IO内部下拉电阻输入
   4、模拟输入GPIO_AIN ——应用ADC模拟输入,或者低功耗下省电
   5、开漏输出GPIO_OUT_OD ——IO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。
   当输出为1时,IO口的状态由上拉电阻拉高电平,但由于是开漏输出模式,这样IO口也就可以由外部电路改变为
   低电平或不变。可以读IO输入电平变化,实现C51的IO双向功能
   6、推挽输出GPIO_OUT_PP ——IO输出0-接GND, IO输出1 -接VCC,读输入值是未知的
   7、复用功能的推挽输出GPIO_AF_PP ——片内外设功能(I2C的SCL,SDA)
   8、复用功能的开漏输出GPIO_AF_OD——片内外设功能(TX1,MOSI,MISO.SCK.SS)

4.2时基初始化结构体

typedef struct
{
  uint16_t TIM_Prescaler;         //预分频器
  uint16_t TIM_CounterMode;       //定时器的计数方式
  uint16_t TIM_Period;            //定时器的周期
  uint16_t TIM_ClockDivision;     //时钟分频因子
  uint8_t TIM_RepetitionCounter;  //配置重复计数器,仅高级定时器需要
} TIM_TimeBaseInitTypeDef; 

 定时器的计数方式

向上计数(基本定时器仅有这一种)、向下计数、中心对齐计数

DIR=0,向上计数

DIR=1,向下计数

配置中心对齐需CMS和DIR寄存器配合使用

4.3输出比较结构体

typedef struct
{
  uint16_t TIM_OCMode;        //比较输出模式选择
  uint16_t TIM_OutputState;   //比较输出使能
  uint16_t TIM_OutputNState;  //比较互补输出使能
  uint16_t TIM_Pulse;         //脉冲宽度
  uint16_t TIM_OCPolarity;    //输出极性
  uint16_t TIM_OCNPolarity;  //互补输出极性
  uint16_t TIM_OCIdleState;   //空闲状态下比较输出状态
  uint16_t TIM_OCNIdleState;  //空闲状态下比较互补输出状态
} TIM_OCInitTypeDef;

1.比较输出模式选择,总共有八种,常用的为 PWM1/PWM2。它设定CCMRx 寄存器 OCxM[2:0]位的值。

2.比较输出使能,决定最终的输出比较信号 OCx 是否通过外部引脚输出。它设定 TIMx_CCER 寄存器 CCxE/CCxNE 位的值。

3.TIM_OutputNState:比较互补输出使能,决定 OCx 的互补信号 OCxN 是否通过外部引脚输出。它设定 CCER 寄存器 CCxNE 位的值。

4.比较输出脉冲宽度,实际设定比较寄存器 CCR 的值,决定脉冲宽度。可设置范围为 0 至 65535。设置脉冲即可设置占空比

5.比较输出极性,可选 OCx 为高电平有效或低电平有效。它决定着定时器通道有效电平。它设定 CCER 寄存器的 CCxP 位的值。可设置占空比由高电平决定

6.比较互补输出极性,可选 OCxN 为高电平有效或低电平有效。它设定 TIMx_CCER 寄存器的 CCxNP 位的值。

7.空闲状态时通道输出电平设置,可选输出 1 或输出 0,即在空闲状态(BDTR_MOE 位为 0)时,经过死区时间后定时器通道输出高电平或低电平。它设定CR2 寄存器的 OISx 位的值。

8.空闲状态时互补通道输出电平设置,可选输出 1 或输出 0,即在空闲状态(BDTR_MOE 位为 0)时,经过死区时间后定时器互补通道输出高电平或低电平,设定值必须与 TIM_OCIdleState 相反。它设定是 CR2 寄存器的 OISxN 位的值。

4.4刹车和死区结构体的初始化

static void AdvancedTIM_BDTR_Init()
{
  TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
  
  TIM_BDTRInitStructure.TIM_OSSIState=TIM_OSSIState_Enable;//空闲模式下的关闭状态选择
  TIM_BDTRInitStructure.TIM_OSSRState=TIM_OSSRState_Enable;//运行模式下的关闭状态选择
  TIM_BDTRInitStructure.TIM_LOCKLevel=TIM_LOCKLevel_1;//锁存配置

  TIM_BDTRInitStructure.TIM_DeadTime=11;//死区时间
  TIM_BDTRInitStructure.TIM_Break=TIM_Break_Enable;//断路输入使能控制

  TIM_BDTRInitStructure.TIM_BreakPolarity=TIM_BreakPolarity_High;//断路输入极性
  TIM_BDTRInitStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable;//自动输出极性
  TIM_BDTRConfig(Advanced_TIM,&TIM_BDTRInitStructure);
}

死区时间的计算可以看看博客,讲解的也是非常详细的,对此不再赘述

这个结构体,你只需关心 TIM_BDTRInitStructure.TIM_DeadTime=11 即可

5.程序源码

高级定时器-两路互补的PWM输出(带死区和刹车控制)

STM32输出两路PWM可以使用定时器。以下是使用STM32CubeMX和HAL库配置两个定时器输出两路PWM的步骤: 1. 打开STM32CubeMX,选择你的STM32型号,然后创建一个新的工程。 2. 在配置选项卡中,打开定时器选项卡。 3. 选择一个可用的定时器(例如TIM2),启用它,并将其时钟频率设置为所需的频率。 4. 在定时器选项卡中,启用PWM输出功能并将其配置为所需的PWM频率和占空比。 5. 重复步骤3和步骤4,以启用第二个定时器(例如TIM3)并配置第二个PWM通道。 6. 生成代码并将其导入到你的IDE中。 7. 在你的代码中,初始化两个定时器和它们的PWM通道,例如: ``` // 初始化定时器2 TIM_HandleTypeDef htim2; htim2.Instance = TIM2; htim2.Init.Prescaler = 0; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 65535; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&htim2); // 初始化定时器2的PWM通道1 TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 32767; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1); // 初始化定时器3 TIM_HandleTypeDef htim3; htim3.Instance = TIM3; htim3.Init.Prescaler = 0; htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 65535; htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&htim3); // 初始化定时器3的PWM通道1 TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 32767; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1); ``` 8. 在你的代码中,启动定时器PWM输出,例如: ``` // 启动定时器2和PWM输出 HAL_TIM_Base_Start(&htim2); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); // 启动定时器3和PWM输出 HAL_TIM_Base_Start(&htim3); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); ``` 这样,你就可以在STM32输出两路PWM了。注意,对于每个定时器,你可以使用多个PWM通道,因此你可以输出更多的PWM信号。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落叶随峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值