PWM(Pulse Width Modulation)——脉宽调制,是一种开关式稳压电源应用,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。
先科普一下,什么是互补PWM:就是两组PWM信号,它们的波形是互补的,简单理解,就是这两个信号直接相加的话,结果是一条直线。互补PWM有时候需要增加一个“死区”,防止两个信号同时为1或者同时为0的瞬间出现。

波形如图:


好了,看懂图后,我就上代码啦,不客气l !

#ifndef __BSP_PWM_H__
  • #define __BSP_PWM_H__
  • #include "bt.h"
  • #include "gpio.h"
  • #define  PWM_PERIOD_4MS  0xbe00
  • void BSP_PWM_Config(void);
  • void BSP_2Comp_PWM_Config(void);
  • void BSP_PWM_SetDuty(uint8_t duty);
  • void BSP_PWM_Deconfig(void);
  • #endif
  • 复制代码

    C文件,核心是定时器做的。

    #include "bsp_pwm.h"
  • #include "bsp_led.h"
  • //Timer0 配置
  • static void App_Timer0Cfg(uint16_t u16Period, en_bt_cr_timclkdiv_t pclk_div, uint16_t u16CHxACompare, uint16_t DeadTime)
  • {
  •     uint16_t                   u16CntValue;
  •     uint8_t                    u8ValidPeriod;
  •     stc_bt_mode23_cfg_t        stcBtBaseCfg;
  •     stc_bt_m23_compare_cfg_t   stcBtPortCmpCfg;
  •     stc_bt_m23_adc_trig_cfg_t  stcBtTrigAdc;
  •     stc_bt_m23_dt_cfg_t        stcBtDeadTimeCfg;
  •         stc_bt_m23_bk_input_cfg_t  stcBtBrakeCfg;
  •        
  •     DDL_ZERO_STRUCT(stcBtBaseCfg);
  •     DDL_ZERO_STRUCT(stcBtPortCmpCfg);
  •     DDL_ZERO_STRUCT(stcBtTrigAdc);
  •     DDL_ZERO_STRUCT(stcBtDeadTimeCfg);
  •     Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE);   //Base Timer外设时钟使能      
  •         
  •     stcBtBaseCfg.enWorkMode    = BtWorkMode3;              //三角波模式
  •     stcBtBaseCfg.enCT          = BtTimer;                  //定时器功能,计数时钟为内部PCLK
  •     stcBtBaseCfg.enPRS         = pclk_div;//BtPCLKDiv16;   //PCLK/x 分频
  •     //stcBtBaseCfg.enCntDir    = BtCntUp;                  //向上计数,在三角波模式时只读
  •     stcBtBaseCfg.enPWMTypeSel  = BtComplementaryPWM;       //互补输出PWM
  •     stcBtBaseCfg.enPWM2sSel    = BtSinglePointCmp;         //单点比较功能
  •     stcBtBaseCfg.bOneShot      = FALSE;                    //循环计数
  •     stcBtBaseCfg.bURSSel       = FALSE;                    //上下溢更新
  •    
  •     Bt_Mode23_Init(TIM0, &stcBtBaseCfg);                   //TIM0 的模式23功能初始化
  •    
  •     Bt_M23_ARRSet(TIM0, u16Period, TRUE);                  //设置重载值,并使能缓存
  •     Bt_M23_CCR_Set(TIM0, BtCCR0A, u16CHxACompare);         //设置比较值A,(PWM互补模式下只需要设置比较值A)
  •    
  •     stcBtPortCmpCfg.enCH0ACmpCtrl   = BtPWMMode2;          //OCREFA输出控制OCMA:PWM模式2
  •     stcBtPortCmpCfg.enCH0APolarity  = BtPortPositive;      //正常输出
  •     stcBtPortCmpCfg.bCh0ACmpBufEn   = TRUE;                //A通道缓存控制
  •     stcBtPortCmpCfg.enCh0ACmpIntSel = BtCmpIntNone;        //A通道比较控制:无
  •    
  •     stcBtPortCmpCfg.enCH0BCmpCtrl   = BtPWMMode2;          //OCREFB输出控制OCMB:PWM模式2(PWM互补模式下也要设置,避免强制输出)
  •     stcBtPortCmpCfg.enCH0BPolarity  = BtPortPositive;      //正常输出
  •     //stcBtPortCmpCfg.bCH0BCmpBufEn   = TRUE;              //B通道缓存控制使能
  •     stcBtPortCmpCfg.enCH0BCmpIntSel = BtCmpIntNone;        //B通道比较控制:无
  •                
  •     Bt_M23_PortOutput_Cfg(TIM0, &stcBtPortCmpCfg);         //比较输出端口配置
  •         stcBtBrakeCfg.bEnBrake = TRUE;  /*刹车使能*/
  •         stcBtBrakeCfg.enBkCH0AStat = BtCHxBksLow; /*IO输出为低*/
  •         stcBtBrakeCfg.enBkCH0BStat = BtCHxBksLow; /*IO输出为低*/
  •         Bt_M23_BrakeInput_Cfg(TIM0, &stcBtBrakeCfg);
  •        
  •     u8ValidPeriod = 1;                                     //事件更新周期设置,0表示三角波每半个周期更新一次,每+1代表延迟半个周期
  •     Bt_M23_SetValidPeriod(TIM0,u8ValidPeriod);             //间隔周期设置
  •    
  •     stcBtDeadTimeCfg.bEnDeadTime      = TRUE;
  •     stcBtDeadTimeCfg.u8DeadTimeValue  = DeadTime;
  •     Bt_M23_DT_Cfg(TIM0, &stcBtDeadTimeCfg);             //死区配置
  •    
  •     u16CntValue = 0;
  •    
  •     Bt_M23_Cnt16Set(TIM0, u16CntValue);                    //设置计数初值
  •    
  •     Bt_ClearAllIntFlag(TIM0);                              //清中断标志
  •     Bt_Mode23_EnableIrq(TIM0,BtUevIrq);                    //使能TIM0 UEV更新中断
  •     EnableNvic(TIM0_IRQn, IrqLevel0, TRUE);                //TIM0中断使能   
  • }
  • //端口配置初始化
  • static void BSP_Timer0PortCfg(void)
  • {
  •     stc_gpio_cfg_t             stcTIM0Port;
  •    
  •     //结构体初始化清零
  •     DDL_ZERO_STRUCT(stcTIM0Port);
  •    
  •     Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //GPIO 外设时钟使能
  •   
  •     stcTIM0Port.enDir  = GpioDirOut;
  •    
  •     Gpio_Init(GpioPortA, GpioPin0, &stcTIM0Port);
  •     Gpio_SetAfMode(GpioPortA,GpioPin0,GpioAf7);            //PA00设置为TIM0_CHA
  •    
  •     Gpio_Init(GpioPortA, GpioPin1, &stcTIM0Port);
  •     Gpio_SetAfMode(GpioPortA,GpioPin1,GpioAf3);            //PA01设置为TIM0_CHB
  • }
  • /*带死区的周期4ms的互补PWM*/
  • void BSP_PWM_Config(void)
  • {          
  •         App_Timer0Cfg(6000, BtPCLKDiv16,3000,0x80);  //Timer0 配置:周期 6000(T= 4ms); 通道A比较值2400; 通道B比较值互补模式不需要设置   
  •     BSP_Timer0PortCfg();                                    //Timer0 Port端口配置   
  •         Bt_M23_EnPWM_Output(TIM0, TRUE, FALSE);              //TIM0 端口输出使能  
  •     Bt_M23_Run(TIM0);                             //TIM0 运行
  • }
  • /*带死区的2路互补pwm输出(250ms+150usHighPuls)*/
  • void BSP_2Comp_PWM_Config(void)
  • {
  •         uint16_t BCompare = 100; // 理论计算值为15
  •         App_Timer0Cfg(23700, BtPCLKDiv256, 23700 - BCompare, 0x80);  // 通道B比较值互补模式不需要设置   
  •     BSP_Timer0PortCfg();                                  //Timer0 Port端口配置      
  •     Bt_M23_EnPWM_Output(TIM0, TRUE, FALSE);    //TIM0 端口输出使能  
  •     Bt_M23_Run(TIM0);                          //TIM0 运行
  • }
  • /*duty : 0~99*/
  • void BSP_PWM_SetDuty(uint8_t duty)
  • {                       
  •         Bt_M23_CCR_Set(TIM0, BtCCR0A, 6000 - 6000*duty/100); //设置通道A比较值
  • }
  • /*******************************************************************************
  • * TIM0中断服务函数
  • ******************************************************************************/
  • void Tim0_IRQHandler(void)
  • {
  •     //Timer0 模式23 更新中断
  •     if(TRUE == Bt_GetIntFlag(TIM0, BtUevIrq))
  •     {  
  •         Bt_ClearIntFlag(TIM0,BtUevIrq);  //清中断标志               
  •     }
  • }
  • 复制代码

    欢迎留言点赞!