<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 基于GD32F305的多串口擴展模塊設計

基于GD32F305的多串口擴展模塊設計

作者:王維(新諾北斗航科信息技術(shù)(廈門(mén))股份有限公司,廈門(mén) 361022) 時(shí)間:2023-01-18 來(lái)源:電子產(chǎn)品世界 收藏
編者按:探討船舶導航儀對多串口的需求,提出一種用GD32F305單片機擴展多串口的方案,該方案采用USB通信。以RK3128主板為例介紹該擴展方案的硬件連接,接著(zhù)探討了單片機程序的具體實(shí)現,最后介紹用libusb進(jìn)行數據傳輸驗證。

船用很多電子設備是通過(guò)RS-422 串口傳輸數據,比如導航儀通過(guò)RS-422 串口傳輸NMEA - 0183數據,這些數據包括定位信息,導航信息,船艏信息,雷達信息等。這就要求船上的顯示終端需要有很多的串口來(lái)接收和發(fā)送數據。導航儀主板上的SoC 芯片原生串口數量有限,有時(shí)不能滿(mǎn)足用戶(hù)需要,這就需要外接模塊來(lái)擴展串口。 總線(xiàn)連接簡(jiǎn)單,信號只需要一對差分數據線(xiàn)傳輸,全速傳輸模式下帶寬可達12 Mbps;常見(jiàn)的船舶電子設備,其中RS-422最高傳輸需求波特率為115 200 bps,全速模式下傳輸率超過(guò)其100倍。總線(xiàn)擴展多個(gè)串口具有連線(xiàn)簡(jiǎn)單,傳輸率高的優(yōu)勢,適合做多。

本文引用地址:http://dyxdggzs.com/article/202301/442729.htm

本文探討的擴展模塊基于F305設計,采用USB 總線(xiàn)擴展最多5 路串口。F305是兆易創(chuàng )新公司出品的一個(gè)系列,該系列有一路USB總線(xiàn),5 路串口,CPU 核心采用Cortex-M4,可以運行在120 MHz,功能和性能均可滿(mǎn)足設計要求。

1   信號連接框圖

本文以一款RK3128 導航儀主板為例,探討方案。圖1 是主板信號連接圖,為重點(diǎn)說(shuō)明擴展方案,信號只保留USB 和串口部分。

1674012378293758.png

圖1 主板信號連接

RK3128 是瑞芯微出品的ARM Cortex-A7 4 核處理器,RK3128有3 個(gè)原生串口,其中串口2 和SD接口復用,實(shí)際可用的原生串口只有2 個(gè), 不夠連接外部設備,因此采用本文所述方案擴展串口。如上圖RK3128 有1 個(gè)USB OTG, 和1 個(gè)USB HOST 接口, 其中USB OTG用于其它通用外設( 如U 盤(pán),鼠標) 和引導鏡像燒寫(xiě),USB HOST 接口連接F305RB 擴展串口;GD32 的5 個(gè)串口全部引出用于連接其它船用電子設備。

GD32F305 系列單片機,CPU 核心采用Cortex-M4,最大運行頻率為120 MHz,內置最少64 KB SRAM,最少128 KB FLASH,包含1 個(gè)USB OTG端口,5 個(gè)串口(3個(gè)USART 和2 個(gè)UART,5 個(gè)串口支持最高9 Mbit/s波特率) 及其他豐富的外設資源。

2   單片機程序

兆易創(chuàng )新提供了GD32F305 的固件庫,其中包含工程模板,啟動(dòng)程序,豐富的外設調用程序及范例程序,并且還有用于簡(jiǎn)化USB 固件程序設計的USB 程序框架。為加速開(kāi)發(fā)過(guò)程,本方案充分利用了固件庫,并參照其中的USB CDC 范例代碼, 以USB 程序框架為基礎設計了USB 通信程序。單片機程序包括串口收發(fā)程序,USB 收發(fā)程序,數據轉發(fā)及命令處理程序,圖2 是整個(gè)單片機程序的概要圖。

1674012606996654.png

圖2 單片機程序概要

