目录
一、项目功能
1、实时采集交流电压和交流电流
2、通过采集的电压和电流计算出相应的电费
3、屏幕显示系统运行时间,交流电压、电流和电费
4、串口传输数据
资料下载地址:基于51单片机的自动抄表系统
二、仿真
由于图比较大,拆分成两个
三、程序
void delay_uint(uint q)
{
while(q--);
}
/********************************************************************
* 名称 : write_com(uchar com)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void write_com(uchar com)
{
e=0;
rs=0;
rw=0;
P0=com;
delay_uint(25);
e=1;
delay_uint(100);
e=0;
}
/********************************************************************
* 名称 : write_data(uchar dat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_data(uchar dat)
{
e=0;
rs=1;
rw=0;
P0=dat;
delay_uint(25);
e=1;
delay_uint(100);
e=0;
}
/********************************************************************
* 名称 : write_string(uchar hang,uchar add,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
write_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_string(uchar hang,uchar add,uchar *p)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
while(1)
{
if(*p == '\0') break;
write_data(*p);
p++;
}
}
/***********************lcd1602上显示特定的字符************************/
void write_zifu(uchar hang,uchar add,uchar date)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
write_data(date);
}
/***********************lcd1602上显示两位十进制数************************/
void write_1(uchar hang,uchar add,uint date)
{
disbuf[0] = date/10000;
disbuf[1] = date%10000/1000;
disbuf[2] = date%100/10;
disbuf[3] = date%10;
if(hang==1)
{
write_com(0x80+add);
write_data(0x30+date/10000);
write_data(0x30+date%10000/1000);
write_data('.');
write_data(0x30+date%100/10);
write_data(0x30+date%10);
cul = disbuf[0] * 10 + disbuf[1] ;
}
else if(hang == 3)
{
write_com(0x80+add);
write_data(0x30+date/10000);
write_data(0x30+date%10000/1000);
write_data(0x30+date%100/10);
write_data('.');
write_data(0x30+date%10);
voltage = disbuf[0] * 100 + disbuf[1] * 10 + disbuf[2];
}
}
void write_2(uchar hang,uchar add,int date)
{
if(hang==2)
{
write_com(0x80+0x40+add);
write_data(0x30+date/10000);
write_data(0x30+date%10000/1000);
write_data(0x30+date%1000/100);
write_data(0x30+date%100/10);
write_data(0x30+date%10);
}
else if(hang == 4)
{
write_com(0x80+0x40+add);
write_data(0x30+date/10000);
write_data(0x30+date%10000/1000);
write_data(0x30+date%1000/100);
write_data(0x30+date%100/10);
write_data(0x30+date%10);
}
}
/***********************lcd1602初始化设置************************/
void init_1602()
{
write_com(0x38); //
write_com(0x0c);
write_com(0x06);
delay_uint(1000);
write_string(1,0,"C: ");
write_string(1,8,"V:"); //显示度
// write_string(2,0," Rmb ");
}
/*延时函数*/
void delay_ms(uint n)
{
uchar i;
while(n--)
{
for(i=0;i<100;i++);
}
}
/*定时器T0初始化 */
void Init_T0()
{
TMOD=0x09;
TH0=0;
TL0=0;
}
/*数码管进行显示*/
void WriteByte(uchar dat)
{
// uchar i;
// for(i=0;i<8;i++)
// {
// DIN = ((dat<<i)&0x80)?1:0;
// CLK = 0;
// _nop_();
// CLK = 1;
// _nop_();
// }
}
void MAX7221_WRITE(uchar addr,uchar dat)
{
// CS = 0;
// WriteByte(addr);
// WriteByte(dat);
// CS = 1;
}
void MAX7221_Initial(void)
{
// MAX7221_WRITE(0x0A,0x07);
// MAX7221_WRITE(0x0B,0x07);
// MAX7221_WRITE(0x0C,0x01);
// MAX7221_WRITE(0x0F,0x00);
// MAX7221_WRITE(0x09,0xff);
}
void display(uchar *str)
{
// uchar i;
// for(i=0;i<8;i++)
// {
// MAX7221_WRITE(i+1,str[i]);
// }
}
/*A/D转换读取转换值*/
uint LTC1864_READ(void)
{
uchar i;
uint temp = 0;
CONV = 0;
CONV = 1;
_nop_();_nop_();_nop_();
CONV = 0;
SDO = 1;
for(i=0;i<16;i++)
{
SCK = 1;
_nop_();
SCK = 0;
_nop_();
if(i==0)
{
SDI=1;
}
if(i==1)
{
choose= !choose;
SDI=choose;
}
temp <<= 1;
if(SDO==1)
{
temp |= 0x0001;
}
}
CONV = 1;
return temp;
}
/*电流值进行数码管转换显示*/
void HEXTOBCD_I(uint temp)
{
write_1(1,2,temp);
}
/*电压值进行数码管转换显示*/
void HEXTOBCD_V(uint temp)
{
write_1(3,11,temp);
}
/*定时器T1初始化*/
void Time_T1(void)
{
TMOD=0x10;
TL1=0xb0;
TH1=0x3c;
IE=0x88;
TR1=1;
}
void delay_choose(int t)
{
Time_T1();
while(t--)
{
while(!TF1);
TF1=0;
TL1=0x3c;
TH1=0X88;
}
}
/*读取相位差方波正脉冲宽度*/
void Message_Width()
{
while(K);
TR0=1;
while(!K);
while(K);
TR0=0;
High=TH0;
Low=TL0;
}
/*串口初始化波特率为9600*/
void UART_init(void)
{
SCON = 0x50;//串口方式1
TMOD = 0x20;// 定时器使用方式2自动重载
TH1 = 0xFD;//9600波特率对应的预设数,定时器方式2下,TH1=TL1
TL1 = 0xFD;
TR1 = 1;//开启定时器,开始产生波特率
}
/*发送一个字符*/
void UART_send_byte(uchar dat)
{
SBUF = dat;
while (TI == 0);
TI = 0;
}
/*发送一个字符串*/
void UART_send_string(uchar *buf)
{
while (*buf != '\0')
{
UART_send_byte(*buf++);
}
}
/*电流显示及发送*/
void dianliu()
{
uchar vol_value[7];//定义串口通信数据缓冲数组
uint I;
I=(int)(t*30500);
HEXTOBCD_I(I);
display(disbuf);
delay_ms(10);
/*串口通信逐一发送电流值*/
UART_init();
UART_send_string(cur);
vol_value[0]=num[disbuf[0]%16];
UART_send_byte(vol_value[0]);
vol_value[1]=num[disbuf[1]%16];
UART_send_byte(vol_value[1]);
UART_send_byte(0x2E);
vol_value[2]=num[disbuf[2]%16];
UART_send_byte(vol_value[2]);
vol_value[3]=num[disbuf[3]%16];
UART_send_byte(vol_value[3]);
vol_value[4]=num[disbuf[4]%16];
UART_send_byte(vol_value[4]);
UART_send_byte(0x41);
UART_send_byte(0x0d);
UART_send_byte(0x0a);
}
/*电压显示及发送*/
void dianya()
{
int I;
uchar vol_value[7];//定义串口通信数据缓冲数组
I=(int)(t*5866);
voltage = I / 1000;
HEXTOBCD_V(I);
display(disbuf);
delay_ms(10);
/*串口通信逐一发送电压值*/
UART_init();
UART_send_string(vol);
vol_value[0]=num[disbuf[0]%16];
UART_send_byte(vol_value[0]);
vol_value[1]=num[disbuf[1]%16];
UART_send_byte(vol_value[1]);
vol_value[2]=num[disbuf[2]%16];
UART_send_byte(vol_value[2]);
UART_send_byte(0x2E);
vol_value[3]=num[disbuf[3]%16];
UART_send_byte(vol_value[3]);
vol_value[4]=num[disbuf[4]%16];
UART_send_byte(vol_value[4]);
UART_send_byte(0x56);
UART_send_byte(0x0d);
UART_send_byte(0x0a);
}
/*串口通信发送功率因数*/
void send_P()
{
uchar vol_value[7];//定义串口通信数据缓冲数组
uint X1,I;
double t=0;
Init_T0();
Message_Width();
X1=(High*256+TL0)/0.92;
t=(X1+t)/2;
/*串口通信逐一发送功率因数*/
t=t*0.000314;
I=abs(cos(t-0.147)*1000);
UART_init();
UART_send_string(pf);
vol_value[0]=num[I/1000];
UART_send_byte(vol_value[0]);
UART_send_byte(0x2E);
vol_value[0]=num[I%1000/100];
UART_send_byte(vol_value[0]);
vol_value[0]=num[I%100/10];
UART_send_byte(vol_value[0]);
vol_value[0]=num[I%10];
UART_send_byte(vol_value[0]);
UART_send_byte(0x0d);
UART_send_byte(0x0a);
UART_send_byte(0x0d);
UART_send_byte(0x0a);
}
void main()
{
Time_T1();
// MAX7221_Initial();
delay_ms(10);
LTC1864_READ();
init_1602();
while(1)
{
scan();
t= LTC1864_READ()*addo;//读取电流模拟量
dianliu();
//delay_ms(1000);//延时2s
t= LTC1864_READ()*addo;//读取电压模拟量
//delay_choose(40);
dianya();
send_P();
power += (cul * voltage / 500);
if(flag == 0)
dianfei += (cul * voltage / 5000);
else if(flag == 1)
dianfei += (cul * voltage / 1000);
write_2(2,0,power);
write_2(4,8,dianfei);
delay_choose(13);//延时2s
}
}