第五章為深入淺出AMetal,本文內(nèi)容為5.8 UART 總線。
5.8 UART 總線
UART(Universal Asynchronous Receiver/Transmitter)是一種通用異步收發(fā)傳輸器,其使用串行的方式在雙機(jī)之間進(jìn)行數(shù)據(jù)交換,實(shí)現(xiàn)全雙工通信,數(shù)據(jù)引腳僅包含用于接收數(shù)據(jù)的RXD 和用于發(fā)送數(shù)據(jù)的TXD。
>>> 5.8.1 初始化
在使用UART 接口前,必須先完成UART 的初始化,獲取標(biāo)準(zhǔn)UART 實(shí)例句柄。在LPC82x 中,能夠提供UART 服務(wù)的外設(shè)有USART0、USART1 和USART2。注意,USART和UART 的概念很容易混淆,USART 比UART 多了一個(gè)S——同步(Synchronous),USART支持同步和異步兩種通信方式,而UART 僅支持異步通信方式。同步方式與異步方式主要的區(qū)別在于,同步方式需要使用一根時(shí)鐘線進(jìn)行時(shí)鐘的同步。由于使用較多的是異步通信方式,因此AMetal 僅僅提供了異步通信方式的通用接口,即LPC824 的USART 外設(shè)也僅被用作UART。為了方便用戶使用,AMetal 提供了與外設(shè)對(duì)應(yīng)的實(shí)例初始化函數(shù),詳見表5.23。
表5.23 UART 實(shí)例初始化函數(shù)(am_lpc82x_inst_init.h)
這些函數(shù)的返回值均為am_uart_handle_t 類型的UART 實(shí)例句柄,該句柄將作為UART通用接口中handle 參數(shù)的實(shí)參。類型am_uart_handle_t(am_uart.h)定義如下:
由于函數(shù)返回的UART 實(shí)例句柄僅作為參數(shù)傳遞給UART 通用接口,因此不需要對(duì)該句柄作其它任何操作。若函數(shù)返回的實(shí)例句柄的值為NULL,則表明初始化失敗,不能使用該實(shí)例句柄。如果使用串口0,則調(diào)用串口0 實(shí)例初始化函數(shù),即可獲取對(duì)應(yīng)的實(shí)例句柄:
>>> 5.8.2 接口函數(shù)
AMetal 提供了5 個(gè)與UART 相關(guān)的標(biāo)準(zhǔn)接口函數(shù)(am_uart.h),詳見表5.24。
表5.24 UART 標(biāo)準(zhǔn)接口函數(shù)
1. UART 控制
實(shí)現(xiàn)UART 的常見的控制,比如,波特率、數(shù)據(jù)位數(shù)和奇偶校驗(yàn)等。其函數(shù)原型為:
常見命令與對(duì)應(yīng)的p_arg 參數(shù),UART 硬件參數(shù)與UART 模式分別詳見表5.25、表5.26和表5.27。
表5.25 UART 常用控制命令
表5.26 UART 硬件參數(shù)
表5.27 UART 模式
為了便于傳遞不同類型的值,通常將p_arg 設(shè)置為void *類型。比如,在設(shè)置波特率時(shí),其類型為uint32_t;而在獲取波特率時(shí),其類型為 uint32_t *。如果返回AM_OK,說明本次控制命令執(zhí)行成功;如果返回-AM_EINVAL,說明因參數(shù)無效導(dǎo)致控制命令執(zhí)行失敗。比如,設(shè)置UART 為查詢模式,波特率為115200,8 位數(shù)據(jù)位,無校驗(yàn),1 位停止位,使用范例詳見程序清單5.101。
程序清單5.101 am_uart_ioctl()范例程序
由于對(duì)應(yīng)控制命令的參數(shù)均為uint32_t 類型,而函數(shù)形參為void *,因此需要使用強(qiáng)制類型轉(zhuǎn)換將uint32_t 強(qiáng)制轉(zhuǎn)換為 void *。
2. UART 發(fā)送(查詢模式)
如果以查詢的方式發(fā)送UART 數(shù)據(jù),則該函數(shù)會(huì)等待發(fā)送結(jié)束后返回。其函數(shù)原型為:
在使用該函數(shù)前,應(yīng)確保UART 工作在查詢模式,其返回值為成功發(fā)送數(shù)據(jù)的個(gè)數(shù)。比如,發(fā)送一個(gè)字符串"Hello World! ",詳見程序清單5.102。
程序清單5.102 am_uart_poll_send()范例程序
3. UART 接收(查詢模式)
如果以查詢的方式接收UART 數(shù)據(jù),則該函數(shù)會(huì)等到指定個(gè)數(shù)的數(shù)據(jù)接收完成后返回。其函數(shù)原型為:
在使用該函數(shù)前,應(yīng)確保UART 工作在查詢模式,其返回值為成功接收數(shù)據(jù)的個(gè)數(shù)。比如,從串口0 接收10 個(gè)數(shù)據(jù),詳見程序清單5.103。
程序清單5.103 am_uart_poll_receive()范例程序
4. 設(shè)置回調(diào)函數(shù)(中斷模式)
由于在查詢模式下收發(fā)數(shù)據(jù)會(huì)阻塞程序,因此最好的方式是使用中斷模式發(fā)送數(shù)據(jù)。當(dāng)中斷事件發(fā)生時(shí),通過回調(diào)函數(shù)與應(yīng)用程序交互。其函數(shù)原型為:
其中,callback_type 表示本次設(shè)置的類型,即設(shè)置發(fā)送回調(diào)函數(shù)還是接收回調(diào)函數(shù),詳見表5.28。
表5.28 callback_type 的含義(am_uart.h)
以獲取一個(gè)待發(fā)送的字符為例,pfn_callback 參數(shù)的類型為am_uart_txchar_get_t:
當(dāng)可以發(fā)送一個(gè)字符時(shí),UART 驅(qū)動(dòng)將自動(dòng)調(diào)用設(shè)置的該類型回調(diào)函數(shù),p_arg 為用戶自定義的參數(shù)(即為設(shè)置該類型回調(diào)函數(shù)時(shí)指定的p_arg),p_char 指針用于獲取一個(gè)待發(fā)送的字符,詳見程序清單5.104。
程序清單5.104 設(shè)置“獲取發(fā)送數(shù)據(jù)的回調(diào)函數(shù)”范例程序
以提交一個(gè)已經(jīng)接收到的字符為例,pfn_callback 參數(shù)的類型為am_uart_rxchar_put_t:
當(dāng)接收一個(gè)字符時(shí),UART 驅(qū)動(dòng)將自動(dòng)調(diào)用設(shè)置的該類型函數(shù),p_arg 為用戶自定義的參數(shù)(即為設(shè)置該類型回調(diào)函數(shù)時(shí)指定的p_arg),ch 為接收的字符數(shù)據(jù),詳見程序清單5.105。
程序清單5.105 設(shè)置“提交已接收數(shù)據(jù)回調(diào)函數(shù)”范例程序
5. 啟動(dòng)發(fā)送(中斷模式)
如果UART 使用中斷模式發(fā)送數(shù)據(jù),當(dāng)UART 發(fā)送器為空時(shí),就會(huì)調(diào)用設(shè)置的“獲取發(fā)送數(shù)據(jù)的回調(diào)函數(shù)”以獲取發(fā)送數(shù)據(jù)。其函數(shù)原型為:
使用中斷模式收發(fā)數(shù)據(jù)的范例程序詳見程序清單5.106。
程序清單5.106 中斷模式范例程序
該程序的功能是將每次收到的10 個(gè)數(shù)據(jù)原封不動(dòng)地發(fā)送出去,am_main()函數(shù)中的主循環(huán)可以不參與任何處理,即可實(shí)現(xiàn)串口數(shù)據(jù)的收發(fā)。
>>> 5.8.3 帶緩沖區(qū)的UART 接口
由于查詢模式會(huì)阻塞整個(gè)應(yīng)用,因此在實(shí)際應(yīng)用中幾乎都使用中斷模式。在中斷模式下,UART 每收到一個(gè)數(shù)據(jù)都會(huì)調(diào)用回調(diào)函數(shù)。如果將數(shù)據(jù)的處理放在回調(diào)函數(shù)中,很有可能因當(dāng)前數(shù)據(jù)的處理還未結(jié)束而丟失下一個(gè)數(shù)據(jù)?;诖耍珹Metal 提供了帶緩沖區(qū)的UART 接收函數(shù),其實(shí)現(xiàn)是在UART 中斷接收與應(yīng)用程序之間,增加一個(gè)接收緩沖區(qū)。當(dāng)串口收到數(shù)據(jù)時(shí),將數(shù)據(jù)存放在緩沖區(qū)中,應(yīng)用程序直接訪問緩沖區(qū)即可。
對(duì)于UART 發(fā)送,雖然不存在丟失數(shù)據(jù)的問題,但為了便于開發(fā)應(yīng)用程序,避免在UART中斷模式下的回調(diào)函數(shù)接口中一次發(fā)送單個(gè)數(shù)據(jù),同樣提供了帶緩沖區(qū)的UART 發(fā)送函數(shù)。當(dāng)應(yīng)用程序發(fā)送數(shù)據(jù)時(shí),將發(fā)送數(shù)據(jù)存放在發(fā)送緩沖區(qū)中,串口在發(fā)送空閑時(shí)提取發(fā)送緩沖區(qū)中的數(shù)據(jù)進(jìn)行發(fā)送。基于此,AMetal 提供了一組帶緩沖區(qū)的UART 通用接口,詳見表5.29。如無特殊需求,均建議使用帶緩沖區(qū)的UART 通用接口。
表5.29 帶緩沖區(qū)的UART 通用接口函數(shù)(am_uart_rngbuf.h)
1. 初始化
指定關(guān)聯(lián)的串口外設(shè)(相應(yīng)串口的實(shí)例句柄handle),以及用于發(fā)送和接收的數(shù)據(jù)緩沖區(qū),初始化一個(gè)帶緩沖區(qū)的串口實(shí)例,其函數(shù)原型為:
其中, p_dev 為指向am_uart_rngbuf_dev_t 類型的帶緩沖區(qū)的串口實(shí)例指針,在使用時(shí),只需要定義一個(gè)am_uart_rngbuf_dev_t 類型(am_uart_rngbuf.h)的實(shí)例即可:
其中,g_uart0_rngbuf_dev 為用戶自定義的實(shí)例,其地址作為p_dev 的實(shí)參傳遞。handle為 UART 實(shí)例句柄,用于指定該帶緩沖區(qū)的串口實(shí)際關(guān)聯(lián)的串口。p_rxbuf 和rxbuf_size 用于指定接收緩沖區(qū)及其大小,p_txbuf 和txbuf_size 用于指定發(fā)送緩沖區(qū)及其大小。
函數(shù)的返回值為帶緩沖區(qū)串口的實(shí)例句柄,可用作其它通用接口函數(shù)中handle 參數(shù)的實(shí)參。其類型am_uart_rngbuf_handle_t(am_uart_rngbuf.h)定義如下:
如果返回值為NULL,表明初始化失敗,初始化函數(shù)使用范例詳見程序清單5.107。
程序清單5.107 am_uart_rngbuf_init()范例程序
雖然程序?qū)⒕彌_區(qū)的大小設(shè)置為128,但實(shí)際上緩沖區(qū)的大小應(yīng)根據(jù)實(shí)際情況確定。若接收數(shù)據(jù)的緩沖區(qū)過小,則可能在接收緩沖區(qū)滿后又接收新的數(shù)據(jù)發(fā)生溢出而丟失數(shù)據(jù)。若發(fā)送緩沖區(qū)過小,則在發(fā)送數(shù)據(jù)時(shí)很可能因?yàn)榘l(fā)送緩沖區(qū)已滿需要等待,直至發(fā)送緩沖區(qū)有空閑空間而造成等待過程。
2. 發(fā)送數(shù)據(jù)
發(fā)送數(shù)據(jù)就是將數(shù)據(jù)存放到am_uart_rngbuf_init()指定的發(fā)送緩沖區(qū)中,串口可以進(jìn)行數(shù)據(jù)發(fā)送時(shí)(發(fā)送空閑),從發(fā)送緩沖區(qū)中提取需要發(fā)送的數(shù)據(jù)進(jìn)行發(fā)送。其函數(shù)原型為:
該函數(shù)將數(shù)據(jù)成功存放到發(fā)送緩沖區(qū)后返回,返回值為成功寫入的數(shù)據(jù)個(gè)數(shù)。比如,發(fā)送一個(gè)字符串“Hello World!“,詳見程序清單5.108。
程序清單5.108 am_uart_rngbuf_send()范例程序
注意,當(dāng)該函數(shù)返回時(shí),數(shù)據(jù)僅僅只是存放到了發(fā)送緩沖區(qū)中,并不代表已經(jīng)成功地將數(shù)據(jù)發(fā)送出去了。
3. 接收數(shù)據(jù)
接收數(shù)據(jù)就是從am_uart_rngbuf_init()指定的接收緩沖區(qū)中提取接收到的數(shù)據(jù),其函數(shù)原型為:
該函數(shù)返回值為成功讀取數(shù)據(jù)的個(gè)數(shù),使用范例詳見程序清單5.109。
程序清單5.109 am_uart_rngbuf_receive()范例程序
4. 控制函數(shù)
與UART 控制函數(shù)類似,用于完成一些基本的控制操作。其函數(shù)原型為:
“控制命令”和“對(duì)應(yīng)命令的參數(shù)”,與UART 控制函數(shù)am_uart_ioctl()的含義類似。帶緩沖區(qū)的UART 可以看作是在UART 基礎(chǔ)上的一個(gè)擴(kuò)展,因此絕大部分UART 控制函數(shù)的命令均可直接使用。之所以不支持“模式設(shè)置”命令,是因?yàn)閹Ь彌_區(qū)的UART 在初始化后始終工作在中斷模式,不能修改為查詢模式。除支持串口控制函數(shù)的絕大部分命令外,還新定義了一些擴(kuò)展命令,詳見表5.30。
表5.30 帶緩沖區(qū)的UART 擴(kuò)展控制命令
前5 條命令都是用于操作緩沖區(qū)的一些命令,“獲取可讀數(shù)據(jù)的個(gè)數(shù)”命令用于獲取接收緩沖區(qū)中已經(jīng)接收的數(shù)據(jù)個(gè)數(shù),“獲取已經(jīng)寫入數(shù)據(jù)的個(gè)數(shù)”命令可以獲取當(dāng)前已經(jīng)寫入發(fā)送緩沖區(qū)中的數(shù)據(jù)個(gè)數(shù)。當(dāng)不再需要發(fā)送或接收緩沖區(qū)的數(shù)據(jù)時(shí),即可直接使用“清空緩沖區(qū)”命令將對(duì)應(yīng)的緩沖區(qū)直接清空,其相應(yīng)的范例程序詳見程序清單5.110。
程序清單5.110 am_uart_rngbuf_ioctl()范例程序
“設(shè)置讀超時(shí)時(shí)間”命令用于設(shè)置讀超時(shí)時(shí)間,該時(shí)間在am_uart_rngbuf_receive()接收數(shù)據(jù)時(shí)起作用。在接收數(shù)據(jù)時(shí)會(huì)指定接收數(shù)據(jù)的個(gè)數(shù),在接收數(shù)據(jù)過程中,可能由于接收緩沖區(qū)中無數(shù)據(jù)可讀而進(jìn)入等待狀態(tài)。在默認(rèn)情況下,如果沒有設(shè)置讀超時(shí)時(shí)間,則會(huì)一直等到數(shù)據(jù)接收完成(接收到指定的數(shù)據(jù)個(gè)數(shù))才會(huì)返回。當(dāng)設(shè)置了超時(shí)時(shí)間后,假設(shè)設(shè)置超時(shí)時(shí)間為50ms,則在等待過程中超過50ms 都沒有接收到任何新數(shù)據(jù)時(shí),函數(shù)同樣會(huì)返回,其返回值為實(shí)際接收到的數(shù)據(jù)個(gè)數(shù),其相應(yīng)的范例詳見程序清單5.111。
程序清單5.111 設(shè)置超時(shí)時(shí)間范例程序
注意,超時(shí)時(shí)間并不是每次接收數(shù)據(jù)前都需要設(shè)置,往往只需要設(shè)置一次。如果需要修改超時(shí)時(shí)間,可以使用該函數(shù)重新設(shè)置一個(gè)超時(shí)時(shí)間。特別地,若希望接收數(shù)據(jù)不足時(shí)立即返回,則可以設(shè)置超時(shí)時(shí)間為AM_NO_WAIT(am_common.h),若需要恢復(fù)為一直等待到數(shù)據(jù)接收完成才返回,則可以設(shè)置超時(shí)時(shí)間為AM_WAIT_FOREVER(am_common.h)。
-
ametal
+關(guān)注
關(guān)注
2文章
24瀏覽量
11386
原文標(biāo)題:周立功:深入淺出AMetal—— UART 總線
文章出處:【微信號(hào):Zlgmcu7890,微信公眾號(hào):周立功單片機(jī)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論