3   串口收發(fā)程序

串口收發(fā)封裝為以下函數:

void uart_init();

int uart_read(int chn, void*dat, int size);

int uart_write(int chn, constvoid* dat, int size);

int uart_ioctl(int chn, intcmd, void * args);

uart_init() 為串口初始化函數,用于初始化所有用到的串口,主要包括收發(fā)緩沖初始化,串口引腳功能初始化,功能寄存器初始化,中斷初始化。

uart_read() 為串口接收函數,chn 為串口編號, dat 為接收數據緩沖指針,size 為數據緩沖的字節數,返回值為實(shí)際讀取到的字節數。

uart_write() 為串口發(fā)送函數,chn 為串口編號,dat為要發(fā)送的數據指針,size 為要發(fā)送的數據字節數,返回實(shí)際寫(xiě)入串口發(fā)送緩沖的字節數。

uart_ioctl() 用于響應控制命令,chn 為串口編號,cmd 為命令編號,args 為命令參數,返回值根據不同命令定義。uart_ioctl() 主要處理串口波特率設置,回應當前對應串口發(fā)送緩沖字節數這兩個(gè)功能。

uart_read() 和 uart_write() 都是非阻塞設計,都是對相應的串口收發(fā)緩沖操作,實(shí)際數據收發(fā)是在中斷函數中處理。串口的中斷處理函數uart_irq_handle() 定義如下:

image.png

如上代碼, 串口中斷處理函數uart_irq_handle()調用了固件庫串口函數usart_interrupt_flag_get() 來(lái)判斷當前串口是否觸發(fā)了接收和發(fā)送中斷,usart_data_receive() 用于從當前串口接收寄存器讀取接收到的數據,usart_data_transmit() 用于將1 個(gè)字節的數據寫(xiě)入當前串口的發(fā)送寄存器發(fā)送數據。bfifo_in_byte() 和bfifo_out_byte() 是一種環(huán)形緩沖bfifo 的操作函數,bfifo_in_byte() 用于將1 個(gè)字節數據寫(xiě)入緩沖,bfifo_out_byte() 用于從緩沖讀取1 個(gè)字節數據,成功讀取返回true,如果緩沖無(wú)數據則返回false。

串口一次收發(fā)字節數不固定,環(huán)形緩沖很適合這種中斷處理隨機字節數據流的收發(fā)。環(huán)形緩沖是一種有固定存儲空間的數據結構,有讀、寫(xiě)兩個(gè)指針,讀取緩沖時(shí)只操作讀指針,不會(huì )修改寫(xiě)指針;往緩沖寫(xiě)入數據時(shí)只操作寫(xiě)指針而不會(huì )修改讀指針,環(huán)形緩沖的這種指針操作機制使得操作指針時(shí)不需要對指針做中斷互斥保護,因此不需要在收發(fā)數據時(shí)關(guān)閉開(kāi)啟中斷。

環(huán)形緩沖的操作,要將指針的操作限定在環(huán)形緩沖大小之內,一般可以采用取模運算,比如以f->ptr_out為環(huán)形緩沖的讀指針,f->size 為環(huán)形緩沖的字節大小,當讀取完一個(gè)字節,讀指針前進(jìn)為例,代碼如下:

image.png

本方案采用的bfifo 參照l(shuí)inux kernel 的kfifo, 在上述基礎上優(yōu)化了指針的操作,將環(huán)形緩沖的大小限定為2 的n 次方,n 為整數,將取模操作用與運算替代以加速計算過(guò)程。同上述例子一樣的操作,設f->mask=f->size-1,代碼如下:

image.png

由于串口接收到數據后,中斷處理函數將數據保存到了環(huán)形接收緩沖中,uart_read() 函數只需要從環(huán)形接收緩沖將數據讀出保存到形參;uart_write() 則將形參指向的數據寫(xiě)入到相應的環(huán)形發(fā)送緩沖中,并判斷當前串口發(fā)送中斷是否關(guān)閉,如果發(fā)送中斷關(guān)閉則重新打開(kāi),單片機將觸發(fā)發(fā)送中斷,發(fā)送環(huán)形發(fā)送緩沖的數據。

