Linux主板支持多机系统的Mark/Space校验

Linux主板支持多机系统的Mark/Space校验

 

  • 关键词: Linux 主板
  • 摘要:英创Linux主板可以通过RS485总线挂载多个单片机组成多机系统,当从机设备比较多、传输数据比较频繁的时候,单片机的负载将大大增加,影响正常的工作,比较通用的解决办法是充分利用串口固定校验位(Parity Stick)的功能,使用Mark/Space校验位区分地址和数据。

 

  英创Linux主板可以通过RS485总线挂载多个单片机组成多机系统,如图1所示,其中Linux主机作为上位机,单片机作为从机,485总线最多能挂载256个从机。系统工作的时候,每一个从机都有自己的地址(从机号),上位机首先发送从机的地址,再发送命令/数据,其发送的命令/数据可以被每一个从机接收,从机收到命令和数据后,如果地址和自己的相符,就进行应答。

 

图1 Linux主机与单片机组成的多机系统

 

图2 多机通信帧格式

 

  单片机每收到一个字节都要产生中断,在一般情况下,当Linux主机向从机1发送数据的时候,从机2、3在每一个字节都要产生中断,不论传输的是地址还是数据,也不论是不是跟自己通信。当从机设备比较多、传输数据比较频繁的时候,单片机的负载将大大增加,影响正常的工作。

 

  比较通用的解决办法是充分利用串口固定校验位(Parity Stick)的功能,使用Mark/Space校验位区分地址和数据,如图2所示的多机通信帧中,发送和接收地址字节时,可以使用Mark校验(也可以使用Space校验),发送和接收数据字节时,使用Space校验(也可以使用Mark校验)。系统初始化的时候,所有的从机都设置成Mark校验,进入等待状态。主机发送第一个字节(addr = 从机1)的时候使用Mark校验。这时,所有的从机都收到了addr,并通过校验产生中断。在从机的中断程序中,如果addr和自己的地址相符,就将从机设置成Space校验(从机1),否则,继续保持Mark校验(从机2、3)。紧接着,主机发送data1、data2的时候使用Space校验,这时,由于从机2、3不能通过Space校验,将不会产生中断,只有从机1会产生中断,应答主机。这样就大大降低了处于等待状态的从机2、3的中断负载。

 

  对Linux目前的串口驱动程序而言,在逻辑上应用程序可以先设置一次Mark校验位,write一个地址字节,再设置一次Space校验,接着write多个数据字节来实现多机通信。但是,两次调用write之间可能会有较大的时间间隙,导致单片机接收数据超时,多机通信失败。为此,英创公司专门修改了Linux串口驱动程序,在不增加新的API调用的前提下,只需要在应用程序中连续两次设置校验位即可使串口驱动进入ADDR_DATA_MODE模式,支持Mark/Space多机通信,并且将同一帧数据的addr、data连续发送出去(应用程序只调用一次write函数)。应用程序具体步骤如下(为方便校验位设置,编写了一个校验位设置函数):

 

  1、校验位设置函数

 

  int CSerial::SetParity(int parity)

  {

      struct termios new_opt;

      int status;

      unsigned int old_ccflag;

 

      tcgetattr(m_fd,&new_opt);

      old_ccflag = new_opt.c_cflag;

 

      new_opt.c_cflag &= ~PARODD ;

      new_opt.c_cflag &= ~CMSPAR ;

 

      if(parity == 0)

      {

          //使用Space校验 标记数据

          new_opt.c_cflag |= PARENB | CS8 | CMSPAR;

      }

      else if(parity == 1)

      {

          //使用Mark校验 标记地址

          new_opt.c_cflag |= PARENB | CS8 | CMSPAR | PARODD;

      }

      else if(parity == 2)

      {   //使用偶校验

          new_opt.c_cflag |= PARENB;      /* Enable parity */

          new_opt.c_cflag &= ~PARODD;     /* 转换为偶效验*/

      }

      else if(parity == 3)

      {

          //使用奇校验

          new_opt.c_cflag |= (PARODD | PARENB);   /* 设置为奇效验*/

      }

      else

      {

          new_opt.c_cflag = old_ccflag;

      }

      status = tcsetattr(m_fd,TCSANOW,&new_opt);

      return status;

  }

 

  2、主程序两次调用校验位设置函数,进入ADDR_DATA_MODE模式

 

  Buf[0] = 0x39;

   Buf[1] = 0xC1;

   Buf[2] = 0x80;

   Buf[3] = 0x1;

   Buf[4] = 0x0;

 

   //连续两次设置校验位,进入ADDR_DATA_MODE.

   //先设置数据使用的校验位,后设置地址使用的校验位

   m_Serial.SetParity(0);      //数据使用space校验

   m_Serial.SetParity(1);      //地址使用mark校验

   sleep(1);

   m_Serial.WritePort( Buf, 5 );

 

  如上程序将5个字节一起发送出去,其中Buf[0]作为地址,使用mark校验,Buf[1-4]作为数据,使用space校验,波形如图3所示。所有从机收到地址后,都通过校验位,产生中断,但仅地址为0x39的从机会将自己的校验位设置为0。之后Buf[1-4]仅有从机0x39能够产生接收中断,应答主机。

 

  发送完这5个字节后,就退出了ADDR_DATA_MODE模式,继续串口发送的所有字节都使用space校验(先设置的校验位)。如果需要其他校验方式,可以调用SetParity()进行设置。

 

图3 ADDR_DATA_MODE发送波形图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值