加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

關(guān)于RS485自動(dòng)收發(fā)那些天坑

11/13 13:18
1416
閱讀需 11 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

來源:公眾號(hào)【魚鷹談單片機(jī)

本筆記將收錄到一條龍代碼倉庫

聽說,你被一條龍服務(wù)過?

對(duì)于?RS485 ,大家應(yīng)該都很熟悉了,在 modbus 協(xié)議中最常用。

但最近魚鷹在調(diào)試 RS485 時(shí)遇到了不少問題。

首先,我們知道 RS485 屬于半雙工,同一時(shí)刻,只能收或者發(fā)。

像這種情況,我們需要一種機(jī)制控制它的收發(fā),既可以是軟件,也可以是硬件。

硬件

一般RS485芯片,都會(huì)提供一個(gè)控制引腳完成收發(fā)工作。

這個(gè)引腳可能由用戶控制,也可能由芯片自動(dòng)控制(一般比較貴),還有第三種可能是,設(shè)計(jì)一種自動(dòng)收發(fā)的電路(應(yīng)該沒有超脫三界之外的吧)。

自動(dòng)收發(fā)電路很多,有用三極管控制的,也有用緩沖器的(好像是吧);因?yàn)?UART_TX 空閑電平為高,因此三極管導(dǎo)通,RE 接地,默認(rèn)為發(fā)。

但是我還看過一種用 S8550 實(shí)現(xiàn)的電路,基極接地,三極管默認(rèn)(空閑)不導(dǎo)通。

我不是電子工程師,無法判斷兩者電路的好壞,但我感覺默認(rèn)不導(dǎo)通更好,功耗更低,另外即使引腳未配置(剛上電,肯定沒那么快配置),那么也不會(huì)影響到總線上的其它節(jié)點(diǎn)通信,這個(gè)涉及到各個(gè) 485 節(jié)點(diǎn)上電時(shí)序問題。

這種電路好像因?yàn)槿龢O管開關(guān)頻率限制,無法做到很高頻率(一般115200,市面上購買的模塊基本都是類似這種電路)。

總之一句話,電路需要默認(rèn)處于接收狀態(tài),保證不會(huì)干擾總線通信,否則只要其中一個(gè)節(jié)點(diǎn)默認(rèn)狀態(tài)不是接收,那么無法通信(因此,如果無法通信,不如查一查是否有節(jié)點(diǎn)狀態(tài)不對(duì),而不是首先懷疑芯片燒掉了)。

另外其中一個(gè)節(jié)點(diǎn)發(fā)送,其它節(jié)點(diǎn)必須保持接收,不要發(fā)送數(shù)據(jù),否則數(shù)據(jù)肯定不是你想要的。

這種有頻率限制,那是否有那種頻率沒限制,同時(shí)不需要買貴的 RS485 自動(dòng)收發(fā)芯片的方案呢?

還真有,這要看你的 MCU 芯片本身是否支持了。

比如 IMX93,就可以實(shí)現(xiàn)(參考 IMX93RM.pdf,62.3.4)。

官網(wǎng)論壇也有對(duì)此實(shí)現(xiàn)方法:

https://community.nxp.com/t5/i-MX-Processors/RS485-iMX93/m-p/1896764#M225674

特別注意這里使用 RTS 引腳,而不是 CTS(其它芯片可能是用RTS)。

設(shè)備樹配置如下(一般在arch/arm64/boot/dts/freescale/xxx 下,引腳描述文件也在):

