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)
{ ;
}
}