PWM输出配置方法

描述

MCU微课堂

CKS32F107xx TIM(二)

第四十七期 2024.11.01

PWM模式简介

从上节课的定时器分类图中我们了解到,互补输出是高级定时器(TIM1、TIM8)所独有的,它可以输出两路互补信号。而在本节课中我们将通过一个简单的例程去介绍如何配置互补PWM输出,同时为了演示在电机控制领域的入门应用,该例程也增加了刹车和死区插入的功能。因此,接下来我们将先对PWM模式、互补输出、死区插入、刹车功能这四个概念作简要介绍,然后通过一个实验例程来演示PWM输出配置方法。

比较输出是通过比较计数器CNT和捕获/比较寄存器CCR的关系,来对输出电平进行置1、置0或翻转的操作,而PWM模式输出的是一种脉冲宽度可调的方波信号,同时也是定时器(高级和通用)比较输出模式中较为常用的一种,我们可以通过捕获/比较模式寄存器CCMRx的位OCxM[2:0]来配置输出。表1罗列了PWM1和PWM2的区别,并通过PWM1边沿对齐的波形示例图来简述下PWM输出的原理。

表1 PWM1和PWM2模式区别

计数器

计数器

图1 边沿对齐的PWM1波形(TIMx_ARR=8)

如上图所示,当CNT < CCR时,参考信号OCxREF输出为高,则通道OCx输出1;当CCR <= CNT <= ARR时,参考信号OCxREF输出为低,则通道OCx输出0。并且当计数器CNT与比较寄存器CCR值匹配时,比较中断寄存器CCxIF位会自动由硬件置 1;而CNT计数达到ARR的值时,会产生上溢事件,并且自动清零,然后重新向上计数,如此循环往复。因此,我们可以通过修改ARR和CCR的值来灵活调整PWM波形的频率和占空比。

定时器产生PWM 输出,除了上节课提到的ARR、PSC、CNT,不得不提的还有捕获/比较模式寄存器CCMR。该寄存器共有两个,CCMR1(控制输出通道1和2)和CCMR2(控制输出通道3和4),且上面一层对应比较输出,下面一层对应输入捕获,输入捕获模式将在下节课中介绍。由于本节课介绍的是互补PWM输出,所以模式设置位OCxM[2:0],必须设置为110/111,对应PWM1/PWM2,两者区别是极性相反。下图是CCMR1寄存器各位描述图,具体请参照CKS32F107xx参考手册。

计数器

图2 CCMR1寄存器各位描述图、

互补输出和死区插入简介

接下来将先通过捕获/比较通道的输出概览图来展现输出控制过程。

计数器

图3 捕获/比较通道的输出部分(通道CH1~CH3)

如上图,红框中是CNT和CCR比较,输出参考信号OCxREF,衔接上文。绿框表明参考信号OCxREF在经过死区发生器之后会产生两路带死区的互补信号OCx_DT和OCxN_DT,并且需要特别说明下,高级定时器(TIM1、TIM8)只有通道CH1~CH3才有互补信号。蓝框是输出控制电路,若没有死区控制,则进入的信号即为OCxREF,且进入的信号会被分成极性相反的两路,并由寄存器CCER的位CCxP和CCxNP控制极性,由CxE和CCxNP位使能输出。若增加了刹车功能,则寄存器BDTR的位MOE、OSSI和OSSR将共同影响输出信号。

关于死区插入,其中一个较为典型的应用就是半桥驱动电路,比如上个时态MOS管M1导通,MOS管M2截止,下一时态需要M1截止,M2导通,由于工艺限制MOS管的关闭不能忽略不计,这就会导致M1和M2有同时导通的时间,进而损坏电路,所以可将M1关闭后等待一段时间再打开M2,这段时间可称为死区时间。死区时间是通过寄存器BDTR的位DTG[7:0]来配置,死区时间的大小需要根据输出通道相连接的器件特性来调整。下图为带死区插入的互补输出图,相信这样能大家有个更为直观的了解。

计数器

图4 带死区插入的互不输出

刹车功能简介

电路控制电机转动出现异常时,若用软件来关闭信号输出,出于软件延时的影响,可能带来不必要的后果。在此工况下,高级定时器中的刹车功能能发挥特定优势,用户只要将检测端连接到TIMx_BKIN引脚,当检测到非正常态,由硬件电路立刻关闭信号输出,电机即可停止转动。刹车功能是一种硬件保护保护,用户需要配置刹车和死区寄存器BDTR,该寄存器各位描述如下:

计数器计数器

图5 BDTR寄存器各位描述图

互补PWM输出配置实验

本实验以高级定时器TIM1为例,并参照CKS32F107xx数据手册的引脚定义章节,分配了OC1(PA8)、OC1N(PB13)和BKIN(PB12)引脚。若我们在工程中选择BKIN引脚高电平有效,那么当BKIN引脚被置高时,两路互补PWM信号立刻停止输出。主要的编程要点如下。 