pinctrl_uart7: uart7grp {fsl,pins = <MX93_PAD_GPIO_IO08__LPUART7_TX 0x31e // TXMX93_PAD_GPIO_IO09__LPUART7_RX 0x31e // RXMX93_PAD_GPIO_IO11__LPUART7_RTS_B   0x31e   // DE>;};
&lpuart7 {  uart-has-rtscts;  rts-gpios = <&gpio2 7 GPIO_ACTIVE_HIGH>;  linux,rs485-enabled-at-boot-time;  // rs485 abilitata fin da subito al boot  rs485-rts-active-high;  rs485-rts-delay = <1 1>;};

當(dāng)你發(fā)送數(shù)據(jù)時(shí),DE 引腳會(huì)被芯片自動(dòng)控制電平狀態(tài)(默認(rèn)為低電平),從而實(shí)現(xiàn)不需要由用戶控制的自動(dòng)收發(fā)功能,并且沒有頻率限制(但受串口自身頻率限制)。

?軟件

說完硬件,再說軟件。

其實(shí)很多軟件或驅(qū)動(dòng)是會(huì)帶上 DE 引腳的控制(硬件挖坑,軟件負(fù)責(zé)填坑),比如如果你的開發(fā)板不支持上面的功能,那大概率這顆芯片的Linux串口驅(qū)動(dòng)會(huì)帶上該功能。

還有開源軟件 libmodbus 也考慮了這個(gè)引腳的控制。只是從效率和省心的角度,當(dāng)然是自動(dòng)收發(fā)爽了。

為了使用 485 的功能,不管 MCU 是否支持,都需要使能 485 模式,只是可能參數(shù)上需要進(jìn)行調(diào)整。下面是硬件支持的配置:

#include?<linux/serial.h>#include <sys/ioctl.h>#include <fcntl.h>#include <unistd.h>#include <stdio.h>        int fd = open("/dev/ttyLP7", O_RDWR);????if?(fd?<?0)?{
    }
    struct serial_rs485 rs485conf = {0};
    /* enable RS485 mode: */    rs485conf.flags |= SER_RS485_ENABLED;
    /* set logical level for RTS pin equal to 1 when sending: */    rs485conf.flags |= SER_RS485_RTS_ON_SEND;
    /* set logical level for RTS pin equal to 0 after sending: */    rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
    /* Set delays for RTS if needed */    rs485conf.delay_rts_before_send = 0;    rs485conf.delay_rts_after_send = 0;
    /* Enable full-duplex mode if supported */    // rs485conf.flags |= SER_RS485_RX_DURING_TX;
    if (ioctl(fd, TIOCSRS485, &rs485conf) < 0) {????????/*?Error?handling?*/    }

Python代碼

port = serial.Serial(port="/dev/ttyLP6", baudrate=115200, timeout=2, write_timeout=2)port.rs485_mode = serial.rs485.RS485Settings()

shell 腳本,注意關(guān)閉回顯

stty -F /dev/ttyLP6 115200 cs8 -cstopb -parenb -echoecho?"dddd"?>?/dev/ttyLP6

系統(tǒng)

從系統(tǒng)角度,我們也要知道一些基礎(chǔ)知識(shí)。

比如,串口設(shè)備名稱一般是 /dev/tty*。

通過命令?udevadm info 可以反查看該設(shè)備的硬件(設(shè)備樹)信息:

udevadm info /dev/tty* |grep DEVPATH=/devices/platform

輸出:

DEVPATH=/devices/platform/soc/107d001000.serial/tty/ttyAMA10

這樣我們可以知道,ttyAMA10?設(shè)備是芯片上的 107d001000 串口。

另外,我們可以通過系統(tǒng)啟動(dòng)信息查看掛載的串口:

dmesg | grep -i fsl-lpuart

剛插入的設(shè)備不知道掛載在哪個(gè)/dev/tty* 目錄下,同樣可以通過上面的類似命令找到:

dmesg?|?grep?-i?tty

設(shè)備樹節(jié)點(diǎn)查看路徑:

/sys/firmware/devicetree/base/soc@xx/bus@xxx/serial@xxxx

腳本直接控制 IO:

gpioset gpiochip0 14=1 gpioset?gpiochip0?14=0

這里面的?gpiochip0 和 14 也不是隨便選的,并且 chip 的選擇和我們常規(guī)的想法不同,具體可看? SDK 文檔說明。

設(shè)備樹編譯:

dtc -I dts -O dtb -o /path/to/your-device-tree.dtbo /path/to/your-device-tree.dts

總之,要在 Linux 環(huán)境中調(diào)試好串口驅(qū)動(dòng),遠(yuǎn)比 MCU 環(huán)境更復(fù)雜,需要掌握知識(shí)也更多。

希望本篇筆記對(duì)大家填坑有所幫助,歡迎一鍵三連支持魚鷹。

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

六年開發(fā)經(jīng)驗(yàn),豐富的KEIL調(diào)試經(jīng)驗(yàn),STM32使用經(jīng)驗(yàn),C語言運(yùn)用經(jīng)驗(yàn)。