#include<reg51.h>
#include<math.h>
sbit select=P1^4;
sbit cfm=P1^5;
sbit g100=0;//继电器
sbit u_d=0;//电位器增加,减小模式
sbit inc=0;//增减脉冲
sbit lock=P1^3;//取样保持
uchar key_x=0;//键盘确认前值
uchar key_v=0;//键盘确认后值
bit key_0;//有无按键
bit auto_ok=0;//增益调节完成
float u_max=0;
float u_min=0;
float i_max=0;
float i_min=0;
float u2=0;//电压采样值平方和
float i2=0;//电流采样值平方和
float v_ef;//电压有效值
float i_ef;//电流有效值
float fi=0;//相位差
float lmd=0;//功率因素
float Py=0;//有功功率
float Ss=0;//视在功率
float Qw=0;//无功功率
uchar gain=1;//前端放大倍数
bit samp=0;//采样结束标志
bit wait_tw=0;
bit ad_ca=0;
bit caculate=0;
uchar count=0;//判断采样点数
uint u_ad[64]=0;//电压采样值
uint i_ad[64]=0;//电压采样值
uint tw=0;//相位差时间
uchar step=1;
void disp_welcome()
{ disp_str(0xe9,0,4,"欢迎使用");
disp_str(0xe9,1,0,"请选择测量...");
disp_str(0xe9,2,0,"1.电压相关量");
disp_str(0xe9,3,0,"2.电流相关量");
disp_str(0xe9,4,0,"3.功率相关量");
disp_str(0xe9,5,0,"4.谐波相关量");
disp_str(0xe9,6,0,"确认");
disp_str(0xe9,7,5,"工频表");
}
void disp_v()
{ clearp();
disp_str(0xe9,1,0,"电压测量");
disp_str(0xe9,2,0,"有效值");
disp_str(0xe9,3,0,"最大值");
disp_str(0xe9,4,0,"最小值");
disp_str(0xe9,0,4,"欢迎使用");
disp_str(0xe9,6,5,"工频表");
}
void disp_i()
{ clearp();
disp_str(0xe9,1,0,"电流测量");
disp_str(0xe9,2,0,"有效值");
disp_str(0xe9,3,0,"最大值");
disp_str(0xe9,4,0,"最小值");
disp_str(0xe9,0,4,"欢迎使用");
disp_str(0xe9,6,5,"工频表");
}
void disp_p()
{ clearp();
disp_str(0xe9,1,0,"功率测量");
disp_str(0xe9,2,0,"视在功率");
disp_str(0xe9,3,0,"有功功率");
disp_str(0xe9,4,0,"无功功率");
disp_str(0xe9,5,0,"功率因素");
disp_str(0xe9,0,4,"欢迎使用");
disp_str(0xe9,6,5,"工频表");
}
void disp_xb()
{ clearp();
disp_str(0xe9,1,0,"基波有效值");
disp_str(0xe9,2,0,"谐波有效值");
disp_str(0xe9,0,4,"欢迎使用");
disp_str(0xe9,6,5,"工频表");
}
disp_conf()
{ switch(key_v)
{ case1:disp_v();break;
case2:disp_i();break;
case3:disp_p();break;
case4:disp_xb();break;
}
}
void disp_select()
{ swith(key_x)
{ case0:disp_welcome();break;
case1:disp_welcome();disp_str(0xe9,2,0,"*");break;
case2:disp_welcome();disp_str(0xe9,3,0,"*");break;
case3:disp_welcome();disp_str(0xe9,4,0,"*");break;
case4:disp_welcome();disp_str(0xe9,5,0,"*");break;
}
}
void disp_waveform(uint *p)
{ uchar ii=0;
clearp();
disp_line(0xc5,117,0,1,1,239);
disp_line(0xc5,0,10,0,1,127);
disp_line(0xc5,57,10,0,1,239);
disp_str(0xe9,7,0,"0");
disp_str(0xe9,4,0,"0");
if(key_v==1)
disp_str(0xe9,1,0,"U/V");
else if(key_v==2)
disp_str(0xe9,7,14,"I/A");
disp_str(0xe9,7,0,"0");
for(;ii<0xff;ii+4)
disp_line(0xc5,((*p)*100/1024),ii+10,0,1,239);
}
void key()
{ if(select==0)
{ delay(100);
if(select==0)
{ key_x++;
if(key_x==5)
key_x=1;
disp_select();
}
}
if(cfm==0)
{ delay(100);
if(cfm==0)
{ key_v=key_x;
step=2;
key_0=1;
}
}
}
void cacu()
{ float u_ad_f=0.0f;//电压实际值
float i_ad_f=0.0f;//电流实际值
uchar roll=1;
if(ad_ca)
{ u_max=u_ad[0]*5.000f/1024*gain;
u_min=u_ad[0]*5.000f/1024*gain;
u_ad_f=u_ad[0]*5.000f/1024*gain;
i_max=i_ad[0]*5.000f/1024*gain;
i_min=i_ad[0]*5.000f/1024*gain;
i_ad_f=i_ad[0]*5.000f/1024*gain;
u2=u_ad_f*u_ad_f;
i2=i_ad_f*i_ad_f;
for(;roll<64;roll++)
{ u_ad_f=u_ad[roll]*5.000f/1024*gain;//电压电流实际值
i_ad_f=i_ad[roll]*5.000f/1024*gain;
if(u_ad_f>u_max)
u_max=u_ad_f;
else if(u_ad_f<u_min)
u_min=u_ad_f;
if(i_ad_f>i_max)
i_max=i_ad_f;
else if(i_ad_f<i_min)
i_min=i_ad_f;
u2+=u_ad_f*u_ad_f;//平方和
i2+=i_ad_f*i_ad_f;
}
v_ef=sqrt(u2/64);//有效值
i_ef=sqrt(i2/64);
}
else
{fi=tw*0.0000005*360/0.02;
lmd=cos(fi);//功率因素
Py=v_ef*i_ef*lmd;//有功功率
Ss=v_ef*i_ef;//视在功率
Qw=sqrt(Ss*Ss-Py*Ss);//无功功率
}
if(key_v==1)
{ ftos(v_ef,3);
disp_str(0xe9,2,7,c);
ftos(u_max,3);
disp_str(0xe9,3,7,c);
ftos(u_min,3);
disp_str(0xe9,4,7,c);
}
if(key_v==2)
{ ftos(i_ef,3);
disp_str(0xe9,2,7,c);
ftos(i_max,3);
disp_str(0xe9,3,7,c);
ftos(i_min,3);
disp_str(0xe9,4,7,c);
}
if(key_v==3)
{ ftos(Ss,3);
disp_str(0xe9,2,9,c);
ftos(Py,3);
disp_str(0xe9,3,9,c);
ftos(Qw,3);
disp_str(0xe9,4,9,c);
ftos(lmd,2);
disp_str(0xe9,5,9,c);
}
void powerup_ad()
{ ADC_CONTR=0x80;
P1ASF=0x07;
delay(1);
}
int tlcAD(uchar i)
{ uchar cn=0;
uint ADout=0;
cn=0xe0+i;
ADC_CONTR=cn;
delay 10us();
ADC_RES=0x00;
ADC_RESL=0x00;
ADC_CONTR|=0x08;
_nop_();
_nop_();
_nop_();
_nop_();
while(!(ADC_CONTR&0x10));
ADC_CONTR&=0xef;
ADout=ADC_RES*4+ADC_RESL;
return(ADout);
}
void send(uchar s_char)
{ SBUF=s_char;
while(TI==0);
TI=0;
}
void auto_gain()
{ if(u_max>4.9f)
{ send(0x02);
if(gain==10)
gain=5;
else if(gain==5)
{ if(gain==1)
disp_str(0xe9,6,7,"过量程!");
gain=1;
}
}
else if(u_max<0.18f)
{ send (0x01);
gain=25;
}
else auto_ok=1;
}
void main()
{ SCON=0x50;
brt=0xfd;
auxr=0x11;
tmod=0x61;
th0=0x00;
tl0=0x00;
th1=0xff;
tl1=0xff;
it0=1;
it1=1;
clearp();
disp_welcome();
send(0x03);
powerup_ad();
while(1)
{ if(step==1)
key();
else if(step==2)
{ if(key_0==1)
{ key_0=0;
disp_conf();
}
if(!samp)
{ ex0=1;
ea=1;
}
else
{ if(caculate)
{ caculate=0;
cacu();
}
if(!auto_ok)
auto_gain();
if(key_v==3)
{ if(wait_tw==0)
ex1=1;
}
else if(key_v==1|key_v==2)
{ if(select==0)
{delay(100);
if(select==0)
disp_waveform(u_ad);
}
if(cfm==0)
{delay(100);
if(select==0)
disp_waveform(i_ad);
}}}
}}}
void sample()interrupt0
{ lock=1;
u_ad[count]=tlcAD(0);
I_ad[count]=tlcAD(1);
lock=0;
if((++count)==64)//采样是否完成
{ ex0=0;
ADC_CONTR&=0xe7;//关AD
count=0;
samp=1;
caculate=1;
ad_ca=1;
}
}
void r_ph(void)interrupt2
{ ex1=0;
wait_tw=1;
tr0=1;
tr1=1;
et1=1;
}
void s_ph(void)interrupt3
{ et1=0;
tr0=0;
tr1=0;
tw=th0*256+tl0;
caculate=1;
th0=0x00;
tl0=0x00;
th1=0xff;
tl1=0xff;
}
///////////////////////////////////////////////
#define LCDIO P0
#define PA XBYTE[0xFCFF]//[0xFF00]
#define PB XBYTE[0xFDFF]//[0xFF01]
#define PC XBYTE[0xFEFF]//[0xFF02]
#define COM XBYTE[0xFFFF]//[0xFF03]
sbit LCD1602_RS=P1^0;
sbit LCD1602_RW=P1^1;
sbit LCD1602_EN=P1^2;
sbit wr=P3^6;
sbit rd=P3^7;
sbit cs=P2^7;
sbit BF=P0^7;
unsigned char table1[]={ 0x03,0x07,0x0f,0x1f,0x1f,0x1f,0x1f,0x1f,
0x18,0x1E,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
0x07,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
0x10,0x18,0x1c,0x1E,0x1E,0x1E,0x1E,0x1E,
0x0f,0x07,0x03,0x01,0x00,0x00,0x00,0x00,
0x1f,0x1f,0x1f,0x1f,0x1f,0x0f,0x07,0x01,
0x1f,0x1f,0x1f,0x1f,0x1f,0x1c,0x18,0x00,
0x1c,0x18,0x10,0x00,0x00,0x00,0x00,0x00}; //心图案
/**************定义函数************************/
void LCD_write_command(unsigned char command); //写入指令函数
void LCD_write_dat(unsigned char dat); //写入数据函数
void LCD_set_xy( unsigned char x, unsigned char y ); //设置显示位置函数
void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat); //显示一个字符函数
void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s); //显示字符串函数
void LCD_init(void); //初始化函数
void delay_nms(unsigned int n); //延时函数
void delay();
void init_8255();
void write_8255PA(uchar ch);
/**************8255初始化******************************/
void init_8255()
{ cs=1;
cs=0;