|
#include "P33ep32mc202.h"
/** CONFIGURATION **************************************************/
_FGS(0xff);//写保护关闭
_FOSCSEL(0xfb);//双速振荡器启动使能 PWM锁定 带PLL的主振荡器
_FOSC(0xdd);//禁止时钟切换 外设引脚多次配置 SOC2数字IO XT晶振模式
_FWDT(0x7f);//看门狗禁止
_FPOR(0xff);//I2C1被映射到SAD1/SCL1引脚 欠压复位_
_FICD(0x03);//禁止JTAG 通过PGEC1 PGED1通讯
void initAdc1(void);
void Delayus(unsigned int);
int i, j;
unsigned char flag;
float DC_BUSSENSE,DC_DAT;
int PFC_CURRENT;
float ACV_SENSE;
int ADCValues[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int PWMDAT;
float ADC_DAT;
float IAC; //IAC=K3*PFC_CURRENT
void __attribute__((__interrupt__, auto_psv)) _ADC1Interrupt(void);
struct _pid{
float SetSpeed; //定义设定值
float ActualSpeed; //定义实际值
float err; //定义偏差值
float err_next; //定义上一个偏差值
float err_last; //定义最上前的偏差值
float Kp,Ki,Kd; //定义比例、积分、微分系数
}pid;
void PID_init()
{
pi_dc.SetSpeed=0.0;
pi_dc.ActualSpeed=0.0;
pi_dc.err=0.0;
pi_dc.err_last=0.0;
pi_dc.err_next=0.0;
pi_dc.Kp=0.22;
pi_dc.Ki=0.015;
pi_dc.Kd=0.0;
pi_cs.SetSpeed=0.0;
pi_cs.ActualSpeed=0.0;
pi_cs.err=0.0;
pi_cs.err_last=0.0;
pi_cs.err_next=0.0;
pi_cs.Kp=0.35;
pi_cs.Ki=0.01;
pi_cs.Kd=0.0;
}
float VDCcompute(float speed,float CurrentValue)
{
pi_dc.SetSpeed=speed;
pi_dc.err=pi_dc.SetSpeed-CurrentValue;
float incrementSpeed=pi_dc.Kp*(pi_dc.err-pi_dc.err_next)+pi_dc.Ki*pi_dc.err-pid.Kd*(pi_dc.err-2*pi_dc.err_next+pi_dc.err_last);
pi_dc.ActualSpeed+=incrementSpeed;
pi_dc.err_last=pi_dc.err_next;
pi_dc.err_next=pi_dc.err;
return pi_dc.ActualSpeed;
}
float PFCcompute(float speed,float CurrentValue)
{
pi_cs.SetSpeed=speed;
pi_cs.err=pi_cs.SetSpeed-CurrentValue;
float incrementSpeed=pi_cs.Kp*(pi_cs.err-pi_cs.err_next)+pi_cs.Ki*pi_cs.err-pid.Kd*(pi_cs.err-2*pi_cs.err_next+pi_cs.err_last);
pi_cs.ActualSpeed+=incrementSpeed;
pi_cs.err_last=pi_cs.err_next;
pi_cs.err_next=pi_cs.err;
return pi_cs.ActualSpeed;
}
void System_Init(void)
{
TRISB &= ~0xfc00;//RB10-RB15 清零
IOCON1 = 0x0000;//GPIO 模块控制 PWMxH PWMxL引脚
}
int main(void)
{
// The CPU clock frequency is Fcy = Fosc/2 = 40 MHz.
CLKDIVbits.PLLPRE = 0; /* N2 = 2 7.3728M/2=3.6864*/
PLLFBD = 41; /* M = 43 3.6864*43=158.5*/
CLKDIVbits.PLLPOST = 0; /* N1 = 2 158.5M/2=79.25M */
OSCTUN = 0;
/* Initiate Clock Switch to Primary Oscillator with PLL (NOSC = 0x3) */
__builtin_write_OSCCONH(0x03);
__builtin_write_OSCCONL(0x01);
while (OSCCONbits.COSC != 0x3);
while (_LOCK == 0); /* Wait for PLL lock at 40 MIPS */
Delayus(5000);
System_Init();
Timer3_Timing_Init();
initAdc1();
OC1_Init();
PID_init();
while(1)
{
}
}
/*-----------------------------------------------
名称:ADC初始化程序
编写: Transmigration
日期:2016-09-12
修改:无
内容: 10位 4路同时采样ADC配置
------------------------------------------------*/
void initAdc1(void)
{
/* ADC端口配置 */
ANSELA = ANSELB = 0x0000;
ANSELAbits.ANSA0 = 1; // Ensure AN0/RA0 is analog
ANSELAbits.ANSA1 = 1; // Ensure AN1/RA1 is analog
ANSELBbits.ANSB0 = 1; // Ensure AN2/RB0 is analog
ANSELBbits.ANSB3 = 1; // Ensure AN5/RB3 is analog
/* Initialize and enable ADC module */
AD1CON1bits.FORM=0b00;//AD结果为整数
AD1CON1bits.SIMSAM=1; //同时采样
AD1CON1bits.ASAM=1; //上次采样结束立即开始采样
AD1CON1bits.SSRCG=0;
AD1CON1bits.SSRC=0b010; //定时器3比较结束立即开始采样
//AD12B=1;//12位ADC
AD1CON2bits.VCFG=0b000; //参考电压为VCC电压
AD1CON2bits.CHPS=0b11; //同时采样4个通道
AD1CON2bits.SMPI=0b00001;//每完成2次采样产生ADC中断
AD1CON3 = 0x0007;//AD转换时钟TP(ADCS<7:0> + 1) =8 Tcy*8 = TAD=0.00000025*8=0.0000002 TCON=12*0.0000002=0.0000024=416K
//FCY=Fsoc/2;TCY=1/Fcy; TCY=1/40M=0.000000025 采样同期TAD=(Tcy*(ADCS+1));转换时间TCON=(12*TAD)或14*TAD
AD1CON4 = 0x0000;
AD1CSSH = 0x0000;
AD1CSSL = 0x0000;
AD1CHS0bits.CH0SA = 5; // Select AN5 for CH0 +ve input
AD1CHS0bits.CH0NA = 0; // Select Vref- for CH0 -ve input
AD1CHS123bits.CH123SA = 0; // Select AN0 for CH1 +ve input
AD1CHS123bits.CH123NA = 0; // Select Vref- for CH1/CH2/CH3 -ve inputs
/*ADC中断设置*/
IFS0bits.AD1IF = 0; // Clear the A/D interrupt flag bit
IEC0bits.AD1IE = 1; // Do Not Enable A/D interrupt
_AD1IP=6;
AD1CON1bits.ADON = 1; // Turn on the A/D converter
}
/*-----------------------------------------------
名称:Timer3定时器初始化
编写: Transmigration
日期:2016-09-12
修改:无
内容: 产生80KHZ时钟信号
* 提供ADC中断触发信号
* 提供OCx比较输出信号
* 改变RP3的值可改变OCx频率
------------------------------------------------*/
void Timer3_Timing_Init(void)//定时器模式
{
T3CONbits.TON = 0;//禁止16位Timer3
T3CONbits.TCS = 0;//内部时钟Fosc/2
T3CONbits.TGATE = 0;//门控时间累加位 禁止
T3CONbits.TCKPS = 0x00;//输入时钟预分频比1:1
T3CONbits.TSIDL = 0;//空闲模式继续工作
TMR3 =0x0000;//初始值*/
PR3 =500;//周期值80KHZ FCY=FOC/2=80M/2=40M/500=80K
_T3IP = 0x01; // 优先级1
IFS0bits.T3IF = 0; // Timer3中断标志状态位 清零
IEC0bits.T3IE = 0; // Timer3中断允许位 禁止
T3CONbits.TON = 1;//启动使能16位Timer3
}
/*-----------------------------------------------
名称:输出比较PWM初始化程序
编写: Transmigration
日期:2016-09-12
修改:无
内容: 配置OC1 OC2 为边沿PWM模式带故障保护
* 改变OC1R OC2R 可改变占空比
------------------------------------------------*/
void OC1_Init(void)
{
RPOR4bits.RP43R = 0b010000;//RP43连接到输出比较 1 输出 OC1映射到RP引脚
RPOR4bits.RP42R = 0b010001;//RP43连接到输出比较 2 输出
OC1CON1bits.OCM = 0b000;//禁止输出比较
OC1CON1bits.OCSIDL = 0;//空闲模式继续
OC1CON1bits.OCTSEL = 0b001;//比较Timer3的时钟源
//OC1CON1bits.OCTSEL = 0;//比较Timer2的时钟源
OC1CON2bits.SYNCSEL=0b01101;//Timer3 同步或触发 OC1
//OC1CON2bits.SYNCSEL=0b01100;//Timer2 同步或触发 OC1
OC1R = 0;//输出比较寄存器
OC1RS =0;
OC2CON1bits.OCM = 0b000;//禁止输出比较
OC2CON1bits.OCSIDL = 0;//空闲模式继续
OC2CON1bits.OCTSEL = 0b001;//比较Timer3的时钟源
//OC2CON1bits.OCTSEL = 0b000;//比较Timer2的时钟源
OC2CON2bits.SYNCSEL=0b01101;//同步Timer3同步或触发 OC2
// OC2CON2bits.SYNCSEL=0b01100;//同步Timer2同步或触发 OC2
OC2R = 0;//输出比较寄存器
OC2RS = 0;
//OC1 CO2 故障设置
RPINR11bits.OCFAR=36; //选择映射脚到RP36即RB4为故障输入低电平有效
OC1CON1bits.ENFLTA=1;
OC1CON1bits.OCFLTA=1;
OC1CON2bits.FLTTRIEN=0; //发生故障输出状态由FLTOUT决定
OC1CON2bits.FLTOUT=0; //发生故障输出为低电平
// OC1CON2bits.FLTMD=1; //PWM故障为无效模式
OC2CON1bits.ENFLTA=1; //使能a 故障输入
OC2CON1bits.OCFLTA=1; //产生故障条件
OC2CON2bits.FLTTRIEN=0; //发生故障输出状态由FLTOUT决定
OC2CON2bits.FLTOUT=0; //发生故障输出为低电平
IPC0bits.OC1IP = 0x02;// 中断优先级2
IFS0bits.OC1IF = 0;// 清中断
IEC0bits.OC1IE = 0;// 禁止中断
IPC1bits.OC2IP = 0x01;// 中断优先级2
IFS0bits.OC2IF = 0;// 清中断
IEC0bits.OC2IE = 0;// 禁止中断
OC1CON1bits.OCM = 0b110;//将OC1引脚初始化为低电平,在OCx引脚上产生连续输出脉冲
OC2CON1bits.OCM = 0b110;//将OC1引脚初始化为低电平,在OCx引脚上产生连续输出脉冲
}
void Delayus(unsigned int delay)
{
for (i = 0; i < delay; i++)
{
asm volatile ("repeat #39");
asm volatile ("nop");
}
}
/* ADC1中断,每2次采样产生一次中断40KHZ*/
void __attribute__((interrupt, no_auto_psv)) _AD1Interrupt(void)
{
IFS0bits.AD1IF = 0; // Clear the ADC1 Interrupt Fla
PFC_CURRENT = ADC1BUF2; // Read the AN1 conversion result
//电压PI补偿器计算
if(flag==0)
{
DC_BUSSENSE = ADC1BUF1; //Read the AN0 输出直流检
DC_DAT=VDCcompute(740.0,DC_BUSSENSE);
}
//读取ACV瞬时值
if(flag==1)
{
ACV_SENSE = ADC1BUF3;// Read the AN2 conversion result
}
//进入电流环PI补偿器计算
if(DC_BUSSENSE>=780)
{ OC1R=OC2R=1;}
else
{
ADC_DAT=(ACV_SENSE*DC_DAT);
ADC_DAT=(ADC_DAT/495)*4.1;
PWMDAT=PFCcompute(ADC_DAT, PFC_CURRENT);
if(PWMDAT<=65) PWMDAT=65;
PWMDAT=500-PWMDAT;
OC1R=OC2R=PWMDAT;
}
flag++;
if(flag>=2)flag=0;
}
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
如果天空是黑暗的,那就摸黑生存;
如果发出声音是危险的,那就保持沉默;
如果自觉无力发光,那就蜷伏于牆角。
但是,不要习惯了黑暗就为黑暗辩护;
也不要为自己的苟且而得意;
不要嘲讽那些比自己更勇敢的人。
我们可以卑微如尘土,但不可扭曲如蛆虫。
|