4   USB 數據收發(fā)程序

USB 數據收發(fā)程序封裝為以下函數:

image.png

usb_init() 為初始化函數,主要初始化USB 端口,USB 程序框架用到的定時(shí)器,USB 中斷,各種USB 描述符等。

usb_write() 為USB 數據送函數,負責將數據通過(guò)bulk 端點(diǎn)發(fā)往主機,dat 為要發(fā)送的數據指針,size 為要發(fā)送的數據字節數,返回實(shí)際發(fā)送的字節數。

usb_read() 是USB 數據讀取函數,負責讀取從主機發(fā)送往bulk 端點(diǎn)的數據,dat 為數據接收緩沖指針,size 為緩沖字節數,返回值為實(shí)際讀取到的字節數。

usb_set_class_callback() 用于設置USB Class 請求回調,callback 為回調函數,callback 的參數wIndex,bRequest,wValue,wLength 對應USB 標準控制傳輸的相應參數,dat 為數據緩沖指針,程序將bRequest 作為請求命令,當wLength > 0 時(shí),程序根據bRequest 內容讀取dat 或往dat 寫(xiě)數據。

USB 數據收發(fā)程序相比串口數據收發(fā)程序復雜很多,因此本方案借助兆易創(chuàng )新的USB 程序框架來(lái)簡(jiǎn)化設計。USB 程序框架實(shí)現了基本的USB 傳輸,調用固件庫提供的USB 設備初始化函數,設置好相應的回調程序指針和USB 描述符,可快速實(shí)現基本的USB 數據傳輸。

固件庫USB 設備初始化函數為 usbd_init(),其定義如下:

image.png

其中參數 udev 為 USB 驅動(dòng)句柄指針,usbd_init 將初始化其數據結構,之后程序操作 USB 設備將用到該句柄。

參數 core 為 USB 設備驅動(dòng)核心枚舉。USB 固件庫支持 USB 全速和 USB 高速設備,core 用來(lái)指示這兩種類(lèi)型設備的其中 1 種。(全速設備帶寬為 12 Mbps,可滿(mǎn)足設計,本方案實(shí)現的是全速設備;高速設備的帶寬為480 Mbps,實(shí)現高速USB設備,需要外加ULPI芯片。)

參數desc 為USB 描述符指針,desc 定義了設備描述符、配置描述符、接口描述符等。這些描述符用來(lái)描述USB 設備的屬性和用途。主機會(huì )在枚舉設備時(shí)獲取以確定設備是什么樣的設備,需要的總線(xiàn)資源,通訊方式等。

參數class_core 為USB 類(lèi)結構體,該結構體定義了USB 類(lèi)的初始化、反初始化、類(lèi)請求、數據收發(fā)等函數指針,程序在初始化時(shí)設置好這些指針,這些指針將在USB 程序框架中被調用。其定義如下:

image.png


image.png其中參數udev 為USB 驅動(dòng)句柄指針,usbd_init 將初始化其數據結構,之后程序操作USB 設備將用到該句柄。參數core 為USB 設備驅動(dòng)核心枚舉。USB 固件庫支持USB 全速和USB 高速設備,core 用來(lái)指示這兩種類(lèi)型設備的其中1 種。( 全速設備帶寬為12 Mbps,可滿(mǎn)足設計,本方案實(shí)現的是全速設備;高速設備的帶寬為480 Mbps,實(shí)現高速USB設備,需要外加ULPI 芯片。)

image.png

其中init 為初始化函數指針,當USB 連接時(shí)該指針指向的函數被調用,程序可在初始化函數中分配端點(diǎn),初始化收發(fā)緩沖等;deinit 為反初始化函數指針,USB 連接斷開(kāi)時(shí)被調用,程序要在這里釋放資源;req_proc 為設備請求函數指針,用于處理端點(diǎn)0 控制傳輸,當主機通過(guò)端點(diǎn)0 請求傳輸時(shí),該指針指向的函數被調用,本方案在這里響應類(lèi)請求,處理串口波特率設置和串口緩沖大小獲??;data_in 是處理data in 傳輸的函數指針,當主機向USB 設備請求數據時(shí),該指針指向的函數被調用,程序在這里準備好要發(fā)往主機的數據;data_out是處理data out 傳輸的函數指針,當主機往USB 設備發(fā)送數據時(shí),該指針指向的函數被調用,程序在這里接收主機下發(fā)的數據。

