91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

RK3588串口RS485自動(dòng)收發(fā)控制:內(nèi)核驅(qū)動(dòng)層改造實(shí)戰(zhàn)

眺望電子 ? 2026-03-20 08:30 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

【前言】

在工業(yè)通信場(chǎng)景中,RS485因其遠(yuǎn)距離傳輸、抗干擾能力強(qiáng)、支持多節(jié)點(diǎn)組網(wǎng)等特性,成為工控領(lǐng)域的首選通信方式。然而,與RS232的全雙工通信不同,RS485采用半雙工模式——同一時(shí)刻只能發(fā)送或接收。這就要求我們必須精確控制收發(fā)狀態(tài)切換:

發(fā)送數(shù)據(jù)前:將控制腳置為高電平,使能發(fā)送器

數(shù)據(jù)發(fā)送完成后:將控制腳置為低電平,切換為接收模式

瑞芯微RK系列芯片(以眺望電子RK3588核心板為例)的UART控制器并未內(nèi)置RS485自動(dòng)控制功能,本文介紹一種內(nèi)核級(jí)驅(qū)動(dòng)改造方案,通過(guò)GPIO實(shí)現(xiàn)可靠的收發(fā)控制。

一、硬件連接原理

RS485收發(fā)器通常有以下引腳:

引腳功能控制方式
RO接收輸出連接UART RX
DI發(fā)送輸入連接UART TX
RE接收使能低電平有效
DE發(fā)送使能高電平有效
A/B差分信號(hào)總線接口

如下圖所示,將RE和DE引腳短接,通過(guò)單個(gè)GPIO統(tǒng)一控制,實(shí)現(xiàn)收發(fā)模式切換:

f54d2e52-23f3-11f1-96ea-92fbcf53809c.png

GPIO輸出高電平 → DE=1, RE=1 → 發(fā)送模式

GPIO輸出低電平 → DE=0, RE=0 → 接收模式

瑞芯微的內(nèi)核源碼沒有?帶的配置接?,需要我們修改如下驅(qū)動(dòng)代碼。


二、設(shè)備樹配置

在設(shè)備樹中為UART節(jié)點(diǎn)添加 rts_gpio 屬性:

