标题:
PIC30F4011 SPWM波 光伏逆变代码 2009年电赛资料
[打印本页]
作者:
a450047941
时间:
2018-7-9 10:45
标题:
PIC30F4011 SPWM波 光伏逆变代码 2009年电赛资料
2009年电赛代码
单片机源程序如下:
#include<p30f4011.h>
#include "oled.h"
//配置位
_FOSC(CSW_FSCM_OFF&XT_PLL4);
_FWDT(0X0000);//关狗
_FBORPOR(PBOR_OFF&MCLR_EN);
_FGS(CODE_PROT_OFF);
#define FCY 8000000
#define FPWM 17050
#define FLAG PORTDbits.RD3
#define AN0 ADCBUF1
#define AN1 ADCBUF2
#define AN2 ADCBUF3
#define AN3 ADCBUF0
unsigned long get_hz_1=0,get_hz_2=0,get_hz_3=0,get_hz_4=0,sum_int = 0;
unsigned int hz_flag=0,hz_count=0,change_flag = 0,change_hz_flag = 0;
unsigned int HZ_count = 0;//用来记录0.25步进hz在数组中的位置
float hz = 0,sum_float = 0;
unsigned long int M = 850;
unsigned int z0=0;//z1=99;z2 = 199;
unsigned long sum0 = 0,sum1 = 0,sum2 = 0,sum3 = 0;//AN0-3
unsigned long ave0 = 0,ave1 = 0,ave2 = 0,ave3 = 0;//AN0-3
unsigned long true0 = 0,true1 = 0,true2 = 0,true3 = 0;
unsigned int ADC_count = 0,ADC_display = 0,ADC_flag = 0;
unsigned int timer1[201] = {
593,592,591,591,590,589,589,588,587,587,
586,585,585,584,584,583,582,582,581,580,
580,579,578,578,577,577,576,575,575,574,
573,573,572,572,571,570,570,569,569,568,
567,567,566,566,565,564,564,563,563,562,
561,561,560,560,559,558,558,557,557,556,
556,555,554,554,553,553,552,552,551,550,
550,549,549,548,548,547,546,546,545,545,
544,544,543,543,542,541,541,540,540,539,
539,538,538,537,537,536,535,535,534,534,
533,533,532,532,531,531,530,530,529,529,
528,528,527,526,526,525,525,524,524,523,
523,522,522,521,521,520,520,519,519,518,
518,517,517,516,516,515,515,514,514,513,
513,512,512,511,511,510,510,509,509,508,
508,507,507,506,506,506,505,505,504,504,
503,503,502,502,501,501,500,500,499,499,
498,498,498,497,497,496,496,495,495,494,
494,493,493,492,492,492,491,491,490,490,
489,489,488,488,488,487,487,486,486,485,
485,
}; //步进0.05hz 45-55hz 201个点
unsigned long int sin[300]={
0,17,35,53,71,89,106,124,142,159,
177,194,212,229,246,263,280,297,313,330,
346,363,379,395,410,426,441,457,472,487,
501,516,530,544,558,572,585,598,611,624,
637,649,661,673,685,696,708,719,729,740,
750,760,770,779,789,798,806,815,823,831,
839,846,854,860,867,873,880,885,891,896,
901,906,910,914,917,921,924,926,929,931,
932,934,934,935,935,935,934,933,932,930,
928,925,922,918,914,910,905,899,894,887,
881,873,866,857,849,840,830,820,809,798,
787,775,762,749,736,722,707,692,677,661,
645,628,611,593,575,556,538,518,499,479,
458,438,417,395,374,352,329,307,284,261,
238,215,191,168,144,120,96,72,48,24,
0,17,35,53,71,89,106,124,142,159,
177,194,212,229,246,263,280,297,313,330,
346,363,379,395,410,426,441,457,472,487,
501,516,530,544,558,572,585,598,611,624,
637,649,661,673,685,696,708,719,729,740,
750,760,770,779,789,798,806,815,823,831,
839,846,854,860,867,873,880,885,891,896,
901,906,910,914,917,921,924,926,929,931,
932,934,934,935,935,935,934,933,932,930,
928,925,922,918,914,910,905,899,894,887,
881,873,866,857,849,840,830,820,809,798,
787,775,762,749,736,722,707,692,677,661,
645,628,611,593,575,556,538,518,499,479,
458,438,417,395,374,352,329,307,284,261,
238,215,191,168,144,120,96,72,48,24,
};
void System_Init(void)
{
TRISD = 0x0000;
TRISDbits.TRISD0 = 1;
TRISDbits.TRISD1 = 1; //RD0,RD1输入捕捉
TRISDbits.TRISD3 = 0;//flag out
TRISB = 0x00FF;//0为输出,1为输入
TRISBbits.TRISB4 = 0;
TRISBbits.TRISB5 = 0;
TRISBbits.TRISB6 = 0;
TRISBbits.TRISB7 = 0;
TRISBbits.TRISB8 = 0;
//PORTB = 0x0000;
//PWMCON1 = 0x0000;//通用IO
TRISE = 0x0000;//设置输出
}
void delay_ams(int ms)//????
{
while(ms--)
{
unsigned int i;
for(i=0;i<8000;i++);
}
}
void Timer3_init()
{
TMR3 = 0;//定时器3计数寄存器TMR3=0
T3CON = 0x0000;//使用内部时钟
T3CONbits.TCKPS = 1; //预分频比为1:8
T3CONbits.TON = 1;//打开定时器TMR3
IEC0bits.T1IE = 0;
}
void init_hz() //IC1(RD0) IC2(RD1) 启用
{
IC1CON = 0x0043;//每1次捕捉事件中断一次,每一个上升沿捕捉一次
IC2CON = 0x0023;
IC1CONbits.ICTMR = 0;//选用Timer3
IC2CONbits.ICTMR = 0;
IFS0bits.IC1IF = 0;//清IC6中断标志
IEC0bits.IC1IE = 1;//使能中断
IC1CONbits.ICM = 3;
//IPC0bits.IC1IP = 6;//设置中断优先级6
}
void InitPWM() //PWM
{
LATE = 0X0000 ;
TRISE = 0X0000 ; //??RE0-RE5??????PWM1-PWM3
PTPER = FCY / FPWM ; //20KHzPWM?? 不减1会有毛刺
PWMCON1 = 0x0077; //PWM I/O ???????????
//??1H ?1L ???I/0?
SEVTCMP = PTPER ; //368*4 PWM ?????? 101110000
PWMCON2 = 0x0F00; //????????????1?16
OVDCON = 0XFF00; //bit 15-8 POVD4H-POVD1L? PWM ?????1 = PWMxx I/O ??????? PWM ?????
PDC1 = 100*4 ; //PWM1 ??? 0.136(PDC1/PTPER/2)
PDC2 = 100*4 ; //PWM2 ??? 0.136
PDC3 = 400;
PTCON = 0x8000 ; //??PWM????1?1????1:1???????
//PTCON? PWM ??????? bit 7-4 PTOPS<3:0>? PWM ??????????? bit 3-2 PTCKPS<1:0>? PWM ?????????????
//bit 1-0 PTMOD<1:0>? PWM ???????
DTCON1bits.DTA = 0x01; //????
// DTCON1bits.DTB =1;
}
void Timer1()//??????
{
T1CONbits.TON = 0;//?????
T1CON = 0x0000;//???? ???1:1 ?????? FOSC/4
T1CONbits.TSYNC = 1;//????
IEC0bits.T1IE = 1;//??Timer1????
INTCON1 |= 0X8000;//?????? NSTDIS?1
IPC0bits.T1IP = 0x07;//?????7
T1CONbits.TON = 1;//?????
PR1 = 533;//8000000/(300*HZ);//0 7.5K 8000000/(150*hz) 150个点
//533.33 是300点50hz的值 800是200点50hz
}//FCY/HZ
void ADC_Init()//
{
TRISBbits.TRISB0 = 1;//输入
TRISBbits.TRISB1 = 1;//输入
TRISBbits.TRISB2 = 1;//输入
TRISBbits.TRISB3 = 1;//输入
ADCON1 = 0x0000;//无符号整数格式
ADCON1bits.SSRC = 7;//内部计数器结束采样并开始转换(自动转换)
ADCON1bits.ASAM = 1;//采样自动 上次转换结束后开始
ADCON2 = 0x020C;//参考电压配置AVDD,AVSS;4个采样/转换完成后产生中断
ADCON3 = 0x1f1f; //使用系统时钟,相邻两次采样之间的时间间隔为31Tad,Tad=32Tcy
ADCHS = 0x0003;////通道0负输入是Vref-,通道0正输入是AN3
ADPCFGbits.PCFG3 = 0;//AN2模拟模式,禁止端口读取输入,A/D采样引脚电压
ADPCFGbits.PCFG2 = 0;//AN2模拟模式,禁止端口读取输入,A/D采样引脚电压
ADPCFGbits.PCFG1 = 0;//AN1模拟模式,禁止端口读取输入,A/D采样引脚电压
ADPCFGbits.PCFG0 = 0;//AN1模拟模式,禁止端口读取输入,A/D采样引脚电压
ADCSSL = 0x0000;//不对输入引脚扫描
IPC2bits.ADIP = 6; //设置AD转换中断优先级为7
IEC0bits.ADIE = 1; //使能AD转换完成中断
ADCON1bits.ADON = 1; //启动ADC 0未启动
}
void delete_hz()
{
/****消除溢出标志****/
if(IC1CONbits.ICOV == 1)
{
IC1CONbits.ICM = 0;
while(IC1CONbits.ICBNE!=0);
IC1CONbits.ICM = 3;
}
}
void PWM_adjust(unsigned int want,unsigned int min)
{
if((ave0 > want+5) && (M < 1020))//普通稳压调节
{
M++;
}
if((ave0 < want-5) && (M > 20))
M--;
}
int main()
{
System_Init();
OLED_Init(); //初始化OLED
OLED_Clear();
disn(4,0,2);disn(5,0,0);disn(6,0,1);disn(7,0,8);disn(8,0,16);disn(9,0,17);disn(10,0,18);disn(11,0,19);//2018电赛(汉字需要左右俩个格子)
disn(1,1,11);disn(2,1,12);disn(3,1,0);disn(4,1,20);disn(5,1,0);disn(6,1,0);disn(7,1,0);disn(8,1,13);//U=0.000V
disn(1,2,14);disn(2,2,12);disn(3,2,0);disn(4,2,20);disn(5,2,0);disn(6,2,0);disn(7,2,0);disn(8,2,15);//I=0.000A
disn(1,3,21);disn(2,3,12);disn(8,3,22);disn(9,3,23);//f=00.00Hz
ADC_Init();
init_hz();
Timer3_init();
InitPWM();
Timer1();
while(1)
{
/**********计算hz的大小**********/
if(hz_flag == 0)
{
hz = 1000000.0/(get_hz_2 -get_hz_1);
sum_float = sum_float + hz;
hz_count++;
}
if(hz_count==8)
{
hz_count = 0;
sum_float = sum_float/8;
sum_int = (int)(sum_float*100);//显示测量频率小数点后俩位
disn(3,3,sum_int/1000);
disn(4,3,sum_int/100%10);
disn(5,3,20);
disn(6,3,sum_int/10%10);
disn(7,3,sum_int%10);
HZ_count = (sum_float*100 -4500) /5 +0.5; //计算在数组中的位置,加0.5为了四舍五入
if(HZ_count <0)
HZ_count = 0;
if(HZ_count >200)
HZ_count = 200;
change_hz_flag =1;
sum_float = 0;
sum_int = 0;
}
/********根据hz改变定时器1的值改变spwm的频率********/
if(change_hz_flag ==1)
{
PR1 = timer1[HZ_count];
change_hz_flag ==0;
}
/***************ADC采样的值计算*****************/
if(ADC_flag == 0)
{
sum0 = sum0 + AN0;
sum1 = sum1 + AN1;
// sum2 = sum2 + AN2;
// sum3 = sum3 + AN3;
ADC_count++;
}
if(ADC_count==16)
{
ave0 = sum0>>4; //512 2.5V
ave1 = sum1>>4;
if((ave1 >= 135) || (M<=20 && ave0<515)) //过流保护
{
M = 0;
delay_ams(1000);
M = 100;
//PWMCON1 = 0x0077;
}
//ave2 = sum2>>5;
// ave3 = sum3>>5;
ADC_count=0;
ADC_flag=1;
}
if(ADC_display == 200)
{
ADC_display = 0;
true0 = ave0*4.8828;
disn(3,1,true0/1000);disn(5,1,true0/100%10);
disn(6,1,true0/10%10);disn(7,1,true0%10);
disn(11,3,M/100); disn(12,3,M/10%10); disn(13,3,M%10);
}
ADC_display++;
delete_hz();
}
}
void __attribute__((__interrupt__, auto_psv))_IC1Interrupt(void)
{
IFS0bits.IC1IF = 0;
z0 = 5;
if(hz_flag==0)
{
get_hz_1 = IC1BUF;
hz_flag = 1;
}
else if (hz_flag == 1)
{
get_hz_2 = IC1BUF;
hz_flag =0;
TMR3= 0;
}
// IFS0bits.IC1IF = 0;
}
void __attribute__((__interrupt__, auto_psv)) _T1Interrupt(void)//功能:key调节rate和pi控制
{
IFS0bits.T1IF = 0;
if(z0<150)
{
PDC1 = 0;
PDC2 = ((M*sin[z0])>>10);
z0++;
}
else
{
PDC1 = ((M*sin[z0])>>10);
PDC2 = 0;
z0++;
if(z0==300) {z0=0;}
}
}
void __attribute__((__interrupt__,no_auto_psv))_ADCInterrupt(void)//ADC 6.3Khz 4.2us PDC 调节 10.48us(加计算) 6.56
{
// PORTDbits.RD3 = 1;
IFS0bits.ADIF=0; //清AD转换中断标志位
if(ADC_flag == 1)
{
PWM_adjust(640,536);//3.08 3.14(5v)-643 2.616---535.75--536
sum0 = 0;
sum1 = 0;
//sum2 = 0;
//sum3 = 0;
ADC_count=0;ADC_flag = 0;
}
//PORTDbits.RD3 = 0;
}
复制代码
所有资料51hei提供下载:
guangfu.zip
(95.51 KB, 下载次数: 43)
2018-7-9 10:42 上传
点击文件名下载附件
光伏逆变代码
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1