//-----------------------------------------------
#include <reg52.h>
#include <intrins.h>
//-----------------------------------------------
sfr AUXR=0x8e;
sfr CLK_DIV=0xC7;
sfr WDT_CONTR=0xe1;
sfr P1M0 = 0x91;
sfr P1M1 = 0x92;
sbit LED_BLUE=P3^7; //指示灯 通讯灯 蓝色
sbit LED_YELLOW=P3^2; //故障指示灯 黄色
sbit LED_RED=P3^3; //报警指示灯 红色
sbit R_T=P3^5; //RS485接收/发送控制
sbit ALM=P3^4; //报警信号, 高电平有效
sbit ERR_OPEN=P1^7; //故障信号,低电平有效 开路
sbit ERR_SHORT=P1^6; //短路
//------------------------------------------------
unsigned char *in_buf_p; //-->接收数据的指针
unsigned char input_num; //计数接收到的字节数
unsigned char input_end; //接收结束
unsigned char in_sum_check; //接收数据累加和校验
unsigned char input_start; //接收开始
unsigned char *out_buf_p; //-->发送数据的指针
unsigned char out_sum_check; //发送累加和校验
unsigned char out_end; //发送结束
unsigned char volatile sta; //分机工作状态
unsigned char volatile it_addr; //分机地址
unsigned char volatile wait_time; //等待时间
unsigned char volatile err_sta; //错误计数
unsigned char volatile alm_sta; //报警计数
unsigned char volatile test_time; //测试时间计数
unsigned char volatile new_addr; //新的地址
unsigned char volatile rd_addr; //读到的地址
unsigned char volatile addr_sta; //改变 地址计数
unsigned char volatile dingshijishu=0; //定时计数
unsigned char volatile yure=0; //开机预热标志
unsigned char volatile shanshuo=0; //闪烁标志
unsigned char volatile mess=0; //信号量,传递中断信号
unsigned char volatile out_buf[10]; //发送数据缓冲 ?
unsigned char volatile in_buf[10]; //接收数据缓冲
unsigned int volatile soft_dog; //软狗
void serial_out(void); //串口发送
void delayms(unsigned int ms); //延时
void serial_in(void); //串口接收
void message_box(void); //数据处理
int main(void)
{
unsigned char i,j,k;
begin:
LED_BLUE=0; //指示灯亮
R_T=0; //RS485为等待接收数据状态
WDT_CONTR=0x3c; //开看门狗 ,并喂狗
AUXR=AUXR&0x3f; //T1,T2时钟
TMOD=0x21;
TH0=0xdc; // timer0 value 10ms
TL0=0x00;
TCON=0x00;
PCON=0x80; // serial mode 3
TL1=0xfd;
TH1=0xfd;
TR1=1; //run timer1
SCON=0xd0;
ES=1; //串口为方式3,9位UART,19200
PS=1; //UART interrupt first
EA=1;
ET0=1;
P1=0xff;
delayms(2);
it_addr=P1&0x3F; //读分机的地址
for(i=0;i<10;i++)
{
in_buf [i]=0;
out_buf[i]=0; //收发数据缓冲区清0
}
//---------------------------------------------------------------------------------
wait_time=0;
input_start=0;
in_sum_check=0;
input_num=0;
input_end=0;
in_buf_p=&in_buf[0];
//---------------------------------------------------------------------------------
// sta=0x04; //分机工作状态标志字节:0x04 初始化
yure=0;
TR0=1;
dingshijishu=0;
shanshuo=0;
//-----------------------------------------------------------------------------------
for(i=0;i<120;i++) //等待4分钟,等待预热完成;
{
while(dingshijishu<200)
{
if((dingshijishu<200)&&(dingshijishu%50==0)&&(shanshuo==0))
{
_nop_();
_nop_();
_nop_();
if(dingshijishu<200)
{LED_BLUE=~LED_BLUE;shanshuo=1;j=dingshijishu;}
} //闪烁指示灯f=1Hz
if(j!=dingshijishu) shanshuo=0;
if(mess==1) message_box(); //有接收信息,进入数据处理
if(wait_time>3) //用于serial超时处理
{
wait_time=0;
for(k=0;k<10;k++) in_buf[k]=0;
input_start=0;
in_sum_check=0;
input_num=0;
input_end=0;
in_buf_p=&in_buf[0];
}
P1=0xff;
_nop_();
_nop_();
it_addr=P1&0x3F; //读地址
WDT_CONTR=0x3c; //喂狗
}
dingshijishu=0;
}
//-------------------------------------------------------------------------------------------
yure=1;
soft_dog=0;
test_time=0;
err_sta=0x00;
alm_sta=0x00;
//--------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//可在此处模拟 故障、报警
//ALM=0; //模拟 报警
//ERR=0; //模拟 故障
while(1)
{
WDT_CONTR=0x3c; //喂狗
if(wait_time>3) //用于serial延时,接收数据超时控制
{
wait_time=0;
for(i=0;i<10;i++) in_buf[i]=0;
input_start=0;
in_sum_check=0;
input_num=0;
input_end=0;
in_buf_p=&in_buf[0];
}
if(mess==1) message_box(); //有接收信息,进入数据处理
if(sta==0x03) LED_RED=0; else LED_RED=1;
if(sta==0x01) LED_YELLOW=0; else LED_YELLOW=1;
if(soft_dog!=0) goto begin; //防死机
}
return 0;
}
//------------------------------------------------------------------------------------
void message_box(void)
{
unsigned char i;
if((in_buf[0]!=06)||(in_buf[1]!=01)||(in_buf[2]!=00)||(in_buf[3]!=0xED)||(in_buf[4]!=it_addr))
//不是探头类码,或者不是本机的地址
{ //接收到的数据无效
for(i=0;i<10;i++) in_buf[i]=0;
in_buf_p=&in_buf[0];
in_sum_check=0;
input_end=0;
input_start=0;
input_num=0;
mess=0;
wait_time=0;
}
else //有效 //如果正确,分机应该立马回复自身的状态给主机
{
LED_BLUE=~LED_BLUE;
out_buf[0]=0x06;
out_buf[1]=sta;
out_buf[3]=0xed;
out_buf[4]=it_addr;
out_buf[5]=0xfb;
out_sum_check=0xcf;
out_end=1;
out_buf_p=&out_buf[0];
ACC=0xcf;
R_T=1;
delayms(2);
TB8=P;
SBUF=0xcf; //发送上行前导码
mess=0; //此次接收到的信息已经处理完了
for(i=0;i<10;i++) in_buf[i]=0; //清空接收缓冲区
}
}
//-----------------------------------------------------------------
//定时器0中断服务函数
void time0(void) interrupt 1 using 1
{
TR0=0;
TH0=0xdc; //reload timer0 value
TL0=0x00; //重装计数初值
TR0=1;
soft_dog=0;
WDT_CONTR=0x3c; //喂狗
if(wait_time!=0) wait_time=wait_time+1;
dingshijishu=dingshijishu+1;
if(ALM==1) alm_sta++; //报警状态标记
if(ERR_SHORT==0||ERR_OPEN==0) err_sta++; //故障状态标记
if (test_time==0)
{
P1=0xff;
_nop_();
_nop_();
new_addr=P1&0x3F; //更新分机地址
addr_sta=0;
}
else
{
P1=0xff;
_nop_();
_nop_();
rd_addr=P1&0x3F;
if (new_addr==rd_addr) addr_sta++;
}
test_time=test_time+1; //每10毫秒自加一次
if(test_time==10)
{
if ( (addr_sta==9)&&(it_addr!=new_addr) ) it_addr=new_addr;
sta=0x00; //分机工作正常
if(alm_sta==10) sta=0x03; //探头报警
if(err_sta==10) sta=0x01; //探头故障
if (yure==0) sta=0x04;
alm_sta=0;
err_sta=0;
test_time=0;
}
}
//----------------------------------------------------------
//串行口接收/发送中断服务函数
//----------------------------------------------------------
void serial(void) interrupt 4
{
if(TI==1) serial_out();
else if(RI==1) serial_in();
}
//----------------------------------------------------------
//串口接收函数
void serial_in(void)
{
unsigned char i;
RI=0;
if(mess==1) return; //前面接收到的信息还没有处理完,退出,现在不想再接收数据了
*in_buf_p=SBUF; //接收一个数据
if((*in_buf_p==0xFE)&&(input_start==0)) //接收起始字节
{
in_sum_check=*in_buf_p;
in_buf_p=&in_buf[0];
input_num=0;
input_end=0;
input_start=1;
wait_time=1;
}
else if((*in_buf_p==0xFB)&&(input_end==0)&&(input_num==5)) //接收结束字节
{
in_sum_check=in_sum_check+0xFB;
input_end=1; //接收结束字节标志
}
else if((*in_buf_p==in_sum_check)&&(input_end==1)) //接收完成
{
in_sum_check=0;
input_end=0;
input_start=0;
mess=1; //接收完一帧数据, mess=1
wait_time=0;
}
else if(input_num>5) //数据溢出,丢弃并且清零
{
for(i=0;i<10;i++) in_buf[i]=0;
in_buf_p=&in_buf[0];
in_sum_check=0;
input_end=0;
input_start=0;
input_num=0;
}
else if(input_start==1) //接收数据
{
input_num++; //接收计数
in_sum_check=in_sum_check+(*in_buf_p); //接收字节累加和校验
in_buf_p++;
}
}
//-----------------------------------------------------------------------
//serial send program
void serial_out(void)
{
unsigned char temp;
TI=0;
if(out_end==0)
{
R_T=0;
return; //发送结束 ,退出
}
if(*out_buf_p==0xFB) //发送结束字节
{
out_end=2;
out_sum_check=out_sum_check+0xFB;
out_buf_p++;
ACC=0xFB;
TB8=P;
SBUF=0xFB;
}
else if(out_end==2)
{
ACC=out_sum_check;
TB8=P; //偶校验
SBUF=out_sum_check; //发送校验字节
for(temp=0;temp<10;temp++) out_buf[temp]=0; //发送缓冲区清0
out_end=0; //发送结束标志
}
else
{
ACC=*out_buf_p; //连续发送数据
TB8=P;
SBUF=*out_buf_p;
out_sum_check=out_sum_check+(*out_buf_p); //校验和
out_buf_p++; //发送计数
}
}
//-----------------------------------------------------------------------------------
//延时函数 1.6 ms 11 . 0592 M Hz 晶体 STC51
void delayms(unsigned int ms)
{
unsigned int i,j=0;
for(i=0;i<ms;i++)
{
for(j=0;j<1001;j++)
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}
//----------------------------------------------------------------------------------------