(原文件名:HubUp_485.JPG)
一个RS485中继器,分两个单片机,例子是与上位机通讯的单片机的,仅供参考!
//Program(cpu 8052) of Part of RS-485 repeater (UpLink)in C51
//Started at 2002/07/17
//Author FenglinYao at Nanjing
//说明:
// 1、平时UpLink部分监视上位机状态,DownLink部分巡检下位机报警数据。
// 2、如果UpLink部分收到登录命令,则关闭DownLink部分巡检通道,打开上位机——下位机通道。
// 3、如果UpLink部分收到退出登录命令,则关闭上位机——下位机通道,恢复DownLink部分巡检。
// 4、如果UpLink部分收到报警查询命令,则转换为上位机与DownLink部分通讯。
// 5、初始化时DownLink部分从UpLink部分获取波特率。
//-----------------------------------------------------------------------------------------
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define nop _nop_();
#define ETX 0X03 /* 消息结束标识 */
#define STX 0X02 /* 消息开始标识 */
bdata uchar Status1 _at_ 0x20; //中继器状态标志
sbitWrite_Not_Need = Status1^0; //显示是否需要写24C04
sbitLog_In = Status1^1; //上位机已登陆到中继器标志位
sbitLog_Out = Status1^2; //上位机退出登陆标志位
sbitAsk_for_Alarm = Status1^3; //上位机查询报警标志位
sbitAsk_for_Baud = Status1^4; //交换波特率状态
sbitInit = Status1^5; //单片机正处于初始化状态
sbitPower_Off = Status1^6; //电源电压低标志位
sbitAlarm_Data_Interchange = Status1^7; //交换报警数据状态
bdata uchar Status2 _at_ 0x21; //中继器状态标志
sbitRead_Error = Status2^0; //读24C04错误
sbitWrite_Error = Status2^1; //写24C04错误
sbitData_Received = Status2^2; //发出数据已被接收到
sbitData_Ver_Send = Status2^3; //发出数据偶校验标志
sbitBroadCasting = Status2^4; //收到上位机对下位机的广播信号(时间、日期)
sbitCom1Data_Sent = Status2^5; //串口1已发送一字节
sbittem_bit = Status2^6; //临时位变量
sbitCom1_Finished = Status2^7; //串口1数据已接收完毕
bdata uchar Status3 _at_ 0x22; //中继器状态标志
sbitAlarm_Over = Status3^0; //掉电时下位机侧传来的报警数据结束
sbitPowerTest = Status3^1; //掉电中断口检测位
sbitOK = Status3^2; //临时变量
sbitCom1_deal = Status3^3; //串口收到数据要进行处理
sbitCom2_Finished = Status3^4; //并口数据接收完毕
sbitPTN = Status3^5; //并口有数据需发送
sbitPTI = Status3^6; //并口数据已发出
sbitnotusedbit = Status3^7; //
bdata uchar ParData _at_ 0x23; //并行输出通讯缓冲区
sbitParData0 = ParData^0;
sbitParData1 = ParData^1;
sbitParData2 = ParData^2;
sbitParData3 = ParData^3;
sbitParData4 = ParData^4;
sbitParData5 = ParData^5;
sbitParData6 = ParData^6;
sbitParData7 = ParData^7;
bdata uchar PaOData _at_ 0x24; //并行读入通讯缓冲区
sbitPaOData0 = PaOData^0;
sbitPaOData1 = PaOData^1;
sbitPaOData2 = PaOData^2;
sbitPaOData3 = PaOData^3;
sbitPaOData4 = PaOData^4;
sbitPaOData5 = PaOData^5;
sbitPaOData6 = PaOData^6;
sbitPaOData7 = PaOData^7;
bdata uchar SData _at_ 0x25; //串行通讯缓冲区
sbitSD_0 = SData^0;
sbitSD_1 = SData^1;
sbitSD_2 = SData^2;
sbitSD_3 = SData^3;
sbitSD_4 = SData^4;
sbitSD_5 = SData^5;
sbitSD_6 = SData^6;
sbitSD_7 = SData^7;
bdata uchar Repeater_Address _at_ 0x26; //中继器地址
sbitRA_0 = Repeater_Address^0;
sbitRA_1 = Repeater_Address^1;
sbitRA_2 = Repeater_Address^2;
sbitRA_3 = Repeater_Address^3;
sbitRA_4 = Repeater_Address^4;
sbitRA_5 = Repeater_Address^5;
sbitRA_6 = Repeater_Address^6;
sbitRA_7 = Repeater_Address^7;
bdata uchar Repeater_Status _at_ 0x27; //中继器状态标志位
sbitDHead_Arrived = Repeater_Status^0;
sbitSdog_Feed = Repeater_Status^1;
sbitDog_Feedback = Repeater_Status^2;
sbitSdog_Play = Repeater_Status^3;
sbitAsk_for_Status = Repeater_Status^4;
sbitRS_5 = Repeater_Status^5;
sbitRS_6 = Repeater_Status^6;
sbitRS_7 = Repeater_Status^7;
uchar data baud _at_ 0x30; //通讯参数-波特率的设置参数
uchar data W_P_Data_Buf1 _at_ 0x32; //Com1写数据缓冲区指针1
uchar data R_P_Data_Buf1 _at_ 0x33; //Com2读数据缓冲区指针1
uchar data W_P_Data_Buf2 _at_ 0x34; //并口写数据缓冲区指针2
uchar data R_P_Data_Buf2 _at_ 0x35; //并口读数据缓冲区指针2
uchar data W_P_24C32Buf _at_ 0x36; //写24C32缓冲区指针
uchar data R_P_24C32Buf _at_ 0x37; //读24C32缓冲区指针
uchar data Buf_of_Com1 _at_ 0x38; //串口1缓冲区
uchar data Buf_of_Com2 _at_ 0x39; //并口缓冲区
uchar data i,j,k,l _at_ 0x3a; //临时变量
uchar data ErrorCode _at_ 0x3e; //用于返回出错代码
uintdata ET _at_ 0x3f; //用于测试
uchar data Timer_tem1 _at_ 0x41; //时间临时变量
uchar data Timer_1m _at_ 0x42; //分
uchar data Timer_1s _at_ 0x43; //秒
uchar data Timer_1h _at_ 0x44; //小时
uchar data Timer_1d _at_ 0x45; //天
uchar data Timer_dog _at_ 0x46; //按秒记数,上位机巡检过清零,溢出时复位
uchar data Tem_Buf _at_ 0x47; //串口溢出后临时缓冲区
uchar data Timer_tem _at_ 0x48; //时间临时变量
uchar data PAlarmData _at_ 0x49; //保存报警数据到24C04时的报警堆栈区指针
uchar data sum _at_ 0x4a; //作校验和运算用
uchar data Buf_of_Com2a _at_ 0x4b;
uchar data Buf_of_Com2b _at_ 0x4c;
uchar data m,n _at_ 0x4d; //临时变量
uchar data ExchangeTemp _at_ 0x4e;
uchar data Timer_Error _at_ 0x4f;
uchar data StackBuf _at_ 0x50; //堆栈区
uchar idata Timer_Over;
uchar idata Com_Buff; //并口收数据缓冲区
uchar idata Data_Buf; //串口收数据缓冲区
uchar idata Buf_of_WR; //页读写24C64的缓冲区
sbit PData0=P1^0;
sbit PData1=P1^1;
sbit PData2=P1^2;
sbit PData3=P1^3;
sbit PData4=P1^4;
sbit PData5=P1^5;
sbit PData6=P1^6;
sbit PData7=P1^7;
sbit TXD2=P2^7;
sbit RXD2=P2^6;
sbit DogHand=P2^5;
sbit LED=P2^4;
sbit sda=P2^3;
sbit scl=P2^2;
sbit WDI=P2^1;
sbit DR1=P2^0;
sbit PTest=P3^2;
sbit PR1=P3^4;
sbit PR2=P3^3;
sbit AnS=P3^5;
sbit Bd1=P3^6;
sbit Bd2=P3^7;
char code RepeaterVer={"Repeater1.1 Author Yaofenglin NJ"};//记录中继器的版本及相关资料
char code NumConver={"0123456789abcdef"};
char code LetterConver={"ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
voidsc_recieve(void);
//------------------------- 用于掉电保护,提醒保存未中继的报警数据到24C04 ------------------------------------
void Int0(void) interrupt 0
{
Power_Off=1;
REN=0;
EX0=0;
}
//------------------------- 用于掉电保护,保存未中继的报警数据到24C04-----------------------------------------
//----------------------------------------定时中断0,发送并口数据----------------------------------------
void int_time_1ms(void) interrupt 1 //total 160T, Max 56T in use,Min 14T,Normal 38T
{
if(PTN)
{
P1=ParData;
nop; nop; nop; //等待数据稳定
PR1=0;
nop; nop; nop; nop; nop; nop;nop;
nop; nop; nop; nop; nop; nop;nop; //等待下位机侧中断
PTN=0;
nop;
PR1=1;
if(ParData==0x03){ nop; nop; nop; nop; nop; nop; nop; nop;
nop; nop; nop; nop; nop; nop; nop; P1=0xff;}
}
}
//------------------------------------定时中断0,发送并口数据--------------------------------------
//----------------------------------------外部中断1,接收并口数据----------------------------------------
void parData_Receive(void) interrupt 2using 3
{
AnS=0;
Buf_of_Com2=P1; nop;
Buf_of_Com2a=P1; nop;
Buf_of_Com2b=P1;
if(Buf_of_Com2==Buf_of_Com2a)Buf_of_Com2=Buf_of_Com2a;
else Buf_of_Com2=Buf_of_Com2b;
if(Buf_of_Com2==0x02) W_P_Data_Buf2=0;
if(W_P_Data_Buf2==0)
{
if(Buf_of_Com2==0x02)
{ DHead_Arrived=1;
Com_Buff=Buf_of_Com2;
W_P_Data_Buf2++;
goto L3;
}
}
if((W_P_Data_Buf2>0)&&(W_P_Data_Buf2<32))
{
Com_Buff=Buf_of_Com2;
W_P_Data_Buf2++;
}
if(W_P_Data_Buf2==32)
W_P_Data_Buf2=0;
L3:if((Buf_of_Com2==0x03)&&( W_P_Data_Buf2!=0))
{ DHead_Arrived=0; Com2_Finished=1;}
else AnS=1;
}
//----------------------------------------外部中断1,接收并口数据----------------------------------------
//--------------------------------------定时中断2,使用定时器2-------------------------------------------
void int_time_st(void) interrupt 5 using 2 //1.25ms
{
Timer_tem++;
if(Timer_tem>8)
{
Timer_tem-=8;
Timer_tem1++;
}
Timer_Over++;
if (Timer_tem1>100)
{
Timer_1s++;
Timer_dog++;
Timer_tem1-=100;
LED=!LED;
}
if ((Timer_tem1%16)==0) Sdog_Feed=1;
if ((Timer_tem1%16)==1) Sdog_Play=1;
if (Timer_1s>59) { Timer_1m++; Timer_1s-=60; }
if (Timer_1m>59) { Timer_1h++; Timer_1m-=60; }
if (Timer_1h>23) { Timer_1d++; Timer_1h-=24; }
if (Timer_1d>29) { Timer_1d-=30;}
TF2=0;
}
//-----------------------------------------定时中断2结束----------------------------------------------------
//------------------------------------串口中断,接收和发送串口数据------------------------------------
void rs_485() interrupt 4 using 1
{
if(RI)
{
sc_recieve();
RI=0;
}
else { Com1Data_Sent=1;TI=0; }
}
//------------------------------------串口中断,接收和发送串口数据------------------------------------
//------------------------------------------------串口数据接收---------------------------------------------------
voidsc_recieve(void)
{
Buf_of_Com1=SBUF;
if(W_P_Data_Buf1!=0)
{
Data_Buf=Buf_of_Com1;
W_P_Data_Buf1++;
}
if((Buf_of_Com1==0x02)&!Com1_Finished)W_P_Data_Buf1=0;
if(W_P_Data_Buf1==0)
{
if(Buf_of_Com1==0x02)
{
BroadCasting=0; //接收前清零
Data_Buf=Buf_of_Com1;
W_P_Data_Buf1++;
}
}
if(W_P_Data_Buf1==32) W_P_Data_Buf1=0;
if(W_P_Data_Buf1!=0)
{
while(PTN) nop;
if((PAlarmData!=0)&Ask_for_Alarm&(Buf_of_Com1==0x03))Buf_of_Com1=0x04;
ParData=Buf_of_Com1;
Data_Ver_Send=0;
PTN=1;
} //串口1送来数据一律转发给下位机侧
if(Buf_of_Com1==0x03)
{ //已登陆时收到结束符即认为该数据包有效,
if((Log_In)|(Data_Buf==Repeater_Address)) //否则只有中继器地址相同时才认为有效
{
W_P_Data_Buf1=0;
Com1_Finished=1;
}
}
if((W_P_Data_Buf1==2)&&((Data_Buf==Repeater_Address)||(Data_Buf==0x01)))
Com1_deal=1;
if((W_P_Data_Buf1==3)&&(Data_Buf==0x01))
BroadCasting=1; //上位机对下位机进行广播
if(Com1_deal)
{
if(W_P_Data_Buf1==5)
{
if((Data_Buf=='Q')&&(Data_Buf=='?')) Ask_for_Alarm=1;
if((Data_Buf=='S')&&(Data_Buf=='?')) Ask_for_Status=1;
if((Data_Buf=='?')&&(Data_Buf=='?')) Ask_for_Alarm=1;
if((Data_Buf=='L')&&(Data_Buf=='I')) Log_In=1;
if((Data_Buf=='L')&&(Data_Buf=='O')) Log_Out=1;
Com1_deal=0;
}
}
}
//------------------------------------------------串口数据接收---------------------------------------------------
//------------------------------喂狗程序------------------------------------
void Feed_dog(void)
{
WDI=!WDI;
}
//------------------------------喂狗程序------------------------------------
//-------------------------------------------发送命令-----------------------------------------
voidSend_command(uchar let1,let2)
{
Ask_for_Baud=1;
Data_Buf=STX;
Data_Buf=Repeater_Address;
Data_Buf=0x00;
Data_Buf=let1;
Data_Buf=let2;
Data_Buf=0x30;
Data_Buf=0x30+baud;
sum=Data_Buf+Data_Buf+Data_Buf+Data_Buf+Data_Buf+Data_Buf+Data_Buf;
// for(i=0;i<7;i++) sum+=Data_Buf;
sum=~sum+1;
Data_Buf=NumConver;
Data_Buf=NumConver;
Data_Buf=ETX;
W_P_Data_Buf1=0;
PTN=0;
do{
ParData=Data_Buf;
Data_Ver_Send=0;
PTN=1; Timer_Over=0;
while(PTN&(Timer_Over<2))nop;
for(i=0;i<2;i++) nop;
while(!AnS&(Timer_Over<2))nop;
W_P_Data_Buf1++;
}
while(Data_Buf!=ETX);
ParData=Data_Buf;
Data_Ver_Send=0;
PTN=1; Timer_Over=0;
while(PTN&(Timer_Over<4))nop;
for(i=0;i<2;i++) nop;
while(!AnS&(Timer_Over<4)) nop;
AnS=0;
for(i=0;i<2;i++) nop;
AnS=1;
W_P_Data_Buf1=0;
}
//-------------------------------------------发送命令-----------------------------------------
bit Ver_Command(void)
{
WDI=!WDI;
Timer_Over=0;
while(!Com2_Finished&(Timer_Over<10)) nop;
if((Com_Buff=='B')&&(Com_Buff=='D'))
{
sum=Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff;
// for(i=0;i<7;i++) sum+=Com_Buff;
if(Com_Buff>96)Com_Buff-=87; else Com_Buff-=48;
sum+=Com_Buff*16;
if(Com_Buff>96)Com_Buff-=87; else Com_Buff-=48;
sum+=Com_Buff;
if(sum==0)
{
AnS=1;
Com2_Finished=0;
W_P_Data_Buf2=0;
return(0);
}
}
if((Com_Buff=='B')&&(Com_Buff=='K')&&(Com_Buff==ETX))
{
sum=Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+
Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+
Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff+Com_Buff;
// for(i=0;i<21;i++) sum+=Com_Buff;
if(Com_Buff>96)Com_Buff-=87; else Com_Buff-=48;
sum+=Com_Buff*16;
if(Com_Buff>96)Com_Buff-=87; else Com_Buff-=48;
sum+=Com_Buff;
if(sum==0)
{
AnS=1;
Com2_Finished=0;
W_P_Data_Buf2=0;
return(0);
}
}
AnS=1;
Com2_Finished=0;
ET++;
W_P_Data_Buf2=0;
return(1);
}
//-------------------------------------------发送、校验波特率和中继器地址-----------------------------------------
//----------------------------------初始化子程序------------------------------------------
void Init1(void)
{
EA=0;
P3=0xff;
P1=0xff;
P2=0xff;
P0=0xff;
Status1=0;
Status2=0;
Status3=0;
ParData=0;
SData=0;
Timer_dog=0;
Repeater_Address=P0;
tem_bit=RA_0;RA_0=RA_7; RA_7=tem_bit;
tem_bit=RA_1;RA_1=RA_6; RA_6=tem_bit;
tem_bit=RA_2;RA_2=RA_5; RA_5=tem_bit;
tem_bit=RA_3;RA_3=RA_4; RA_4=tem_bit;
Repeater_Address=~Repeater_Address;
Repeater_Address+=16;
baud=P3;
baud>>=6;
if((baud==0)|(baud==3))
{
PCON&=0X7f;
TH1 = 0xfd; //设置波特率为9.6k
}
if(baud==1)
{
PCON|=0x80;
TH1 = 0xfd; //设置波特率为19.2k
}
if(baud==2)
{
PCON|=0x80;
TH1 = 0xff; //设置波特率为57.6k
}
SCON=0x50; //定义串口使用8位数据,波特率由T1决定的方式
TMOD=0x22; //定义定时器0,1为自动重载的八位计数器
TH0=0x60; //定义T0的溢出时间为160T
ET0=1;
TR0=1; //开定时器0
TR1=1; //开定时器1
RCAP2H=0xfb;
RCAP2L=0x80;
C_T2=0;
RCLK=0;
TCLK=0;
ET2=1;
TR2=1; //定时器2溢出时间为1.25ms
ES=1; //开窜口中断
PT0=1; //定时中断0中断优先处理
EX0=1; //允许掉电中断
IT1=1; //中断1设为边沿触发方式
EX1=1;
PX1=1;
ET=0;
// PS=1;
Timer_tem1=0;
PAlarmData=0;
// W_P_Com_Buff=0;
// R_P_Com_Buff=0;
W_P_Data_Buf1=0;
R_P_Data_Buf1=0;
W_P_Data_Buf2=0;
R_P_Data_Buf2=0;
DR1=0;
for(i=0;i<32;i++)Com_Buff=0;
for(i=0;i<32;i++)Data_Buf=0;
for(i=0;i<32;i++)Buf_of_WR=0;
REN=0;
EA=1; //开中断
}
//----------------------------------初始化子程序------------------------------------------
//--------------------------24C04的读写操作函数集----------------------------
void start_24(void) //提供I2C总线的起使位
{
scl=1; nop; sda=0; nop ;scl=0; nop; sda=1;
}
void stop_24(void) //提供I2C总线的停止位
{
sda=0; scl=1; nop; sda=1; scl=0;
}
void init_24(void) //I2C总线初始化
{
scl=0;stop_24();
}
unsigned char read_24(void)
{
sda=1;
for(k=0;k<7;k++)
{
scl=1; nop; SD_0=sda; nop; scl=0; nop;
SData<<=1;
}
scl=1; nop; SD_0=sda; nop; scl=0; nop;
scl=1; nop; sda=1; nop; scl=0;
return(SData);
}
unsigned char Sread_24(void)
{
sda=1;
for(k=0;k<7;k++)
{
scl=1; nop; SD_0=sda; nop; scl=0; nop;
SData<<=1;
}
scl=1; nop; SD_0=sda; nop; scl=0; nop;
sda=0; scl=1; nop;scl=0;sda=1;
return(SData);
}
bitwrite_24(unsigned char dd)
{
bit sample1;
SData=dd;
for(k=0;k<8;k++)
{
sda=SD_7; nop; scl=1; nop; scl=0; nop;
SData<<=1;
}
sda=1; nop; scl=1; nop; sample1=sda;nop; scl=0; nop; nop;
return(!sample1);
}
bit Sread64(unsigned int address) //读取24C64指定地址的十六字节数据
{
unsigned char Addr_Hi,Addr_Lo;
Addr_Hi=(address&0x1fff)/256;
Addr_Lo=(address&0xff);
start_24();
if(write_24(0xa0))
{if(write_24(Addr_Hi))
{ if(write_24(Addr_Lo))
{start_24();
if(write_24(0xa1))
{
for(i=0;i<31;i++)
Buf_of_WR=Sread_24();
Buf_of_WR=read_24();
stop_24();return(1);
}
else { Read_Error=1;stop_24(); return(0); }
}
else { Read_Error=1;stop_24(); return(0); }
}
else { Read_Error=1;stop_24();return(0); }
}
else { Read_Error=1;stop_24();return(0); }
}
/*
unsigned char read(unsigned int address) //读取24C04指定地址的一字节数据
{
unsigned char dd,ee;
dd=((address&0x7ff)/256)<<1; //得到块地址
start_24();
ee=0xa0|dd;
if(write_24(ee))
{if(write_24(address))
{
if(write_24(0xa1|dd))
{dd=read_24(); stop_24(); Read_Error=0; return(dd); }
else { Read_Error=1;stop_24(); return(0); }
}
else { Read_Error=1;stop_24();return(0); }
}
else { Read_Error=1;stop_24();return(0); }
}
*/
unsigned char read64(unsigned int address) //读取24C64指定地址的一字节数据
{
unsigned char Addr_Hi,Addr_Lo,dd;
Addr_Hi=(address&0x1fff)/256;
Addr_Lo=(address&0xff);
nop;
start_24();
nop;
if(write_24(0xa0))
{if(write_24(Addr_Hi))
{ if(write_24(Addr_Lo))
{start_24();
if(write_24(0xa1))
{dd=read_24(); stop_24(); Read_Error=0; return(dd); }
else { Read_Error=1;stop_24(); return(0); }
}
else { Read_Error=1;stop_24(); return(0); }
}
else { Read_Error=1;stop_24();return(0); }
}
else { Read_Error=1;stop_24();return(0); }
}
/*
bit write(unsigned int address,unsigned char dd) //写入24C04指定地址的一字节数据
{
unsigned char ddd;
ddd=((address&0x7ff)/256)<<1;
start_24();
if(write_24(0xa0|ddd))
{if(write_24(address))
{if(write_24(dd));stop_24();
Timer_Over=0;while(Timer_Over<10) nop;return(1); }
}
Write_Error=1;
stop_24();
return(0);
}
*/
bit write64(unsigned int address,unsigned char dd) //写入24C64指定地址的一字节数据
{
unsigned char Addr_Hi,Addr_Lo;
Addr_Hi=(address&0x1fff)/256;
Addr_Lo=(address&0xff);
start_24();
if(write_24(0xa0))
{if(write_24(Addr_Hi))
{ if(write_24(Addr_Lo))
{if(write_24(dd))
{stop_24(); Timer_Over=0;while(Timer_Over<8) nop; return(1); }
}
}
}
Write_Error=1;
stop_24();
return(0);
}
bit Swrite64(unsigned int address)
{
unsigned char Addr_Hi,Addr_Lo;
Addr_Hi=(address&0x1fff)/256;
Addr_Lo=address&0xff;
start_24();
if(write_24(0xa0))
{if(write_24(Addr_Hi))
{ if(write_24(Addr_Lo))
for(i=0;i<32;i++)
{ if(!(write_24(Buf_of_WR)))
{stop_24(); return(0); }
}
}
}
Write_Error=0;
stop_24();
Timer_Over=0;while(Timer_Over<8) nop;
return(1);
}
bit clear(void)
{
unsigned int Ver1;
for(i=0;i<16;i++)
{
for(j=0;j<32;j++) Buf_of_WR=0;
Swrite64(32*i);
WDI=!WDI;
}
Ver1=0;
for(i=0;i<16;i++)
{
Sread64(32*i);
for(j=0;j<32;j++) Ver1+=Buf_of_WR;
WDI=!WDI;
}
if(Ver1==0) return(1); else return(0);
}
void SaveTo_24C04(bit First,uchar Location)
{
if(First)
{
if(Com_Buff==0) Write_Not_Need=1; elseWrite_Not_Need=0;
for(j=0;j<8;j++)
{
Buf_of_WR=Com_Buff;
Buf_of_WR=Com_Buff;
if(Buf_of_WR==0)
{ ExchangeTemp=PAlarmData;PAlarmData=(32*Location-64)+j+ExchangeTemp; Alarm_Over=1; break; }
}
}
else
{
for(j=0;j<8;j++)
{
if(Alarm_Over) break;
Buf_of_WR=Com_Buff;
Buf_of_WR=Com_Buff;
if(Buf_of_WR==0)
{ ExchangeTemp=PAlarmData;PAlarmData=(32*Location-64)+j+8+ExchangeTemp; Alarm_Over=1;break; }
}
if(!Write_Not_Need)Swrite64(32*Location+ExchangeTemp);
}
}
//-----------------------------24C04的读写操作函数集----------------------------
//---------------------------------主程序体-------------------------------------
void main(void)
{
SP=0X4f;
Init1();
init_24();
if(Sread64(0))
{
if(Buf_of_WR!='1'||Buf_of_WR!='1'||Buf_of_WR!='Y')
{
OK=clear();
for(i=0;i<32;i++) Buf_of_WR=RepeaterVer; //初使化24C64
Swrite64(0);
write64(32,0);
}
}
PAlarmData=read64(32);
tem_bit=1;
while(tem_bit)
{
nop;
Send_command('B','D');
tem_bit=Ver_Command();
}
Send_command('O','V');
for(i=0;i<32;i++) Data_Buf=0;
REN=1;
while(1)
{
ml://if(Timer_dog>240) while(1) //调试时停用
nop; //4分钟内没有检测到上位机巡检则复位
if(Power_Off) //检测到电源电压底的转储过程
{
REN=0;
for(l=0;l<14;l++)
{
for(n=0;n<2;n++)
{
tem_bit=1;
while(tem_bit)
{
Send_command('B','K'); //要求下位机侧将报警信息按16字节(8个报警数据)一组发给上位机侧
tem_bit=Ver_Command();
}
Send_command('O','V');
if(n==0)
SaveTo_24C04(1,l+2);
else
SaveTo_24C04(0,l+2);
}
if(Alarm_Over){ write64(32,PAlarmData);break;} //写报警数据指针
}
while(!PowerTest){ PowerTest=PTest; WDI=!WDI;} //试图等待电压恢复正常
while(1) nop; //复位
}
if(Ask_for_Alarm|Ask_for_Status) //上位机报警查询
{
Timer_dog=0;
Timer_Over=0;
while(!Com1_Finished&( Timer_Over<8)) nop; //等待上位机发送数据完毕
if(Com1_Finished) { DR1=1;Com1_Finished=0; }
else { Ask_for_Alarm=0; Ask_for_Status=0; goto ml; }
PAlarmData=read64(32);
if((PAlarmData==0)|Ask_for_Status) //如果24C04内没有掉电时未来得及中继的数据
{
if(Timer_Error>2) Timer_dog=241; //下位机侧3次无应答复位中继器
Timer_Over=0;
while(!Com2_Finished&( Timer_Over<20)) nop; //等待下位机侧发送报警数据完毕
AnS=1;
if(!Com2_Finished)
{ Timer_Error++;DR1=0; Ask_for_Alarm=0; P1=0xff; Ask_for_Status=0; goto ml; }
else { Com2_Finished=0;Timer_Error=0; }
}
else
{
AnS=0;
Com_Buff=STX;
Com_Buff=Repeater_Address;
Com_Buff=read64(2*PAlarmData+62);
Com_Buff='A';
Com_Buff='L';
Com_Buff=0x30;
Com_Buff=read64(2*PAlarmData+63);
sum=0;
for(i=0;i<7;i++) sum+=Data_Buf;
sum=~sum+1;
Com_Buff=NumConver;
Com_Buff=NumConver;
Com_Buff=ETX;
W_P_Data_Buf2=10;
}
R_P_Data_Buf2=0; DR1=1;
while(R_P_Data_Buf2<W_P_Data_Buf2)
{
SBUF=Com_Buff;
//Timer_Over=0;
while(!Com1Data_Sent) nop;
Com1Data_Sent=0;
R_P_Data_Buf2++;
}
if(PAlarmData!=0)
{
PAlarmData--;
write64(32,PAlarmData);
}
R_P_Data_Buf2=0;
W_P_Data_Buf2=0;
AnS=1;
DR1=0;
if(Ask_for_Alarm) Ask_for_Alarm=0;else Ask_for_Status=0;
}
if(Log_Out&!Log_In) //防止Log_Out标志位干扰程序运行
{
Log_Out=0;
while(!Com1_Finished)nop;
Com1_Finished=0;
}
WDI=DogHand;
if(Log_In) //上位机登陆到下位机
{
L1: Timer_Over=0;
while(!Com1_Finished) //等待上位机发送数据完毕
{
nop;
// if(Timer_Over>40) break;
}
Com1_Finished=0;
if(Log_Out|BroadCasting)
{
BroadCasting=0;
Log_In=0;
Log_Out=0;
gotoL2;
}
Timer_Over=0;
while(!Com2_Finished) //等待下位机侧发送数据完毕
{
if(!DHead_Arrived&(Timer_Over>20)){ Log_In=0; goto L2; } //25mS收不到起始符退出
if(DHead_Arrived&(Timer_Over>60)) { Log_In=0; goto L2; } //75mS左右收不到结束符退出
if(Com1_Finished) { Log_In=0; goto L2; } //在等下位机响应时,上位机可要求中断
}
DR1=1;
Com2_Finished=0;
R_P_Data_Buf2=0;
while(R_P_Data_Buf2<W_P_Data_Buf2)
{
SBUF=Com_Buff;
Timer_Over=0;
while(!Com1Data_Sent&(Timer_Over<2)) nop;
Com1Data_Sent=0;
R_P_Data_Buf2++;
}
R_P_Data_Buf2=0;
W_P_Data_Buf2=0;
AnS=1;
Feed_dog();
DR1=0;
goto L1;
nop;
L2: nop;
}
} //End while(1)
} //End main()
//--------------------------------主程序体结束------------------------------------- mark 最近也在了解485总线 学习下 小弟也在学习中,与楼主情况相似 学习了! 485是半双工的,收发切换注意下延时 其他和232处理起来是一样的 mark{:cry:} mark!学习
页:
[1]