串口处理数据(接收、解析、回复、框架)

         
//-----------------------------------------------
#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_();
            }
        }
}
//----------------------------------------------------------------------------------------  

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值