基于51单片机自动抄表系统

目录

一、项目功能

二、仿真

三、程序

一、项目功能

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
	}
}

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

森旺电子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值