#include <reg51.h>
#define uchar unsigned char
#define DELAY_TIME 60 /*经实验,不要小于50!否则可能造成时序混乱*/
#define TRUE 1 //IIC返回应答正确
#define FALSE 0
sbit T_D=P3^1; //TXD
sbit R_D=P3^2; //RXD
sbit led_green=P2^0; //信号发送指示灯
sbit led_yellow=P2^1; //信号接收指示灯
sbit TorR = P3^7; //485接收标志
sbit SDA=P0^1;/*假设由P0.1和P0.2控制*/
sbit SCL=P0^2;
bit flag; //数据标志位
static uchar rdata[72]; //接收数据缓冲区
static uchar n=72;
static uchar counter; //接收计数器
static uchar totalnum;
static uchar times; //分三次接收标记位
void ldelay(uchar t)
{
uchar i;
uchar k=200;
while(t-->0)
{
while(k-->0)
for(i=0;i<255;i++);
}
}
/********** Function Definition函数定义 ************/
void DELAY(uchar t) /*延时函数*/
{
while(t!=0)
t--;
}
void I2C_Start(void)
{
/*启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变*/
SDA=1;
SCL=1;
DELAY(DELAY_TIME);
SDA=0;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
void I2C_Stop(void)
{
/*终止I2C总线,当SCL为高电平时使SDA产生一个正跳变*/
SDA=0;
SCL=1;
DELAY(DELAY_TIME);
SDA=1;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
void SEND_0(void) /* SEND ACK */
{
/*发送0,在SCL为高电平时使SDA信号为低*/
SDA=0;
SCL=1;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
void SEND_1(void)
{
/*发送1,在SCL为高电平时使SDA信号为高*/
SDA=1;
SCL=1;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
bit Check_Acknowledge(void)
{
/*发送完一个字节后检验设备的应答信号*/
SDA=1;
SCL=1;
DELAY(DELAY_TIME/2);
F0=SDA;
DELAY(DELAY_TIME/2);
SCL=0;
DELAY(DELAY_TIME);
if(F0==1)
{
return FALSE;
}
return TRUE;
}
void WriteI2CByte(char b)
{
/*向I2C总线写一个字节*/
uchar i;
for(i=0;i<8;i++)
{
if((b<<i)&0x80)
SEND_1();
else
SEND_0();
}
}
uchar ReadI2CByte(void)
{
/*从I2C总线读一个字节*/
uchar b=0,i;
for(i=0;i<8;i++)
{
SDA=1; /*释放总线*/
SCL=1; /*接受数据*/
DELAY(10);
F0=SDA;
DELAY(10);
SCL=0;
if(F0==1)
{
b=b<<1;
b=b+0x01;
}
else
b=b<<1;
}
return b;
}
/**********以下为读写24c02的函数**********/
/*void Write_One_Byte(char addr,char thedata)
{
bit acktemp=1;
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);
acktemp=Check_Acknowledge();
WriteI2CByte(thedata);
acktemp=Check_Acknowledge();
I2C_Stop();
} */
void Write_A_Page(uchar *buffer,uchar addr)
{
bit acktemp=1;
uchar i;
/*write a page to at24c02*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
for(i=0;i<8;i++)
{
WriteI2CByte(buffer[i]);
if(!Check_Acknowledge())
{
I2C_Stop();
}
}
I2C_Stop();
}
/*uchar Read_One_Byte(char addr)
{
bit acktemp=1;
uchar mydata;
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);
acktemp=Check_Acknowledge();
I2C_Start();
WriteI2CByte(0xa1);
acktemp=Check_Acknowledge();
mydata=ReadI2CByte();
acktemp=Check_Acknowledge();
I2C_Stop();
return mydata;
} */
void Read_N_Bytes(uchar *buffer,uchar k,uchar addr)
{
bit acktemp=1;
uchar i=0;
/*read 8 bytes from mem*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
I2C_Start();
WriteI2CByte(0xa1);
acktemp=Check_Acknowledge();
for(i=0;i<k;i++)
{
buffer[i]=ReadI2CByte();
if(i!=k-1)
SEND_0(); /*发送应答*/
else
SEND_1(); /*发送非应答*/
}
I2C_Stop();
}
void main(void)
{
uchar i;
uchar t;
PCON=0x00;
SCON=0x90;
EA=1;
ES=1;
led_yellow=0;//信号接收灯亮
TorR=0;//允许接收
ldelay(1); //短延时
if(TorR) //判断是否接受到数据
{
do
{
for(i=0;i<n;i+=8)
Write_A_Page(rdata+i,0x00+i+(72*times));//写EEPROM
counter=0;
totalnum=0;
times++;
TorR=0;
if(times<3)while(TorR==0); //写三次即可
}while(times<3);
led_yellow=1;//信号接收灯灭
ldelay(15);
}
led_yellow=1;
ldelay(2);
TorR=1; //接收停止,开始发送
led_green=0;
TB8=0;
SBUF=0x00; //reset-code 复位码
while(TI==0);TI=0;
while(1)
{
T_D=0;
for(i=70;i>0;i--);//delay 100 us
T_D=1;
for(i=7;i>0;i--);//delay 10 us
TB8=1;
SBUF=0x00; //start-code 起始码
while(TI==0);TI=0;
for(t=0;t<32;t++) //共控制32台灯具
{
Read_N_Bytes(rdata,7,0x00+(t<<2)+(t<<1));//读取每台灯命令 共六个通道
for(i=1;i<7;i++)
{
TB8=1;
SBUF=rdata[i];
while(TI==0);TI=0;
}
}
}
}
/*串口中断响应函数*/
void receive(void) interrupt 4 using 2
{
if(RI==1)/*如果是接收中断*/
{
if(!RB8)flag=1; //复位帧即置标志位
else if(flag&&((totalnum++/72)==times)) //每次读取72字节,分三次读取
{
rdata[counter++] =SBUF;
if(counter==n) //读取72字节至缓冲区,暂停接收
TorR=1;
}
RI=0;/*清除中断标志位,允许下一次中断*/
}
}
- 1
- 2
- 3
前往页