分析USB 程序框架,USB 數據傳輸采用DMA,1次可能傳輸多個(gè)字節數據;data_in 和data_out 都是在中斷處理程序中被調用,因此本文案設計一種環(huán)形緩沖加雙緩沖的方案來(lái)提高數據傳輸效率。環(huán)形緩沖用于避免變量互斥沖突,而雙緩沖用于提高DMA 傳輸效率。

上述雙緩沖,由1 個(gè)寫(xiě)緩沖和1 個(gè)讀緩沖構成,數據結構如下:

image.png

結構體成員buffer 為內存緩沖,buf_len 為雙緩沖的字節數,程序分配雙緩沖時(shí),分配buffer 空間為雙倍buf_len 字節數;index 為數據索引,用于指示當前讀寫(xiě)緩沖的地址;len 為當前寫(xiě)緩沖的數據字節數。

當程序往雙緩沖寫(xiě)數據時(shí),先獲取寫(xiě)緩沖的地址,寫(xiě)緩沖的地址為buffer+index*buf_len,再將數據寫(xiě)入寫(xiě)緩沖的末尾,地址為buffer+index*buf_len+len,之后再根據數據大小累加len。

當程序要讀取雙緩沖數據時(shí),程序先讀取當前寫(xiě)緩沖的字節數,獲取當前寫(xiě)緩沖的內存地址,再對雙緩沖做一次數據緩沖翻轉,將原來(lái)的讀寫(xiě)緩沖互換。雙緩沖的翻轉,重點(diǎn)是對index 進(jìn)行反運算,index = !index。當DMA 完成一次傳輸時(shí),程序可以快速翻轉雙緩沖,將讀寫(xiě)緩沖地址交給DMA控制器進(jìn)行下一次數據傳輸。如此可達到減少DMA 控制器等待時(shí)間的目的,以提高數據傳輸效率。

關(guān)于往bulk 端點(diǎn)發(fā)送數據,本方案定義了一個(gè)前文所述的環(huán)形緩沖fifo_bulk_in 和雙緩沖dbuf_bulk_in 來(lái)緩存數據,程序通過(guò)調用usb_write() 函數完成。usb_write() 主要負責將形參數據寫(xiě)入fifo_bulk_in,并檢測當前USB 框架是否正在傳輸數據,這個(gè)狀態(tài)由變量is_bulk_in_busy 表示, 如果還未啟動(dòng)數據傳輸,則取出環(huán)形緩沖fifo_bulk_in 的數據轉存至dbuf_bulk_in,翻轉dbuf_bulk_in,并調用固件庫函數usbd_ep_send() 啟動(dòng)一次DMA 傳輸。當單片機完成一次傳輸,USB 框架會(huì )調用回調函數data_in(),此時(shí)根據data_in() 傳入的端點(diǎn)號,判斷端點(diǎn)號為bulk 端點(diǎn)準備bulk 數據發(fā)送。檢測fifo_bulk_in 是否有數據和上次傳輸的字節數是否為空,函數根據以下幾種情況處理:

如果fifo_bulk_in 有數據,則和上述usb_write() 檢測到未啟動(dòng)傳輸時(shí)一樣,取fifo_bulk_in 數據轉存至dbuf_bulk_in,翻轉dbuf_bulk_in,再次發(fā)起一次DMA傳輸。

如果fifo_bulk_in 無(wú)數據,則發(fā)起一次0 數據傳輸以表示當前傳輸完成當fifo_bulk_in 無(wú)數據,且上次是0 數據傳輸時(shí),則將is_bulk_in_busy 變量設置為false,表示USB 程序框架已停止bulk 數據發(fā)送bulk 端點(diǎn)數據接收也采用了一個(gè)環(huán)形緩沖和一個(gè)雙緩沖來(lái)緩存數據,分別用變量fifo_bulk_out 和dbuf_bulk_out 表示。