--- a/arch/arm64/boot/dts/rockchip/talowe-rk3588-common.dtsi+++ b/arch/arm64/boot/dts/rockchip/talowe-rk3588-common.dtsi@@ -1057,13 +1057,14 @@&uart6 {&uart9 {pinctrl-names = "default";pinctrl-0 = <&uart9m2_xfer>;- // rts-gpio = <&gpio3 RK_PC4 GPIO_ACTIVE_HIGH>;+ rts_gpio = <&gpio3 RK_PC4 GPIO_ACTIVE_LOW>;status = "okay";};&uart0 {pinctrl-names = "default";pinctrl-0 = <&uart0m2_xfer>;+ rts_gpio = <&gpio3 RK_PC5 GPIO_ACTIVE_LOW>;status = "okay";};


重要提示:屬性名必須是 rts_gpio(單數(shù)形式),不能寫成 rts-gpios(復(fù)數(shù)形式)。若使用復(fù)數(shù)形式,串口驅(qū)動(dòng)會(huì)觸發(fā) mctrl_gpio 機(jī)制,導(dǎo)致本文方案失效。

f55e38f0-23f3-11f1-96ea-92fbcf53809c.png


三、驅(qū)動(dòng)層改造詳解

diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.cindex 2f7553cea..3cb98ae0d 100644--- a/drivers/tty/serial/8250/8250_core.c+++ b/drivers/tty/serial/8250/8250_core.c@@ -1024,6 +1024,8 @@int serial8250_register_8250_port(const struct uart_8250_port *up)#ifdefCONFIG_ARCH_ROCKCHIPuart->port.line = up->port.line;#endif+ if (up->rts_gpios > 0)+ uart->rts_gpios = up->rts_gpios;/* Take tx_loadsz from fifosize if it wasn't set separately */if (uart->port.fifosize && !uart->tx_loadsz)uart->tx_loadsz = uart->port.fifosize;diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.cindex 816c0122c..d37909cd3 100644--- a/drivers/tty/serial/8250/8250_dw.c+++ b/drivers/tty/serial/8250/8250_dw.c@@ -35,7 +35,8 @@#else#include"8250_dwlib.h"#endif-+#include+#include/* Offsets for the DesignWare specific registers */#defineDW_UART_USR 0x1f /* UART Status Register */#defineDW_UART_DMASA 0xa8 /* DMA Software Ack */@@ -573,7 +574,7 @@static int dw8250_probe(struct platform_device *pdev)int irq;int err;u32 val;+ int rts_gpios;regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (!regs)return dev_err_probe(dev, -EINVAL, "no registers defined\n");@@ -610,7 +611,16 @@static int dw8250_probe(struct platform_device *pdev)#ifdefCONFIG_ARCH_ROCKCHIPdata->irq = irq;#endif-+ rts_gpios = of_get_named_gpio(dev->of_node,"rts_gpio", 0);+ up->rts_gpios = rts_gpios;+ if (up->rts_gpios > 0)+ {+ printk("rts_gpios=%d\n", up->rts_gpios);+ gpio_direction_output(up->rts_gpios, 0);+ gpio_set_value(up->rts_gpios, 0);+ }++data->uart_16550_compatible = device_property_read_bool(dev,"snps,uart-16550-compatible");diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.cindex b7a3634c6..e7c49272a 100644--- a/drivers/tty/serial/8250/8250_port.c+++ b/drivers/tty/serial/8250/8250_port.c@@ -38,6 +38,8 @@#include"8250.h"+#include/* Nuvoton NPCM timeout register */#defineUART_NPCM_TOR 7#defineUART_NPCM_TOIE BIT(7) /* Timeout Interrupt Enable */@@ -1825,7 +1827,7 @@void serial8250_tx_chars(struct uart_8250_port *up)struct uart_port *port = &up->port;struct circ_buf *xmit = &port->state->xmit;int count;-+ int lsr,cnt;if (port->x_char) {uart_xchar_out(port, UART_TX);return;@@ -1838,7 +1840,11 @@void serial8250_tx_chars(struct uart_8250_port *up)__stop_tx(up);return;}+ if (up->rts_gpios > 0 )+ {+ gpio_set_value(up->rts_gpios, 1);+ }count = up->tx_loadsz;do {serial_out(up, UART_TX, xmit->buf[xmit->tail]);@@ -1878,7 +1884,19 @@void serial8250_tx_chars(struct uart_8250_port *up)if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))+ {__stop_tx(up);+ if (up->rts_gpios > 0 )+ {+ for (cnt = 0; cnt < 200; cnt++)+ {+ mdelay(3);+ lsr = serial_in(up, UART_LSR);+ if(UART_LSR_TEMT == (lsr & UART_LSR_TEMT))+ {+ break;+ }+ }+ gpio_set_value(up->rts_gpios, 0);+ }+ }}EXPORT_SYMBOL_GPL(serial8250_tx_chars);diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.hindex 46d76b035..e088fe6ba 100644--- a/include/linux/serial_8250.h+++ b/include/linux/serial_8250.h@@ -141,6 +141,7 @@struct uart_8250_port {/* Serial port overrun backoff */struct delayed_work overrun_backoff;u32 overrun_backoff_time_ms;+ int rts_gpios;};static inline struct uart_8250_port *up_to_u8250p(struct uart_port *up)diff --git a/include/uapi/linux/serial.h b/include/uapi/linux/serial.hindex cea06924b..9f3435e98 100644--- a/include/uapi/linux/serial.h+++ b/include/uapi/linux/serial.h@@ -134,7 +134,7 @@struct serial_rs485 {__u32 delay_rts_before_send; /* Delay before send (milliseconds) */__u32 delay_rts_after_send; /* Delay after send (milliseconds) */-+/* The fields below are defined by flags */union {__u32 padding[5]; /* Memory is cheap, new structs are a pain */

3.1核心數(shù)據(jù)結(jié)構(gòu)擴(kuò)展

修改 include/linux/serial_8250.h,在 uart_8250_port 結(jié)構(gòu)體中新增GPIO字段:

structuart_8250_port {// ... 原有字段/* Serial port overrun backoff */structdelayed_work overrun_backoff;u32 overrun_backoff_time_ms;intrts_gpios; /* 新增:RS485方向控制GPIO */};


3.2平臺(tái)驅(qū)動(dòng)初始化

修改 drivers/tty/serial/8250/8250_dw.c,在probe函數(shù)中解析設(shè)備樹GPIO:

#include#includestaticintdw8250_probe(structplatform_device *pdev){// ... 原有代碼intrts_gpios;// 從設(shè)備樹獲取GPIOrts_gpios =of_get_named_gpio(dev->of_node,"rts_gpio",0);up->rts_gpios = rts_gpios;if(up->rts_gpios >0) {printk("rts_gpios=%d\n", up->rts_gpios);gpio_direction_output(up->rts_gpios,0);gpio_set_value(up->rts_gpios,0); // 默認(rèn)接收模式}// ... 后續(xù)代碼}


3.3注冊(cè)時(shí)傳遞GPIO信息

修改 drivers/tty/serial/8250/8250_core.c:

intserial8250_register_8250_port(conststructuart_8250_port *up){// ... 原有代碼#ifdefCONFIG_ARCH_ROCKCHIPuart->port.line = up->port.line;#endif// 傳遞GPIO信息到新實(shí)例if(up->rts_gpios >0)uart->rts_gpios = up->rts_gpios;// ... 后續(xù)代碼}


3.4發(fā)送時(shí)序控制(核心邏輯)

修改 drivers/tty/serial/8250/8250_port.c 中的 serial8250_tx_chars 函數(shù):

#includevoidserial8250_tx_chars(structuart_8250_port *up){structuart_port*port = &up->port;structcirc_buf*xmit = &port->state->xmit;intcount;intlsr, cnt;// ... 原有檢查代碼/* ===== 發(fā)送前:置高GPIO,進(jìn)入發(fā)送模式 ===== */if(up->rts_gpios >0) {gpio_set_value(up->rts_gpios,1);}count = up->tx_loadsz;do{serial_out(up, UART_TX, xmit->buf[xmit->tail]);xmit->tail = (xmit->tail +1) & (UART_XMIT_SIZE -1);port->icount.tx++;if(uart_circ_empty(xmit))break;}while(--count >0);// ... 原有發(fā)送邏輯/* ===== 發(fā)送完成后:等待FIFO清空,再置低GPIO ===== */if(uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM)) {__stop_tx(up);if(up->rts_gpios >0) {// 輪詢等待發(fā)送完成(最多600ms)for(cnt =0; cnt rts_gpios,0); // 切換回接收模式}}}


四、關(guān)鍵設(shè)計(jì)要點(diǎn)

4.1為什么要在8250_core.c中傳遞GPIO?

因?yàn)?rts_gpios 定義在 struct uart_8250_port 結(jié)構(gòu)體中,而發(fā)送函數(shù) serial8250_tx_chars 操作的是該結(jié)構(gòu)體的實(shí)例。如果不通過(guò) serial8250_register_8250_port 函數(shù)傳遞,在 8250_port.c 中引用的 up->rts_gpios 將為0,導(dǎo)致GPIO控制失效。


4.2發(fā)送完成檢測(cè)策略

方案采用輪詢UART_LSR寄存器的方式檢測(cè)發(fā)送完成:

// UART_LSR_TEMT位為1表示發(fā)送FIFO和移位寄存器均為空if(UART_LSR_TEMT == (lsr & UART_LSR_TEMT))break;

每次輪詢間隔3ms

最大輪詢200次(總計(jì)600ms超時(shí))

適用于最高波特率115200bps下的典型幀傳輸



4.3多串口支持

本方案支持對(duì)多個(gè)UART同時(shí)進(jìn)行RS485改造,只需在設(shè)備樹中為各串口配置不同的GPIO即可。每個(gè)串口的GPIO狀態(tài)獨(dú)立維護(hù),互不干擾。



4.4注意事項(xiàng)

設(shè)備樹屬性名:使用 rts_gpio(單數(shù)),勿用 rts-gpios(復(fù)數(shù))

GPIO有效電平:根據(jù)RS485收發(fā)器規(guī)格選擇 GPIO_ACTIVE_LOW 或 GPIO_ACTIVE_HIGH

超時(shí)設(shè)置:若波特率較低或數(shù)據(jù)量較大,需適當(dāng)延長(zhǎng)輪詢超時(shí)時(shí)間


五、總結(jié)

本文介紹的驅(qū)動(dòng)層改造方案,通過(guò)設(shè)備樹配置+內(nèi)核驅(qū)動(dòng)修改,實(shí)現(xiàn)了RK3588 RS485的自動(dòng)控制。相比用戶空間輪詢方案,具有以下優(yōu)勢(shì):

時(shí)序精確:在數(shù)據(jù)發(fā)送的最開始置高GPIO,在所有數(shù)據(jù)徹底發(fā)送完成后置低,無(wú)用戶態(tài)切換延遲

應(yīng)用透明:應(yīng)用層無(wú)需任何修改,直接按普通串口使用

資源節(jié)?。簾o(wú)需外置RS485協(xié)議芯片,降低BOM成本

內(nèi)核標(biāo)準(zhǔn):基于8250串口驅(qū)動(dòng)框架,兼容性好,易于維護(hù)


相關(guān)代碼補(bǔ)丁可在眺望電子提供的SDK上應(yīng)用,適用于眺望電子RK3568、RK3588、RK3576等RK全系列芯片平臺(tái)。

廣州眺望電子科技有限公司專注于嵌入式處理器模組的研發(fā)與應(yīng)用,提供從硬件設(shè)計(jì)到驅(qū)動(dòng)開發(fā),系統(tǒng)解決方案的全流程技術(shù)支持。歡迎關(guān)注我們的公眾號(hào),獲取更多嵌入式項(xiàng)目開發(fā)實(shí)戰(zhàn)經(jīng)驗(yàn)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • RS485
    +關(guān)注

    關(guān)注

    40

    文章

    1338

    瀏覽量

    86065
  • 串口
    +關(guān)注

    關(guān)注

    15

    文章

    1623

    瀏覽量

    82991
  • 無(wú)線收發(fā)控制

    關(guān)注

    0

    文章

    2

    瀏覽量

    742
  • RK3588
    +關(guān)注

    關(guān)注

    8

    文章

    565

    瀏覽量

    7412
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    RK3588 PCB推薦疊及阻抗設(shè)計(jì)

    近期華秋電子聯(lián)合瑞芯微、凡億重磅發(fā)布了:《RK3588 PCB設(shè)計(jì)指導(dǎo)白皮書》,幫助開發(fā)者更好地規(guī)范利用RK3588開發(fā)產(chǎn)品,提高所設(shè)計(jì)的PCB質(zhì)量,在實(shí)戰(zhàn)中鞏固及提高PCB設(shè)計(jì)水平。本文
    發(fā)表于 08-10 09:32 ?1965次閱讀
    <b class='flag-5'>RK3588</b> PCB推薦疊<b class='flag-5'>層</b>及阻抗設(shè)計(jì)

    HaaS100通過(guò)RS485串口控制380V電機(jī)

    開發(fā)筆記:阿里云物聯(lián)網(wǎng)硬件HaaS100通過(guò)RS485串口控制380V電機(jī):涉及到modbus的驅(qū)動(dòng)函數(shù)使用,以及跟廠家的協(xié)議匹配,數(shù)值處理等方面。
    發(fā)表于 09-13 07:43

    RS485串口是如何完成數(shù)據(jù)收發(fā)的呢

    RS232和RS485串口有區(qū)別嗎?RS485串口是如何完成數(shù)據(jù)收發(fā)的呢?
    發(fā)表于 12-09 06:11

    RS485 232串口通信數(shù)據(jù)解析

    文章目錄(RS485 232串口通信數(shù)據(jù)解析實(shí)用干貨(1)生成一個(gè)適合你的列表創(chuàng)建一個(gè)表格設(shè)定內(nèi)容居中、居左、居右SmartyPants創(chuàng)建一個(gè)自定義列表如何創(chuàng)建一個(gè)注腳注釋也是必不可少的KaTeX
    發(fā)表于 02-22 07:14

    RS232-RS485串口通信詳解

    RS232-RS485串口通信詳解,很不錯(cuò)的東東
    發(fā)表于 08-09 15:08 ?30次下載

    RS232/RS485 串口檢測(cè)軟件分享

    RS232/RS485串口檢測(cè)軟件,感興趣的小伙伴們可以瞧一瞧。
    發(fā)表于 11-16 11:22 ?9次下載

    RS485串口轉(zhuǎn)mqtt協(xié)議網(wǎng)關(guān)

    RS485串口轉(zhuǎn)mqtt協(xié)議網(wǎng)關(guān)
    發(fā)表于 11-21 10:12 ?2811次閱讀
    <b class='flag-5'>RS485</b><b class='flag-5'>串口</b>轉(zhuǎn)mqtt協(xié)議網(wǎng)關(guān)

    RS485/RS232串口轉(zhuǎn)Modbus網(wǎng)關(guān)

    RS485/RS232串口轉(zhuǎn)Modbus網(wǎng)關(guān)
    發(fā)表于 12-03 16:59 ?3142次閱讀

    RS485或者rs232串口設(shè)備如何上傳mqtt平臺(tái)

    RS485或者rs232串口設(shè)備如何上傳mqtt平臺(tái)
    發(fā)表于 12-03 17:03 ?2252次閱讀

    modbus轉(zhuǎn)MQTT協(xié)議網(wǎng)關(guān)RS485串口接入華為云

    modbus轉(zhuǎn)MQTT協(xié)議網(wǎng)關(guān)RS485串口一鍵快速接入華為云金鴿BL101E
    發(fā)表于 12-06 15:01 ?1839次閱讀
    modbus轉(zhuǎn)MQTT協(xié)議網(wǎng)關(guān)<b class='flag-5'>RS485</b><b class='flag-5'>串口</b>接入華為云

    RS485串口轉(zhuǎn)以太網(wǎng)接入MODBUS TCP第三方云平臺(tái)

    RS485串口轉(zhuǎn)以太網(wǎng)接入MODBUS TCP第三方云平臺(tái)
    發(fā)表于 12-06 14:57 ?2811次閱讀

    (RS485 232串口通信數(shù)據(jù)解析實(shí)用干貨(1)

    文章目錄(RS485 232串口通信數(shù)據(jù)解析實(shí)用干貨(1)生成一個(gè)適合你的列表創(chuàng)建一個(gè)表格設(shè)定內(nèi)容居中、居左、居右SmartyPants創(chuàng)建一個(gè)自定義列表如何創(chuàng)建一個(gè)注腳注釋也是必不可少的KaTeX
    發(fā)表于 12-28 19:35 ?17次下載
    (<b class='flag-5'>RS485</b> 232<b class='flag-5'>串口</b>通信數(shù)據(jù)解析實(shí)用干貨(1)

    如何實(shí)現(xiàn)RS485串口通訊采集模擬量

    如何實(shí)現(xiàn)RS485串口通訊采集模擬量流程分享
    的頭像 發(fā)表于 08-23 11:30 ?5896次閱讀
    如何實(shí)現(xiàn)<b class='flag-5'>RS485</b><b class='flag-5'>串口</b>通訊采集模擬量

    如何實(shí)現(xiàn)開關(guān)量輸入與繼電器輸出聯(lián)動(dòng)功能RS485串口通訊

    如何實(shí)現(xiàn)開關(guān)量輸入與繼電器輸出聯(lián)動(dòng)功能RS485串口通訊流程分享
    的頭像 發(fā)表于 08-23 11:33 ?3015次閱讀
    如何實(shí)現(xiàn)開關(guān)量輸入與繼電器輸出聯(lián)動(dòng)功能<b class='flag-5'>RS485</b><b class='flag-5'>串口</b>通訊

    工業(yè)RS485串口網(wǎng)關(guān)實(shí)現(xiàn)485接口數(shù)據(jù)采集

    其成為首選的串行接口。但是RS485通信的最遠(yuǎn)的短離也只有1.2KM,無(wú)法實(shí)現(xiàn)遠(yuǎn)程控制,對(duì)于分布式的設(shè)備來(lái)說(shuō),環(huán)境不適合布線或者布線成本高,數(shù)據(jù)采集遠(yuǎn)程監(jiān)控存在問(wèn)題。那么如何解決這個(gè)問(wèn)題呢? 利用物通博聯(lián)工業(yè)RS485
    的頭像 發(fā)表于 02-03 16:56 ?2759次閱讀
    工業(yè)<b class='flag-5'>RS485</b><b class='flag-5'>串口</b>網(wǎng)關(guān)實(shí)現(xiàn)<b class='flag-5'>485</b>接口數(shù)據(jù)采集