电路大致都介绍完啦,下面开始先把程序附近来,由于我是在三相程序里面改动的,因此会有些突如其来的注释,不必管他
#include <STC12C5A60S2.H>
#include <intrins.h> /*use _nop_() function*/
#define uchar unsigned char
#define uint unsigned int
#define ADC_FLAG 0X10
#define S1_S0 0x40 //P_SW1.6
#define S1_S1 0x80 //P_SW1.7
sbit SD1 = P3^3; //第一桥臂,和P13对应同一块ir2104
sbit LED1 = P1^5;
sbit LED2 = P1^6;
sbit LED3 = P1^7;
sbit LED4 = P3^4;
sbit key1 = P0^0; //ok
sbit key2 = P2^0; //+
sfr P_SW1 = 0xA2; //外设功能切换寄存器1
uint Vout=0;
uint Iout = 0; //输出电压
uint V1=0;
uint I1 = 0;
uint sum = 0;
uint Vref = 0;
uchar block = 175;
uchar log = 0;
uchar lag = 0;
uchar snm = 0;
uint get = 0;
uint got = 0;
float R = 9.998;
float Vin = 5.08;
float Vget;
float Rfu;
bit busy;
void delay();
void Key_1_();
void Key_2_();
void init_pca();
void init_timer();
void SendData(uchar dat);
void SendString(char *s);
/**********************************************************
函数说明: 延时程序
**********************************************************/
void delay(uchar t)
{
uint j;
uchar i;
for(i=0;i<t;i++)
for(j=0;j<1000;j++);
}
/**********************************************************
函数说明: pca计数器初始化函数
**********************************************************/
void init_pca(void)
{
CMOD=0x08;//计数器0的溢出为PCA计数器的时钟源,允许pca中断使能,PDF资料上错误
CCON=0x00;
CCAPM0=0x42;//8位PWM输出,无中断
CCAPM1=0x42;//8位PWM输出,无中断
CL=0x00;//清零pca计数器
CH=0x00;
CCAP0L=0; //初始化spwm输出的占空比
CCAP0H=0;
CCAP1L=0; //初始化spwm输出的占空比
CCAP1H=0;
CR=1;//运行pca计数器
}
/**********************************************************
函数说明: 计数器0初始化函数
**********************************************************/
void init_timer(void)
{
TMOD= 0x21;//
TH0 = 0XF7;//
TL0 = 0x7C; //T1的计数值低位
ACC = P_SW1;
ACC &= ~(S1_S0 | S1_S1); //S1_S0=0 S1_S1=0
P_SW1 = ACC; //(P3.0/RxD, P3.1/TxD)
SCON = 0x50; //8位可变波特率
AUXR=0xC0;//计数器均工作在1T模式。计数频率11.0592M
ET0 = 1; //开中计数器0断
TR0 = 1; //开启计数器0
TL1 = 0xD9; //设定定时初值
TH1 = 0xD9;
TR1 = 1; //定时器1开始工作
ES = 1; //使能串口中断
}
/**********************************************************
函数说明: 读ADC数值
**********************************************************/
uchar GetADC(uchar ch)
{ uint laji;
uint result=0;
ADC_CONTR=0x88|ch; //选择通道 开始AD转换
_nop_(); _nop_();
_nop_(); _nop_();
while(!ADC_FLAG); //查询ADC_FLOG是否置位1 转换结束
~ADC_FLAG; //Clear ADC interrupt flag//1111 0111 结束AD转换
laji=ADC_RESL;
result=ADC_RES;
return(result);
}
/**********************************************************
函数说明: ADC查询法 始化函数
**********************************************************/
void InitADC()
{ uchar a;
P1M1=0x07;
P1M0=0x00;
P1ASF=0X07;
//相应端口当ADC使用时,端口要置位 P10&P11
ADC_RES=0;
ADC_CONTR=0X80; //1000 0000 开电源,最低速
delay(50);
for(a=0;a<5;a++)
{
GetADC(0);
}
}
/**************************************
短延时
**************************************/
void delay5ms()
{
uchar i,v,k;
for(i=1;i>0;i--)
for(v=168;v>0;v--)
for(k=22;k>0;k--);
}
/**********************************************************
函数说明: 过流保护开启按键
**********************************************************/
void Key_1_()
{
if(key1==0)
{
delay(100);
if(key1==0)
{
SD1 = 1;
LED4 = 1;
delay(200);
LED4 = 0;
} delay(100);
}
}
/**********************************************************
函数说明: 模式选择按键
**********************************************************/
void Key_2_()
{
if(key2==0)
{
delay(100);
if(key2==0)
{
if(log<3)log+=1;
else log = 0;
LED4 = 1;
delay(200);
LED4 = 0;
}
delay(100);
}
}
/**********************************************************
函数说明: 调整电压
**********************************************************/
void VAdjust()
{ uchar a,b,c,d;
switch(lag)
{
case 0: I1 = GetADC(1); sum+=1;Iout +=I1;break;
case 1: ADC_CONTR=0X00;_nop_(); _nop_();_nop_(); _nop_();sum+=1;break;
case 2: V1 = GetADC(0); sum+=1; Vout +=V1;break;
case 3: ADC_CONTR=0X80;_nop_(); _nop_();_nop_(); _nop_();sum+=1;break;
}
if(sum >= 100)
{
sum = 0;
switch(lag)
{
case 0: Iout = Iout/50;
a = 48+Iout/1000;
b = 48+Iout%1000/100;
c = 48+Iout%100/10;
d = 48+Iout%10;
// SendData(e);
SendData(a);
SendData(b);
SendData(c);
SendData(d);
SendData('\n');
Vref = 119+ Iout/29
;
break;
case 1: break;
case 2: Vout = Vout/100;
a = 48+Vout/1000;
b = 48+Vout%1000/100;
c = 48+Vout%100/10;
d = 48+Vout%10;
// SendData(e);
SendData(a);
SendData(b);
SendData(c);
SendData(d);
SendData('\n');
if(Vout>Vref) //输出电压小于36V
{
if(block==255)
block=255;
else
block++;
}
else //输出电压大于36V
{
if(block==50)
block= 50;
else
block--;
} break;
case 3: break;
}
lag+=1;
if(lag>3) lag=0;
Vout = 0;
Iout = 0;
}
}
/**********************************************************
函数说明: 过流保护
**********************************************************/
void IAdjust()
{ uchar a,b,c,d;
switch(lag)
{
case 0: I1 = GetADC(1); sum+=1;Iout +=I1;break;
case 1: ADC_CONTR=0X00;_nop_(); _nop_();_nop_(); _nop_();sum+=1;break;
case 2: V1 = GetADC(0); sum+=1; Vout +=V1;break;
case 3: ADC_CONTR=0X80;_nop_(); _nop_();_nop_(); _nop_();sum+=1;break;
}
if(sum >= 100)
{
sum = 0;
switch(lag)
{
case 0: Iout = Iout/50;
a = 48+Iout/1000;
b = 48+Iout%1000/100;
c = 48+Iout%100/10;
d = 48+Iout%10;
// SendData(e);
SendData(a);
SendData(b);
SendData(c);
SendData(d);
SendData('\n');
if(Iout>=218)
{
snm+=1;
if(snm >=20)
SD1 = 0;
} Vref = 119+ Iout/29; break;
case 1: break;
case 2: Vout = Vout/100;
a = 48+Vout/1000;
b = 48+Vout%1000/100;
c = 48+Vout%100/10;
d = 48+Vout%10;
// SendData(e);
SendData(a);
SendData(b);
SendData(c);
SendData(d);
SendData('\n');
if(Vout>Vref) //输出电压小于36V
{
if(block==255)
block=255;
else
block++;
}
else //输出电压大于36V
{
if(block==50)
block= 50;
else
block--;
} break;
case 3: break;
}
lag+=1;
if(lag>3) lag=0;
Vout = 0;
Iout = 0;
}
}
/**********************************************************
函数说明: 负载识别
**********************************************************/
void KnowLoad(void)
{ uchar a,b,c,d;
switch(lag)
{
case 0: get = GetADC(2); sum+=1;got +=get;break;
case 1: ADC_CONTR=0X00;_nop_(); _nop_();_nop_(); _nop_();sum+=1;break;
case 2: V1 = GetADC(0); sum+=1; Vout +=V1;break;
case 3: ADC_CONTR=0X80;_nop_(); _nop_();_nop_(); _nop_();sum+=1;break;
}
if(sum >= 100)
{
sum = 0;
switch(lag)
{
case 0: got = got/100;
a = 48+got/1000;
b = 48+got%1000/100;
c = 48+got%100/10;
d = 48+got%10;
// SendData(e);
SendData(a);
SendData(b);
SendData(c);
SendData(d);
SendData('\n');
if(got>=240) Vref = 0;
else
{ if(got<=60) {Vget = (got+2)*0.02;
Rfu =Vget*R/Vin/(1-Vget/Vin)/2.0;
Vref = Rfu/0.02-3;
}
if(got>60 && got<100)
{ Vget = (got-3)*0.02;
Rfu =Vget*R/Vin/(1-Vget/Vin)/2.0;
Vref = Rfu/0.02+2;
}
if(got>=100)
{ Vget = (got-6)*0.02;
Rfu =Vget*R/Vin/(1-Vget/Vin)/2.0;
Vref = Rfu/0.02;
}
} break;
case 1: break;
case 2: Vout = Vout/100;
a = 48+Vout/1000;
b = 48+Vout%1000/100;
c = 48+Vout%100/10;
d = 48+Vout%10;
// SendData(e);
/* SendData(a);
SendData(b);
SendData(c);
SendData(d);
SendData('\n'); */
if(Vout>Vref) //输出电压小于36V
{
if(block==255)
block=255;
else
block++;
}
else //输出电压大于36V
{
if(block==50)
block= 50;
else
block--;
} break;
case 3: break;
}
lag+=1;
if(lag>3) lag=0;
Vout = 0;
Iout = 0;
}
}
/**********************************************************
函数说明: 主函数
**********************************************************/
void main(void)
{ LED1 = LED2 =LED3 =LED4 =0;
delay(255);delay(255);delay(255);
InitADC();
init_pca();
init_timer();
EA=1;//开总中断
while(1)//主循环
{
Key_2_();
// VAdjust();
switch(log)
{
case 1: break;
case 0: VAdjust();LED1 = 1;LED2 = LED3 = 0;break;
case 3: IAdjust();LED2 = 1;LED1 = LED3 = 0;Key_1_();break;
case 2: KnowLoad();LED3 = 1;LED1 = LED2 = 0;break;
}
}
}
/**********************************************************
函数说明: 定时器0中断
**********************************************************/
void int_timer0(void) interrupt 1//计数器1中断函数
{
CCAP0H=block;
CCAP1H=175;
}
/*----------------------------
UART 中断服务程序
-----------------------------*/
void Uart() interrupt 4 using 1
{
if (RI)
{
RI = 0; //清除RI位
P0 = SBUF; //P0显示串口数据
}
if (TI)
{
TI = 0; //清除TI位
busy = 0; //清忙标志
}
}
/*----------------------------
发送串口数据
----------------------------*/
void SendData(uchar dat)
{
while (busy); //等待前面的数据发送完成
ACC = dat; //获取校验位P (PSW.0)
busy = 1;
SBUF = ACC; //写数据到UART数据寄存器
}
/*----------------------------
发送字符串
----------------------------*/
void SendString(char *s)
{
while (*s) //检测字符串结束标志
{
SendData(*s++); //发送当前字符
}
}