當程序調用usb_read() 時(shí),先從fifo_bulk_out 中取數據存儲到形參接收緩沖,接著(zhù)檢查當前bulk 端點(diǎn)是否正在接收數據,該狀態(tài)用is_bulk_out_busy 表示,當is_bulk_out_busy 值為false 時(shí)調用固件庫函數usb_ep_recv(),發(fā)起DMA 傳輸將數據存至dbuf_bulk_out,并將is_bulk_out_busy 值設置為true。

當bulk 端點(diǎn)接收到數據時(shí),USB 程序框架調用data_out(),此時(shí)取出dbuf_bulk_out 的接收緩沖指針和接收數據字節數。先判斷fifo_bulk_out 剩余空間是否大于bulk 端點(diǎn)最大傳輸量,如果空間足夠則翻轉dbuf_bulk_out 并調用usb_ep_recv() 發(fā)起下一次DMA 傳輸;否則設置is_bulk_out_busy 值為false,表示bulk 端點(diǎn)接收空閑。最后通過(guò)之前暫存的dbuf_bulk_out 接收緩沖指針和接收數據字節數將本次傳輸接收到的數據轉存到fifo_bulk_out 完成本次bulk 端點(diǎn)數據接收處理。

當主機向單片機請求類(lèi)的控制傳輸時(shí),USB 程序框架將調用回調函數req_proc,請求的內容從req_proc 的參數req 獲得,req 的類(lèi)型usb_req 定義如下:

image.png

程序接收到類(lèi)控制傳輸請求時(shí),根據req->bmRequestType 判斷當前數據傳輸方向s,如果是IN 類(lèi)型的傳輸,則調用前文所述usb_set_class_callback() 設置的回調函數,傳遞req 的其它參數,如果req->wLength不為0,從回調函數讀取數據到全局變量ctlbuf 準備將數據回傳給主機。將ctlbuf 和req->wLength 傳遞給USB程序框架,USB程序框架將發(fā)送數據和狀態(tài)給主機。當數據發(fā)送完成時(shí),USB 程序框架調用前文所述data_in 通知程序,程序設置調用API 通知USB 程序框架無(wú)剩余數據,完成本次控制傳輸請求。

如果當前數據傳輸類(lèi)型是OUT 傳輸時(shí),則先判斷req->wLength 是否為0,如果req->wLength 為0 時(shí),直接調用前文所述usb_set_class_callback() 設置的回調函數即可。當req->wLength 不為0 時(shí),表示此次控制傳輸附帶數據,此時(shí)程序先用全局變量last_req 暫存req 值,然后調用API 通知USB 程序框架將把此次傳輸的數據保存到ctlbuf。當USB 程序框架接收完此次傳輸的數據,將調用前文所述的data_out 通知程序,這時(shí)程序將傳遞上述last_req 變量及ctlbuf 通知前文所述usb_set_class_callback() 設置的回調函數。

5   數據轉發(fā)程序

數據轉發(fā)程序負責將所有串口的數據通過(guò)USB 端口轉發(fā)到主機,同時(shí)通過(guò)USB 端口從主機讀取數據發(fā)送給指定的串口。中間的數據傳輸采用特定的數據格式對串口數據進(jìn)行封裝,標記同步頭,串口編號,字節數。本方案采用的數據包格式如下:

image.png

其中sync 為同步頭,固定為兩個(gè)’$’字符,用于解析時(shí)找到數據包的起始位置;chn 為串口編號,對應收發(fā)數據的串口;len 為數據字節數,用于表示后面dat 的實(shí)際大??;dat 為實(shí)際收發(fā)的數據,此處定義的數組大小不作為實(shí)際數據大小。

本方案定義了函數mux_pack_data() 用于封裝串口數據,其聲明如下:

image.png

其中dst 為數據緩沖地址,用于存放封裝好的數據包;chn 為串口編號;dat 為要傳輸的數據;len 為上述dat的數據字節數;返回封裝后的數據字節數。

數據轉發(fā)程序的串口接收部分主要操作為,逐一讀取各個(gè)串口的數據,調用mux_pack_data() 將數據封裝成一個(gè)個(gè)數據包存儲至臨時(shí)緩沖out_buf,最后調用前文所述USB 收發(fā)程序的發(fā)送函數usb_write() 將out_buf 的數據發(fā)給主機。

串口發(fā)送部分操作為,調用usb_read() 函數從主機讀取數據并解析,根據解析的數據包調用uart_write()往對應的串口發(fā)送數據。解析函數為mux_parse_data(),其聲明如下:

image.png

其中src 和len 為原始數據緩沖指針及數據大??;callback為回調函數;回調函數的參數chn 表示串口編號,dat為數據緩沖指針,len 為數據字節數。這里將從usb_read() 讀取到的數據傳入參數src 和len,當mux_parse_data() 解析到數據包,將通過(guò)callback 通知,此時(shí)程序將調用uart_write() 將數據發(fā)往指定串口。

6   命令處理程序

命令處理程序主要負責響應主機設置串口波特率,獲取串口寫(xiě)緩沖的請求。這些請求通過(guò)USB 控制傳輸的類(lèi)請求來(lái)處理,程序通過(guò)上文所述usb_set_class_callback() 設置類(lèi)請求回調函數。類(lèi)請求回調函數聲明如下:

image.png

bRequest 用于表示請求的命令,wIndex 表示串口編號,wValue 根據bRequest 不同用于表示設置的值,dat和wLength 用于當前請求需要補充的數據。

用宏定義表示請求的命令,REQ_SET_BAUD,REQ_ALL_UART_WRITE_ROOM 分別表示設置串口波特率,請求所有串口的剩余寫(xiě)緩沖空間。

當主機請求設置串口波特率,handle_class_request將被調用,bRequest 值為REQ_SET_BAUD,wValue為波特率除以100 的值(以9600 為例,wValue 值為96),wIndex 表示串口編號,此時(shí)程序調用前文所述串口函數uart_ioctl() 設置編號為wIndex 串口的波特率為wValue×100。

當主機請求所有串口寫(xiě)緩沖時(shí),bRequest 值為REQ_ALL_UART_WRITE_ROOM, 程序調用uart_ioctl() 逐一獲取每個(gè)串口的剩余寫(xiě)緩沖空間,寫(xiě)至dat參數。傳遞至dat 的數據結構如下:

image.png

其中chn_num 為串口數量,room 為各個(gè)串口的剩余寫(xiě)緩沖字節數,每個(gè)串口的剩余寫(xiě)緩沖字節數用2 個(gè)字節的類(lèi)型uint16_t 表示。

7   傳輸驗證

本方案USB 數據傳輸采用libusb 編寫(xiě)測試程序在LINUX 系統下驗證。libusb 是一個(gè)在應用層調用的跨平臺USB 庫,包含了USB 傳輸所需要的API。相比在編寫(xiě)內核驅動(dòng)來(lái)驗證本方案的數據傳輸,采用libusb 更快捷,更方便調試。

本方案驗證傳輸采用了libusb 中比較方便調試的同步I/O API,聲明如下:

image.png

其中libusb_control_transfer() 用于發(fā)起控制傳輸,參數dev_handle 為USB 設備句柄,data 為補充數據的指針,timeout 為超時(shí)毫秒數,其它參數對應控制傳輸USB 的標準定義。函數返回傳輸狀態(tài),成功傳輸返回枚舉值LIBUSB_SUCCESS。

libusb_bulk_transfer() 用于發(fā)起bulk 傳輸,dev_handle 為USB 設備句柄,endpoint 為bulk 端點(diǎn)編號,data 為接收或發(fā)送的數據緩沖指針,length 為數據字節數,actual_length 為實(shí)際傳輸的字節數,timeout 為超時(shí)毫秒數。

