您当前的位置:五五电子网电子知识单片机-工控设备嵌入式系统-技术嵌入式系统应用实现RS485的方向切换 正文
嵌入式系统应用实现RS485的方向切换

嵌入式系统应用实现RS485的方向切换

点击数:7898 次   录入时间:03-04 11:39:06   整理:http://www.55dianzi.com   嵌入式系统-技术

      RS485总线是工业应用中非常成熟的技术,是现代通信技术的工业标准之一。RS485总线用于多站互连十分方便,用一对双绞线即可实现,采用平衡发送和差分接收,即在发送端驱动器将TTL电平信号转换成差分信号输出,在接收端接收器将差分信号变成TTL电平,因此具有抗共模干扰的能力。根据RS485标准,传送数据速率达100 kb/s时通信距离可达1200 m。

      RS485在嵌入式系统中的应用非常广泛。嵌入式系统可以通过RS485接口来控制终端设备。由于RS485是半双工模式,因此发送和接收的方向切换需要我们的关注和研究。如果方向切换方式选择不好可能会导致RS485驱动能力下降、软件执行效率下降,甚至导致系统异常等问题。

      本文分别给出硬件实现RS485方向切换和软件实现RS485方向切换两种方式。两种方式各有优点,硬件方式控制起来比较简单。软件方式的驱动能力更好,但是和嵌入式平台关系比较密切,不同的平台都需要调试和验证。

      1 硬件方式控制RS485方向

      图1所示为硬件控制RS485的电路图。电路中使用2N7002LT1G MOS场效晶体管把UART_TXD_485这个MCU输出的RS485发送信号逻辑取反后送给RS485芯片的RE/DE PIN脚。控制的原理是,当UART_TXD_485输出低电平时RS485芯片的DE使能;输出高电平时RE使能。默认情况下UART_TXD_485是高电平,RS485芯片处于接收状态。发送数据时,UART_TXD_485上面有高低电平信号变化,低电平信号通过RS485芯片SP3072EENL/TR直接输出,高电平信号通过外部上下拉电阻来控制。

      这种方法的优点是控制简单,软件不需要做额外的工作,控制RS485像控制RS232一样。但是这种方法的缺点是驱动能力可能不足,由于这种控制方法没有完全发挥出RS485驱动芯片自身的驱动能力,输出信号依赖于外部上下拉电阻,因此在复杂环境下,譬如很多负载需要控制时,就会存在驱动能力不足的问题。但是在一些简单的环境或者软件实现较复杂的平台下,使用这种方法还是切实可行的。

      

     

      图1 硬件控制RS485电路图

      2 软件方式控制RS485方向

      2.1 驱动能力分析

      在复杂的RS485控制环境下,用上面介绍的硬件方式来控制RS485的方向会存在比较突出的驱动能力不足的问题。修改上述控制方法,将TTL这一侧的2线控制改为3线控制,就是将收发控制信号不用当前的/TXD来控制,而从主控分出一根GPIO线来控制收发。

      按照输出电流计算,3线控制方式相对用2线控制的总线上下拉作为输出的方式,其驱动能力提高了25~50倍(不同厂家不同型号有差异),如果辅以终端电阻灵活配置的措施,RS485的驱动能力将完全不是问题。表1是两种控制方式驱动能力的对比。

      2.2 软硬件环境

      

     

      图2 软件控制方法中的硬件设计

      软件控制方法采用图2的硬件设计,图中很突出的修改是使用MCU的GPIO来控制RE和DE.RS485芯片的供电采用5 V供电,提高驱动能力。RS485芯片的RE和DE控制使用MCU的GPIO输出高低电平来控制。简单来说就是,在RS485进行数据传输时,通过GPIO来控制传输方向。这里采用的MCU是TI公司的DM8168处理器来实现软件的RS485切换功能。软件版本使用UBoot2010.06和linux2.6.37。用软件来实现RS485的收发,尽量要保证执行效率;要达到上面的目的就需要对串口驱动进行调试,使用串口驱动用到的软件资源和串口控制器本身的硬件资源来实现RS485的控制。

      表1 软件和硬件控制方式驱动能力的对比

      

     

      2.3 UBoot代码修改

      需要修改的文件:

      ① board/ti/ti8168/evm.c

      ② drivers/serial/ns16550.c

      ③ include/configs/ti8168_evm.h

      ti8168_evm.h文件中增加切换宏定义:

      #define CONFIG_RS485_DIR_SW 1

      evm.c文件中增加切换函数:

      void rs485_dir_sw(int rs485_dir){

      if (rs485_dir ==0)

      _raw_writel(RS485_DIR_MASK, TI81XX_GPIO1_CLEARDATAOUT);

      else

      _raw_writel(RS485_DIR_MASK, TI81XX_GPIO1_SETDATAOUT);

      }

      s16550.c串口驱动文件中增加RS485方向控制:

      void NS16550_putc(NS16550_t com_port, char c){

      #ifdef CONFIG_RS485_DIR_SW

      rs485_dir_sw(1);

      #endif

      ……//此处代码省略

      #ifdef CONFIG_RS485_DIR_SW

      while((serial_in(&com_port->lsr) & UART_LSR_TEMT) == 0)

      rs485_dir_sw(0);

      #endif

      }

      其中UART_LSR_TEMT表示发送BUF和移位寄存器为空。默认情况下RS485是接收状态,一旦要发送数据,就把RS485切换为发送状态。发送完数据后,等待发送BUF和移位寄存器为空,然后切换回接收状态,这里无需使用timeout。