1、开启GPIO时钟,配置引脚

要使用GPIOA、GPIOB的相关引脚,需要开启端口时钟,调用的函数为:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

因为要将普通GPIO复用到定时器的相关引脚,所以要配置GPIO工作模式,示例代码如下,以PA8配置为例,PB13和PB12配置雷同:

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

2、TIM1时基结构体设置

鉴于前一章节已详述过,这里仅做代码演示,针对TIM1时基初始化示例代码格式如下:

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

TIM_TimeBaseStructure.TIM_Prescaler= 8;

TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;  

TIM_TimeBaseStructure.TIM_Period=7;

TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;  

TIM_TimeBaseStructure.TIM_RepetitionCounter=0;

TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

根据前文定时时间的描述,当TIM1工作时钟配置为72MHz时,那么示例代码中配置的中断次时间为:(8+1)*(7+1) / 72000000 = 1us,则PWM输出的频率为1MHz。

3、TIM1输出比较结构体设置

通过配置TIM1_CCMR1的相关位来设置TIM1_CH1的PWM模式。在库函数中,PWM通道设置是通过函数TIM_OC1Init()~TIM_OC4Init()来设置的,不同通道的设置函数不一样,使用时需要注意区分,这里我们选用CH1通道和CH1N通道,选用的库函数如下:

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

输出比较结构体在库函数中对应名称为TIM_OCInitTypeDef,下面是结构体的定义:

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;

参数TIM_OCMode是用来设置比较输出模式,这里我们选用PWM1模式。

参数TIM_OutputState和TIM_OutputNState用来配置OCx和OcxN通道输出使能。

参数TIM_Pulse是设置比较寄存器CCR的值,决定脉冲宽度,对应PWM1的占空比。

参数OCPolarity和TIM_OCNPolarity是设置OCx和OcxN通道极性,我们可以选择高电平或低电平有效。

参数TIM_OCNIdleState和TIM_OCNIdleState是设置空闲状态时OCx和OcxN通道输出的电平。

针对TIM1输出比较结构体初始化示例如下:

TIM_OCInitTypeDef      TIM_OCInitStructure;  

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;

TIM_OCInitStructure.TIM_Pulse = 4;

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;

TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;

TIM_OC1Init(TIM1, &TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);

在该示例中,设置了工作模式PWM1,使能了OCx和OcxN通道,配置了脉冲宽度、输出极性和空闲状态下的输出电平,所以PWM1的占空比为:CCR / (ARR + 1) = 50%。

4、TIM1断路和死区结构体设置

我们在库函数中设置刹车和死区参数是通过函数TIM_BDTRConfig来实现的,其结构体TIM_BDTRInitTypeDef中列出了各个成员,以下是结构体的定义:

Typedef struct  

{

  uint16_t TIM_OSSRState;         

  uint16_t TIM_OSSIState;         

  uint16_t TIM_LOCKLevel;         

  uint16_t TIM_DeadTime;          

  uint16_t TIM_Break;             

uint16_t TIM_BreakPolarity;     

  uint16_t TIM_AutomaticOutput;   

}TIM_BDTRInitTypeDef;

这里结构体中的成员可以对照上文BDTR寄存器的各位来理解,在此不再赘述,本实验中我们针对TIM1断路和死区结构体初始化示例如下:

TIM_BDTRInitTypeDef    TIM_BDTRInitStructure;

TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;

TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_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(TIM1, &TIM_BDTRInitStructure);

在该示例中,配置的死区时间为11 / 72000000 = 152ns,配置BKIN引脚为高电平有效。

5、使能TIM1和主输出

因为本实验是互补PWM输出,所以除了要开启定时器,也要对定时器主输出进行使能,配置示例如下: 

TIM_Cmd(TIM1, ENABLE);

TIM_CtrlPWMOutputs(TIM1, ENABLE);

6、修改TIM1_CCR1来调整占空比

实际使用时,用户需要控制占空比来调整电机的转速,我们能通过修改TIM1_CCR1则可以控制CH1的输出占空比。在库函数中,修改TIM1_CCR1占空比的函数是:

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);

同样的,对于其他三个通道,也有如下对应函数供调用,用户使用时注意区分即可。

void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);

void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);

void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

只要按照上述配置,用户在主函数中调用即可,我们示波器的两个输入通道分别接PA8、PB13引脚,可观测到两路互补带死区插入的PWM波形,频率为1MHz,占空比默认为50%(用户可自行调整),死区时间为152ns左右。

计数器

如果将BKIN引脚拉高,可观测到输出信号立刻停止,若松开则恢复默认输出。

计数器

至此,本实验已介绍完毕。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分