DSP

dspic33系列编程之PWM篇

2019-07-13 19:15发布

dspic33F系列共有3个PWM模块,还有一个额外的其它引脚形成的PWM4,PWM4需要额外设置。PWM1~PWM3是通用的告诉PWM模块,每个PWM模块有两个输出口,以输出PWM信号,芯片引脚上用PWMxL和PWMxH(x为1~3)表示。 PWM模块在很多领域都得到使用:AC/DC转换器,DC/DC转换器,UPS,电池管理,逆变器等等。以下是dipic33F的PWM功能介绍:可触发ADC中断、有四种工作模式(独立模式,互补模式,推挽模式,冗余模式),可产生过流保护及中断,可产生特殊事件中断(定时)等等功能。本PWM最高频率可达250khz,并由以下寄存器控制其功能:PTCON、PTCON2、PTPER,SEVTCMP,MDC,PWMCONX,PDCX,PHASEX,DTRX,ALTDTRX, SDCX,SPHASE,TRGCONX,IOCONX,FCLCONX,TRIGX,STRIGX,LEBCONX,PWMCAP这些。有X代表其控制的是1~3的单独工作。 各个寄存器每位功能及其作用见官方资料。以下是具体的例子,实现各种配合。   例子1:利用PWM产生器产生固定占空比30%,并PWMH,PWML互补的信号。存在3%的死区。     代码:void  pwm_init()                     {    PTPER=0X0800;                  //时基设为56KHZ,作为周期 PDC3=0X0267;                    //占空比设置为30% IOCON3bits.PENH=1;    //pwm3h高电平有效   IOCON3bits.PENL=1;         //pwm3L高电平有效         IOCON3bits.PMOD=3; //互补模式 DTR3=0X003D;                //死区设为3% PTCONbits.PTEN=1;           //开启PWM模块 } 例子2:利用pwm及其中断产生每个周期更新的SPWM驱动信号,设正弦表已知,为sintab 代码:void  pwm_init() { PTPER=0x0800; //设置PWM周期56Khz  PTCON2bits.PCLKDIV=0; //设置预分频为1:4,Tcy=16*Tsy,频率为56KHZ  PWMCON1bits.MDCS=0; //占空比由各自MDC决定 PDC1=0x0100; //初始化占空比为0          IOCON1bits.PENH=1;  IOCON1bits.PENL=1;  IOCON1bits.PMOD=0; //互补模式  PWMCON1bits.IUE=1; //立即改变占空比 PWMCON1bits.TRGIEN=1; //允许中断 TRIG1=0x0800;       //每个周期内产生中断 PTCONbits.SEIEN=1; //特殊事件触发  PTCONbits.PTEN=1; //开启PWM模块 }    void  pwm_isrinit() { CORCONbits.IPL3=0; SRbits.IPL=0;    //CPU优先级设为0 IPC23bits.PWM1IP=2;    IEC5bits.PWM1IE=1;       //设置PWM中断1优先级 }  void __attribute__((interrupt, no_auto_psv)) _PWM1Interrupt() { PDC1=sinetab[i]; IFS5bits.PWM1IF=0; i++; if(i>280) i=0; } 例子3:利用PI调节与SPWM实现闭环控制(应用AD中断) void pwm_init() { PTPER=0x0800;    //设置PWM周期56Khz PTCON2bits.PCLKDIV=0;   //设置预分频为1:4,Tcy=16*Tsy,频率为56KHZ PWMCON1bits.MDCS=0;          //占空比由各自MDC决定 PDC1=0x0000;                        //初始化占空比为0 IOCON1bits.PENH=1; IOCON1bits.PENL=1; IOCON1bits.PMOD=0;             //互补模式 TRIG1=0x0008;                 //触发AD采样的时间 // PWM1H rising and falling edges trigger LEB counter (240ns) // LEB is applied to current limit input LEBCON1 = 0xC4F0; // PWM 限流设置 FCLCON1bits.FLTMOD = 0; // Latched Fault Mode FCLCON1bits.CLMOD = 1; // 限流使能 FCLCON1bits.CLSRC = 1; // Current Limit Source is Fault 2 FCLCON1bits.CLPOL = 0; // Current Limit Source is Active High
TRGCON1bits.TRGDIV = 0; // Trigger ADC every PWM Period TRGCON1bits.TRGSTRT = 0; // Wait 0 PWM cycles before generating first PWM trigger      PTCONbits.SEIEN=1; PTCONbits.PTEN=1;               //开启PWM模块 } void ad_init() {     ADCONbits.SLOWCLK = 1;          // ADC辅助始终     ADCONbits.FORM = 0;             // 输出格式右对齐  ADCONbits.EIE = 1;              // 2次转换后中断  ADCONbits.ORDER = 0;            // 偶数通道优先 ADCONbits.SEQSAMP = 0;          // Simultaneus Sampling Enabled  ADCONbits.ASYNCSAMP = 1; // Asynchronous Sampling Enableed  ADCONbits.ADCS = 4;             // 时钟设为5分频 ADSTAT = 0;                     // 清除数据状态位         ADPCFGbits.PCFG1 = 0;           // AN1 反激1电流 ADPCFGbits.PCFG2 = 0; // AN2 反激2电流     ADCPC0bits.TRGSRC0 = 4;    // AN0 and AN1 由PWM1触发  } void isrinit() { CORCONbits.IPL3=0; SRbits.IPL=0;            //CPU优先级设为0 IPC27bits.ADCP0IP = 6;          // Set ADC Pair0 Interrupt Priority (2nd highest priority) IFS6bits.ADCP0IF = 0;     // Clear ADC Pair0 Interrupt Flag  IEC6bits.ADCP0IE = 1;           // Enable ADC Pair0 Interrupt at start  } void __attribute__((interrupt, no_auto_psv)) _ADCP0Interrupt() { int duty; fbcurrent[0]=(ADCBUF1 << 5); PDC1=dctab[i]+PIcalculate(1,1,sintab[i],fbcurrent[0]); if(duty>UK_DC_MAX) duty=UK_DC_MAX; PDC1=duty; i++; if(i>280) i=0; IFS6bits.ADCP0IF = 0;                   // Clear ADC Interrupt Flag } int main() { pwminit(); adinit(); ADCONbits.ADON = 1;       // Enable the ADC Module early for ADC Settling Time
isrinit(); while(1) { ; } } 分享: