dspic33系列编程之PWM篇

来源:互联网 发布:安卓淘宝没有指纹支付 编辑:程序博客网 时间:2024/06/17 05:16
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)
{ ;
}
}
原创粉丝点击