for(j=0;j<1140;j++);
}
voidtime2ms(void)//T0定时器初始化
{
TMOD=0x01;//T0工作方式1
/*2ms定时设置*/
time0_0=65536-time0*fosc/12;//计算初值
TH0=(time0_0/256);//装定时器0初值
TL0=(time0_0%256);
TR0=1;//启动定时器0
ET0=1;//打开定时器0中断
EA=1;//打开总中断
}
/*定时器0中断服务子程序,定时用于AD转换
1s约转换3次,8路信号约3s时间
为了时间充裕5s采集一次电能信号*/
voidtime0_int(void)interrupt1
{
TH0=(time0_0/256);//重装定时器0初值
TL0=(time0_0%256);
TIME[0]++;
if(TIME[0]==250)//250*2ms=500ms=0.5s时间到
{
TIME[0]=0;//到0.5s时TIME[0]清0
TIME[1]++;//TIME[1]加1内存的0.5秒的整数倍
}
}
voidICL7135(void)//启动8路AD转换
{
uchari,j;
STAT7135=1;//7135启动端使能启动AD转换
CD4051=CD4051&0xf0;//设置CD4051的第一路信号输入AD
for(j=0;j<=7;j++)//8路循环测量
{
i=CD4051&0xf0;//读P1口的状态保护高位
CD4051=j|i;//通过j调节多路开关的转换
STAT7135=1;//7135启动端使能启动AD转换
i=busy;//读7135的正在转换忙端
do{i=busy;}while(busy==0);//忙端为0时等待直到开始转换
do{i=busy;}while(busy==1);//忙端为1时正在转换等待
STAT7135=0;//7135禁止AD转换
do{i=ADP2;}while((ADP2&0x010)!
=0x010);//读7135的D5,直到D5为1
if((ADP2&0x010)==0x010)//D5为1开始读AD转换结果
{
//STAT7135=0;
ADBUF[j*5]=ADP0&0x0f;//读7135的万位
do{i=ADP2;}while((ADP2&0x08)!
=0x08);//读7135的D4,直到D4为1
ADBUF[1+j*5]=ADP0&0x0f;//读7135的千位
do{i=ADP2;}while((ADP2&0x04)!
=0x04);//读7135的D3,直到D3为1
ADBUF[2+j*5]=ADP0&0x0f;//读7135的百位
do{i=ADP2;}while((ADP2&0x02)!
=0x02);//读7135的D2,直到D2为1
ADBUF[3+j*5]=ADP0&0x0f;//读7135的十位
do{i=ADP2;}while((ADP2&0x01)!
=0x01);//读7135的D1,直到D1为1
ADBUF[4+j*5]=ADP0&0x0f;//读7135的个位
//ADBUF[0]=j+1;//路号
//Max7221Display(&ADBUF[j*5]);//当频率慢时可以显示AD转换的结果
}
}
}
voidSAVE(void)//电能处理保存
{
uchark,i;
ulongkk,kk1,kk2;
if(TIME[1]<120)//小于1分钟时120*0.5=60s简单加
{
for(k=0;k<=7;k++)//8路电能循环存储
{
while(page_rd(k*5,5,&BUF[0])==0);//读原来的电能各路5位数字
for(i=0;i<=4;i++)
{
BUF[i]=BUF[i]+ADBUF[i+k*5];//本次的电能和原来的电能求和
}
while(page_wr(k*5,5,&BUF[0])==0);//存新的总电能
}
}
if(TIME[1]==120)//等于1分钟时做电度数的处理
{
TIME[1]=0;
for(k=0;k<=7;k++)//8路电能循环转换成电度数存储
{
while(page_rd(k*5,5,&BUF[0])==0);//读原来的电能各路5位数字
for(i=0;i<=4;i++)
{
BUF[i]=BUF[i]+ADBUF[i+k*5];//本次的电能和原来的电能求和
}
while(page_wr(k*5,5,0)==0);//清寄存的电能
kk=(ulong)BUF[0]*10000+(ulong)BUF[1]*1000+(ulong)BUF[2]*100+(ulong)BUF[3]*10+(ulong)BUF[4];
//把电能转化为千瓦时即度
while(page_rd(100+k*2,2,&BUF[0])==0);//读上次余数
kk=kk*jishu+(ulong)BUF[0]*100+(ulong)BUF[1];//(jishu*1000)/(10000*12*60)=jishu/7200
kk1=kk/7200;//取电度数
kk2=kk%7200;//kk1为电度数kk2余数
BUF[0]=(uchar)(kk2/100);//分两部分存储电度的余数100为界
BUF[1]=(uchar)(kk2%100);
while(page_wr(100+k*2,2,&BUF[0])==0);//电度的存余数
while(page_rd(50+k*5,5,&BUF[0])==0);//读原来电度数
kk1=kk1+(ulong)BUF[0]*10000+(ulong)BUF[1]*1000+(ulong)BUF[2]*100+(ulong)BUF[3]*10+(ulong)BUF[4];
//原来的电度和新的电度数相加
BUF[0]=(uchar)(kk1/10000);//万
BUF[1]=(uchar)((kk1%10000)/1000);//千
BUF[2]=(uchar)(((kk1%10000)%1000)/100);//百
BUF[3]=(uchar)((kk1%100)/10);//十
BUF[4]=(uchar)((kk1%100)%10);//个
while(page_wr(50+k*5,5,&BUF[0])==0);//存新电度数
DISPBUF[0]=k+1;//显示户号
DISPBUF[1]=0xf;//显示2个F
DISPBUF[2]=0xf;
DISPBUF[3]=BUF[0];//显示此时电度数
DISPBUF[4]=BUF[1];
DISPBUF[5]=BUF[2];
DISPBUF[6]=BUF[3];
DISPBUF[7]=BUF[4];
Max7221Display(&DISPBUF[0]);//送显示
delay(20);//延时
}
}
}
/*-----------------------------------------------
调用方式:
voidstart_bit(void)
函数说明:
开始位
-----------------------------------------------*/
voidstart_bit(void)
{
SCL=1;_nop_();
SDA=1;_nop_();
SDA=0;_nop_();
SCL=0;_nop_();
}
/*-----------------------------------------------
调用方式:
voidstop_bit(void)
函数说明:
停止位
-----------------------------------------------*/
voidstop_bit(void)
{
SDA=0;_nop_();
SCL=1;_nop_();
SDA=1;_nop_();
}
/*-----------------------------------------------
调用方式:
voidmast_ack(void)
函数说明:
主答函数
-----------------------------------------------*/
voidmast_ack(void)
{
SCL=0;_nop_();
SDA=0;_nop_();
SCL=1;_nop_();
SCL=0;_nop_();
SDA=1;_nop_();
}
/*-----------------------------------------------
调用方式:
write_8bit(ucharch)
函数说明:
写一个字节(8位)数据
-----------------------------------------------*/
bitwrite_8bit(ucharch)
{
uchari=8;
bitfan_w;
SCL=0;_nop_();
while(i--)
{
SDA=(bit)(ch&0x80);_nop_();
ch<<=1;
SCL=1;_nop_();
SCL=0;_nop_();
}
SDA=1;_nop_();
SCL=1;_nop_();
fan_w=SDA;
SCL=0;_nop_();
return(fan_w);
}
/*----------------------------------------------
调用方式:
ucharread24c16(uintaddress,uchar*shu)
函数说明:
读24c16指定地址数据(字节读)
-----------------------------------------------*/
ucharread24c16(uintaddress,uchar*shu)
{
uchardatardata;
uchari=8;
EA=0;//避免与串口通讯等中断冲突
start_bit();
if(write_8bit(0xA0)!
=0){
stop_bit();EA=1;return(0);
}
if(write_8bit(address)!
=0){
stop_bit();EA=1;return(0);
}
start_bit();
if(write_8bit(0xA1)!
=0){
stop_bit();EA=1;return(0);
}
while(i--)
{
rdata<<=1;
SCL=1;_nop_();
if(SDA)rdata|=0x01;
SCL=0;_nop_();
}
stop_bit();
EA=1;
*shu=rdata;
return
(1);
}
/*-----------------------------------------------
调用方式:
voidwrite24c16(uintaddress,ucharddata)
函数说明:
写数据到24c16的指定地址(字节写)
-----------------------------------------------*/
ucharwrite24c16(uintaddress,ucharddata)
{
EA=0;//避免与串口通讯等中断冲突
start_bit();
if(write_8bit(0xA0)!
=0){
stop_bit();EA=1;return(0);
}
if(write_8bit(address)!
=0){
stop_bit();EA=1;return(0);
}
if(write_8bit(ddata)!
=0){
stop_bit();EA=1;return(0);
}
stop_bit();
EA=1;
return
(1);
}
/*-----------------------------------------------
调用方式:
voidpage_wr(uintfirstw_ad,uintcounter,uintdata*firstr_ad)
函数说明:
页面写函数,firstw_ad为写入字节单元的首地址,
*firstr-ad为被写入数据所在首地址指针
counter为写入数据字节数
-----------------------------------------------*/
ucharpage_wr(uintfirstw_ad,uintcounter,uchar*firstr_ad)
{
uchardata*ufirstr_ad;
ufirstr_ad=firstr_ad;
start_bit();
if(write_8bit(0xA0)!
=0){
stop_bit();return(0);
}
if(write_8bit(firstw_ad)!
=0){
stop_bit();return(0);
}
while(counter--)
{
if(write_8bit(*ufirstr_ad)!
=0){
stop_bit();return(0);
}
ufirstr_ad++;
}
stop_bit();
return
(1);
}
/*-----------------------------------------------
调用方式:
voidpage_rd(uintfirstrd_ad,uintcount,uintfirstwr_ad)
函数说明:
页面读函数,firstrd-ad为所读字节首地址,count为读字节数
*ufirstwr-ad为读出数据存储首地址指针
-----------------------------------------------*/
ucharpage_rd(uintfirstrd_ad,uintcount,uchar*firstwr_ad)
{
ucharj=8;
uchardata*ufirstwr_ad;
ufirstwr_ad=firstwr_ad;
start_bit();
if(write_8bit(0xA0)!
=0){
stop_bit();return(0);
}
if(write_8bit(firstrd_ad)!
=0){
stop_bit();return(0);
}
start_bit();
if(write_8bit(0xA1)!
=0){
stop_bit();return(0);
}
while(count--)
{
uchari=8;
while(i--)
{
(*ufir