英创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、校验位设置函数
intCSerial::SetParity(intparity)
{
structtermios new_opt;
intstatus;
unsignedintold_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;
}
elseif(parity == 1)
{
//使用Mark校验 标记地址
new_opt.c_cflag |= PARENB | CS8 | CMSPAR | PARODD;
}
elseif(parity == 2)
{ //使用偶校验
new_opt.c_cflag |= PARENB; /* Enable parity */
new_opt.c_cflag &= ~PARODD; /* 转换为偶效验*/
}
elseif(parity == 3)
{
//使用奇校验
new_opt.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
}
else
{
new_opt.c_cflag = old_ccflag;
}
status = tcsetattr(m_fd,TCSANOW,&new_opt);
returnstatus;
}
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条评论
快来发表一下你的评论吧 !