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引脚拉高,可观测到输出信号立刻停止,若松开则恢复默认输出。
至此,本实验已介绍完毕。
全部0条评论
快来发表一下你的评论吧 !