多用户电子式电能表的设计程序

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include<c8051f360.h>
#include <intrins.h>
#include <stdio.h>
#define AT24C16 0xa0 //AT24C16 地址
sbit DIN=P1^0; /*定义P1口*/
sbit CLK=P1^1;
sbit YH1=P2^0; /*定义P2口*/
sbit YH2=P2^1;
sbit YH3=P2^2;
sbit YH4=P2^3;
sbit YH5=P2^4;
sbit YH6=P2^5;
sbit YH7=P2^6;
sbit YH8=P2^7;
unsigned char a,b,c,d,e,f,g,h,m,i,j,k,n,z;
unsigned char zf[]={0x88,0xeb,0x4c,0x49,0x2b,0x19,0x18,0xcb,0x08,0x09,0xff,0x7f}; unsigned char yh[8][8]={{0x00,0x00,0x00,0x00,0x00,0x00,0xb,0x1},
{0x00,0x00,0x00,0x00,0x00,0x00,0xb,0x2},
{0x00,0x00,0x00,0x00,0x00,0x00,0xb,0x3},
{0x00,0x00,0x00,0x00,0x00,0x00,0xb,0x4},
{0x00,0x00,0x00,0x00,0x00,0x00,0xb,0x5},
{0x00,0x00,0x00,0x00,0x00,0x00,0xb,0x6},
{0x00,0x00,0x00,0x00,0x00,0x00,0xb,0x7},
{0x00,0x00,0x00,0x00,0x00,0x00,0xb,0x8}};
#define NOP() _nop_() /* 定义空指令 */
#define _Nop() _nop_() /* 定义空指令 */
sbit SCL=P1^6; //I2C 时钟
sbit SDA=P1^3; //I2C 数据
bit ack; /*应答标志位*/
/*******************************************************
起动总线函数
函数原型: void Start_I2c();
功能: 启动I2C总线,即发送I2C起始条件.
*******************************************************/
void Start_I2c()
{
SDA=1; /*发送起始条件的数据信号*/
_Nop();
SCL=1;
_Nop(); /*起始条件建立时间大于4.7us,延时*/
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0; /*发送起始信号*/
_Nop(); /* 起始条件锁定时间大于4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0; /*锁住I2C总线,准备发送或接收数据 */
_Nop();
_Nop();
}
/*******************************************************
结束总线函数
函数原型: void Stop_I2c();
功能: 结束I2C总线,即发送I2C结束条件.
*******************************************************/
void Stop_I2c()
{
SDA=0; /*发送结束条件的数据信号*/
_Nop(); /*发送结束条件的时钟信号*/
SCL=1;
_Nop();
_Nop(); /*结束条件建立时间大于4μs*/
_Nop();
_Nop();
_Nop();
SDA=1; /*发送I2C总线结束信号*/
_Nop();
_Nop();
_Nop();
_Nop();
}
/*******************************************************
字节数据发送函数
函数原型: void SendByte(UCHAR c);
功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使ack=0)发送数据正常,
ack=1; ack=0表示被控器无应答或损坏。

*******************************************************/
void SendByte(unsigned char c)
{
unsigned char BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/
{
if((c<<BitCnt)&0x80)SDA=1; /*判断发送位*/
else SDA=0;
_Nop();
SCL=1; /*置时钟线为高,通知被控器开始接收数据位*/
_Nop();
_Nop(); /*保证时钟高电平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0;
}
_Nop();
_Nop();
SDA=1; /*8位发送完后释放数据线,准备接收应答位*/
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA==1)ack=0;
else ack=1; /*判断是否接收到应答信号*/
SCL=0;
_Nop();
_Nop();
}
/*******************************************************
字节数据接收函数
函数原型: UCHAR RcvByte();
功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),发完后请用应答函数应答从机。

*******************************************************/ unsigned char RcvByte()
{
unsigned char retc;
unsigned char BitCnt;
retc=0;
SDA=1; /*置数据线为输入方式*/
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_Nop();
SCL=0; /*置时钟线为低,准备接收数据位*/
_Nop();
_Nop(); /*时钟低电平周期大于4.7μs*/
_Nop();
_Nop();
_Nop();
SCL=1; /*置时钟线为高使数据线上数据有效*/
_Nop();
_Nop();
retc=retc<<1;
if(SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */ _Nop();
_Nop();
}
SCL=0;
_Nop();
_Nop();
return(retc);
}
/*******************************************************
应答子函数
函数原型: void Ack_I2c(bit a);
功能: 主控器进行应答信号(可以是应答或非应答信号,由位参数a决定) *******************************************************/
void Ack_I2c(bit a)
{
if(a==0)SDA=0; /*在此发出应答或非应答信号 */
else SDA=1;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop(); /*时钟低电平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0; /*清时钟线,钳住I2C总线以便继续接收*/
_Nop();
_Nop();
}
/*******************************************************
向有子地址器件发送多字节数据函数
函数原型: bit ISendStr(UCHAR sla,UCHAR suba,ucahr *s,UCHAR no);
功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。

如果返回1表示操作成功,否则操作有误。

*******************************************************/
bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
unsigned char i;
Start_I2c(); /*启动总线*/
SendByte(sla); /*发送器件地址*/
if(ack==0)return(0);
SendByte(suba); /*发送器件子地址*/
if(ack==0)return(0);
for(i=0;i<no;i++)
{
SendByte(*s); /*发送数据*/
if(ack==0)return(0);
s++;
}
Stop_I2c(); /*结束总线*/
return(1);
}
/*******************************************************
向有子地址器件读取多字节数据函数
函数原型: bit RecndStr(UCHAR sla,UCHAR suba,ucahr *s,UCHAR no);
功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。

如果返回1表示操作成功,否则操作有误。

*******************************************************/
bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
unsigned char i;
Start_I2c(); /*启动总线*/
SendByte(sla); /*发送器件地址*/
if(ack==0)return(0);
SendByte(suba); /*发送器件子地址*/
if(ack==0)return(0);
Start_I2c(); /*重新启动总线*/
SendByte(sla+1);
if(ack==0)return(0);
for(i=0;i<no-1;i++)
{
*s=RcvByte(); /*发送数据*/
Ack_I2c(0); /*发送就答位*/
s++;
}
*s=RcvByte();
Ack_I2c(1); /*发送非应位*/
Stop_I2c(); /*结束总线*/
return(1);
}
/*******************************************************
延时函数
函数原型: delay();
功能: 延时3ms.
*******************************************************/
delay()
{
unsigned m,n;
for(m=300;m>0;m--)
for(n=512;n>0;n--);
}
/*******************************************************
读函数
函数原型: void Read24();
功能: 多字节读取数据.
*******************************************************/
void Read24()
{IRcvStr(AT24C16, 0 , &yh[0][0], 6);delay();
IRcvStr(AT24C16, 10 , &yh[1][0], 6);delay();
IRcvStr(AT24C16, 20 , &yh[2][0], 6);delay();
IRcvStr(AT24C16, 30 , &yh[3][0], 6);delay();
IRcvStr(AT24C16, 40 , &yh[4][0], 6);delay();
IRcvStr(AT24C16, 50 , &yh[5][0], 6);delay();
IRcvStr(AT24C16, 60 , &yh[6][0], 6);delay();
IRcvStr(AT24C16, 70 , &yh[7][0], 6);delay();
}
/******************************************************* 写函数
函数原型: void Write24();
功能: 多字节写取数据.
*******************************************************/ void Write24()
{ISendStr(AT24C16, 0 , &yh[0][0], 6);delay();
ISendStr(AT24C16, 10 , &yh[1][0], 6);delay();
ISendStr(AT24C16, 20 , &yh[2][0], 6);delay();
ISendStr(AT24C16, 30 , &yh[3][0], 6);delay();
ISendStr(AT24C16, 40 , &yh[4][0], 6);delay();
ISendStr(AT24C16, 50 , &yh[5][0], 6);delay();
ISendStr(AT24C16, 60 , &yh[6][0], 6);delay();
ISendStr(AT24C16, 70 , &yh[7][0], 6);delay();
}
/******************************************************* 计数及进位函数
函数原型: void jinwei ();
功能: 对相应用户产生的脉冲进行加1计数并进位.
*******************************************************/ void jinwei (unsigned char z)
{
yh[z][0]++;
if(yh[z][0]==0xa)
{yh[z][0]=0x0;
yh[z][1]++;}
if (yh[z][1]==0xa)
{yh[z][1]=0x0;
yh[z][2]++;}
if (yh[z][2]==0xa)
{yh[z][2]=0x0;
yh[z][3]++;}
if (yh[z][3]==0xa)
{yh[z][3]=0x0;
yh[z][4]++;}
if (yh[z][4]==0xa)
{yh[z][4]=0x0;
yh[z][5]++;}
if(yh[z][5]==0xa)
{yh[z][0]=0x0;
yh[z][1]=0x0;
yh[z][2]=0x0;
yh[z][3]=0x0;
yh[z][4]=0x0;
yh[z][5]=0x0;}
}
/******************************************************* 用户扫描函数
函数原型: void saomiao();
功能: 对各用户口进行扫描,判断是否有脉冲产生.
*******************************************************/ void saomiao()
{
if(YH1==0)
{
if(a==1)
{
a=0;
z=0;
jinwei(z);
}
}
else
a=1;
if(YH2==0)
{
if(b==1)
{
b=0;
z=1;
jinwei(z);
}
}
else
b=1;
if(YH3==0)
{
if(c==1)
c=0;
z=2;
jinwei(z);
}
}
else
c=1;
if(YH4==0)
{
if(d==1)
{
d=0;
z=3;
jinwei(z);
}
}
else
d=1;
if(YH5==0)
{
if(e==1)
{
e=0;
z=4;
jinwei(z);
}
}
else
e=1;
if(YH6==0)
{
if(f==1)
{
f=0;
z=5;
jinwei(z);
}
}
else
f=1;
if(YH7==0)
{
if(g==1)
g=0;
z=6;
jinwei(z);
}
}
else
g=1;
if(YH8==0)
{
if(h==1)
{
h=0;
z=7;
jinwei(z);
}
}
else
h=1;
}
/*******************************************************
主函数
函数原型: void main();
功能: 实现读写函数、计数及进位函数、数码管显示等函数的调用,初始化相应功能.
*******************************************************/
void main()
{
SFRPAGE=0x0F;
P1MDIN=0XFF; //P1口初始化
P1MDOUT=0XEF; //推挽输出
P2MDIN=0xFF;
P2MDOUT=0xfF;
XBR1=0x40; //交叉开关使能
PCA0MD=0x00; //关闭看门狗clear Watchdog
PSCTL=0x03; //写FLESH允许
OSCXCN=0x67; //用外晶振
OSCICN=0x0; //内部振荡器使能,8分频
CLKSEL=0x01; //系统时钟选内部高频振荡器,不预分频
Read24();
TMOD=0x01; //设置定时器0为工作方式1
TH0=0x28;
TL0=0x00;
EA=1; //开总中断
ET0=1; //开定时器0中断
TR0=1; //启动定时器0
while(1)
{
a=b=c=d=e=f=g=h=1;
saomiao();
Write24();
}
}
/*******************************************************
定时器中断及显示函数
函数原型: void DS() interrupt 1;
功能: 对定时器写入初值,定时约3s,数码管显示各用户的用电情况. *******************************************************/
void DS() interrupt 1
{TH0=0x28;
TL0=0x00;
if(++n==50)
{ n=0;
for(k=0;k<8;k++)
{
m=zf[yh[j][k]];
if(k==2)
{m=m&0xf7;}
for(i=0;i<8;i++)
{ CLK=0;
DIN=m&0x01;
CLK=1;
m>>=1;
}
}
j=(j+1)%8;
}
}。

相关文档
最新文档