www.55dianzi.com

      2.4 Linux代码修改

      需要修改的文件:

      ① arch/arm/machomap2/bordti8168evm.c

      ② drivers/serial/omapserial.c

      ③ include/linux/serial_core.h

      serial_core.h文件,UART_port结构体中增加set_rs485_direction函数指针,用于执行RS485的方向切换void (*set_rs485_direction)(int rs485_dir);原本考虑在uart_ops结构体中增加的,但是这个结构体是常量类型,对它不作改动,因此加到了uart_port结构体中。在该文件中添加相关宏定义和函数指针类型用于函数注册:

      #define SET_RS485_RX0

      #define SET_RS485_TX1

      typedef void (*set_rs485_direction_t)(int rs485_dir);//用于函数注册

      omapserial.c文件主要做了如下几点改动:

      ① 添加omap_rs485_dir_fun全局的函数指针。

      statIC set_rs485_direction_t omap_rs485_dir_fun[OMAP_MAX_HSUART_PORTS]={NULL, NULL, NULL, NULL, NULL, NULL}

      ② 外部驱动利用omap_rs485_dir_fun_reg注册函数对omap_rs485_dir_fun进行赋值。

      void omap_rs485_dir_fun_reg(int port_num, set_rs485_direction_t rs485_dir_fun){

      if (port_num>=OMAP_MAX_HSUART_PORTS)

      printk(KERN_ERR “%s, port_num error max is %d, but %d \\n”, __FUNCTION__, OMAP_MAX_HSUART_PORTS-1, port_num);

      omap_rs485_dir_fun[port_num]= rs485_dir_fun;

      }

      EXPORT_SYMBOL(omap_rs485_dir_fun_reg);

      ③ serial_omap_probe函数中对控制程序中用到的up->port.set_rs485_direction进行赋值。

      up->port.set_rs485_direction= omap_rs485_dir_fun[pdev->id];

      ④ 默认情况下RS485处于接收状态。

      ⑤ serial_omap_enable_ier_thri函数中把RS485切换为发送状态。

      static incline void serial_omap_enable_ier_thri(struct uart_omap_port *up){

      if (!(up->ier & UART_IER_THRI)) {

      /* rs485 dir change to tx */

      if (up->port.set_rs485_direction != NULL)

      up->port.set_rs485_direction(SET_RS485_TX);

      ……//此处代码省略

      }

      }

      ⑥ serial_omap_stop_tx函数中把RS485切换为接收状态。

      static void serial_omap_stop_tx(struct uart_omap_port *port){

      ……//此处代码省略

[1] [2]  下一页


本文关键字:嵌入式  嵌入式系统-技术单片机-工控设备 - 嵌入式系统-技术