7.1 本方案主機接收據傳輸驗證,主要流程如下:

1)調用libusb_open_device_with_vid_pid(),根據設備vid,pid 打開(kāi)USB 設備s

2)通過(guò) libusb_control_transfer() 設置各個(gè)串口的波特率

3)通過(guò)電腦串口上發(fā)送測試文件到單片機的串口

4)電腦測試程序通過(guò)libusb_bulk_transfer() 從單片機USB 口讀取數據,通過(guò)轉發(fā)程序定義的協(xié)議解析數據包,根據串口號不同將數據分別存儲到不同的文件

5)對比發(fā)送和接收到的文件

7.2 主機發(fā)送數據傳輸驗證,流程如下:

1)在電腦測試程序通過(guò) libusb_control_transfer()設置各個(gè)串口的波特率

2)電腦測試程序加載測試文件,通過(guò)轉發(fā)程序定義的協(xié)議將文件數據按各個(gè)串口封裝數據包,通過(guò)libusb_bulk_transfer() 往單片機USB 口發(fā)送數據

3)通過(guò)電腦串口從單片機接收數據并根據不同串口保存到不同文件

4)對比發(fā)送和接收到的文件由于USB 傳輸速度遠高于本方案串口,為避免緩沖溢出導致數據丟失,主機發(fā)送數據時(shí)需要根據串口最大發(fā)送緩沖大小和設計的最高波特率定時(shí)通過(guò)libusb_control_transfer() 獲取各個(gè)串口的剩余發(fā)送緩沖空間,測試程序根據單片機串口剩余發(fā)送緩沖空間確定當時(shí)能發(fā)送的字節數。本方案設計單片機串口最大發(fā)送緩沖大小為1 024 個(gè)字節,最高波特率為115 200,根據最高波特率串口最高發(fā)送速度為115 200/10等于11 520 字節/s,根據以上參數可知最大緩沖填滿(mǎn)時(shí)間為1 024/11 520 ≈ 88 ms,因此本方案輪詢(xún)單片機串口剩余發(fā)送緩沖時(shí)間間隔為80 ms 即可。

測試程序運行命令如下:

image.png

mux-test 為測試程序,-b 選項為波特率,這里設置為 115200;-f 選項為測試數據文件名,這里為origin.txt,origin.txt 為64kB 的文本文件;-s 為電腦的串口 tty 設備名,這里/dev/ttyUSB0 - 4 表示加載 /dev/ttyUSB0、/dev/ttyUSB1、…… /dev/ttyUSB4。

程序運行后,將從電腦串口讀取到的數據存儲到./tty 目錄下,文件根據串口編號命名,為0.txt、1.txt、……4.txt;從USB 讀取到的數據存儲到./usb 目錄下,文件根據單片機串口編號命名,為0.txt、1.txt、…… 4.txt。當程序運行完,運行以下命令比較文件:

image.png

以下是運行結果:

image.png

根據結果可以判斷出收發(fā)的數據完全一致。

8   結束語(yǔ)

本文首先分析了船舶導航儀對多串口的需求,并提出USB 擴展多串口的方案,分析該方案的可行性及便利性,并提出兆易創(chuàng )新的GD32F305 單片機來(lái)實(shí)現這一方案。接著(zhù)以RK3128 主板為例介紹該擴展方案的硬件連接,然后探討了單片機程序的具體實(shí)現,最后介紹用libusb 進(jìn)行數據傳輸驗證。

參考文獻:

[1] GD32F305xx Datasheet Rev1.3[G].

[2] GD32F30x_User_Manual_Rev2.8.pdf[G].

[3] USBFS/HS Firmware Library User Guide Revision1.0[G].

[4] Firmware Library User Guide Revison 1.0[G].

[5] USB in a Nutshell[G].

(本文來(lái)源于《電子產(chǎn)品世界》雜志2023年1月期)

image.png

image.png


image.png



image.png


image.png


image.png



上一頁(yè) 1 2 3 4 下一頁(yè)

關(guān)鍵詞: 串口擴展 GD32 單片機 USB 202301

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>