牛洪海,臧 峰,周緒貴
(南京南瑞繼保電氣有限公司,江蘇 南京 211102)
通用異步收發(fā)器(universal asynchronous receiver transmitter,UART)是一種通用串行數(shù)據(jù)收發(fā)器。該收發(fā)器可以用來(lái)實(shí)現(xiàn)主機(jī)與輔助設(shè)備之間的通信,因其實(shí)現(xiàn)簡(jiǎn)單而被廣泛應(yīng)用于工業(yè)控制和通信領(lǐng)域[1-2]。UART數(shù)據(jù)傳輸主要通過(guò)中斷或直接內(nèi)存存取(direct memory access,DMA)的方式實(shí)現(xiàn)[3-4]?;谥袛喾绞降闹醒胩幚砥?central processing unit,CPU)使用率較高。當(dāng)有大批量的數(shù)據(jù)傳輸時(shí),將占用大量時(shí)間片,導(dǎo)致其他低優(yōu)先級(jí)程序無(wú)法得到有效執(zhí)行。DMA可以不經(jīng)由CPU控制而直接從內(nèi)存中存取數(shù)據(jù)[5-8],用于實(shí)現(xiàn)外設(shè)與存儲(chǔ)器之間,以及存儲(chǔ)器與存儲(chǔ)器之間的高速數(shù)據(jù)傳輸。該操作是根據(jù)地址空間的標(biāo)志[9],實(shí)現(xiàn)單通道源地址和目的地址之間的單向數(shù)據(jù)傳輸[10],為不同模塊之間的高速數(shù)據(jù)傳輸提供了一種可靠的方式。但由于DMA數(shù)據(jù)傳輸操作是定長(zhǎng)傳輸,即發(fā)送方將所需發(fā)送的報(bào)文按照發(fā)送方和接收方約定好的固定長(zhǎng)度進(jìn)行發(fā)送。采用DMA方式接收數(shù)據(jù)時(shí),如不足固定長(zhǎng)度就需要填充無(wú)效數(shù)據(jù)至固定長(zhǎng)度。當(dāng)使用DMA方式進(jìn)行數(shù)據(jù)接收時(shí),先向DMA控制器指定需要接收的字節(jié)個(gè)數(shù)。DMA控制器接收到指定字節(jié)后,產(chǎn)生DMA傳輸中斷。而在實(shí)際應(yīng)用時(shí),串口接收數(shù)據(jù)的字節(jié)個(gè)數(shù)往往是不固定的,因此無(wú)法直接使用DMA進(jìn)行數(shù)據(jù)接收。如何利用DMA方式接收不定長(zhǎng)數(shù)據(jù),已成為亟待解決的問(wèn)題。
基于上述存在的問(wèn)題,本文提出了一種通過(guò)DMA接收高速通信串口不定長(zhǎng)數(shù)據(jù)的方法。該方法步驟具體如下。①設(shè)置串口為DMA接收模式;②設(shè)置一個(gè)通用輸入/輸出引腳(general purpose input output,GPIO)引腳(本文為PC14引腳)為外部中斷控制(external interrupt controller,EIC),并且該引腳與串口的接收引腳(receive data,RXD)相連,產(chǎn)生外部中斷(interrupt)INT14;③配置外部引腳為下降沿模式,即下降沿產(chǎn)生外部引腳中斷,當(dāng)產(chǎn)生第一個(gè)下降沿時(shí),啟用0號(hào)定時(shí)器(timer counter 0,TC0);④設(shè)置外部中斷產(chǎn)生EVENT事件,并將此事件與定時(shí)器TC0相關(guān)聯(lián);⑤設(shè)置TC0的輸入事件,與外部引腳產(chǎn)生的事件相關(guān)聯(lián),并把TC0設(shè)置為Retrigger模式;⑥設(shè)置定時(shí)器超時(shí)時(shí)間,本文設(shè)為20 s,定時(shí)器超時(shí)后關(guān)閉,然后進(jìn)行報(bào)文處理,并重新使能DMA接收,以等待下一幀報(bào)文。方案設(shè)計(jì)原理如圖1所示。
圖1 方案設(shè)計(jì)原理圖
使用DMA進(jìn)行數(shù)據(jù)傳輸時(shí),需要對(duì)DMA控制器進(jìn)行配置。首先,選擇串口DMA接收通道。本文所述的接收通道為6。其次,配置DMA對(duì)應(yīng)通道的源地址。本文所述的是串口接收數(shù)據(jù)的寄存器地址。最后,配置DMA通道的目的地址,即存儲(chǔ)串口數(shù)據(jù)的緩沖區(qū)數(shù)組首地址,并設(shè)置目的地址為自增模式。
設(shè)置一個(gè)GPIO引腳(PC14引腳)為外部中斷模式,并把此引腳與串口的接收引腳RXD相連。配置外部引腳為下降沿模式,即下降沿產(chǎn)生外部中斷。當(dāng)產(chǎn)生第一個(gè)下降沿時(shí),使能定時(shí)器TC0。當(dāng)產(chǎn)生外部中斷時(shí),同時(shí)配置產(chǎn)生EVENT事件。此事件與定時(shí)器TC0的輸入事件相關(guān)聯(lián)。
定時(shí)器TC0設(shè)置為Retrigger模式,即接收到EVENT事件后,把定時(shí)器的累計(jì)時(shí)間清零。因?yàn)榇趫?bào)文是以低電平作為起始位,所以在串口發(fā)送數(shù)據(jù)時(shí),一定會(huì)產(chǎn)生下降沿,使定時(shí)器TC0不會(huì)因溢出而產(chǎn)生定時(shí)中斷。當(dāng)串口沒(méi)有數(shù)據(jù)報(bào)文發(fā)送時(shí),保持高電平,使定時(shí)器溢出,產(chǎn)生定時(shí)中斷。在定時(shí)中斷服務(wù)程序中,關(guān)閉定時(shí)器,重啟DMA接收通道以等待下一幀報(bào)文,并進(jìn)行串口報(bào)文處理。
本文采用的硬件是由Microchip公司提供的Atmel系列ATSAME54N20A芯片。該芯片具有豐富的外圍接口,包括32路可配置的DMA通道、16路可配置的外部中斷引腳、8路可配置的UART串口。相關(guān)串口硬件電路圖如圖2所示。ATSAME54N20A芯片可配置的UART引腳與RS-485芯片的A/B引腳相連接,RS-485芯片的接收引腳RXD與外部中斷引腳PC14相連。
圖2 串口硬件電路圖
為了使軟件能正常運(yùn)行,需要對(duì)芯片的一些模塊進(jìn)行初始化,主要包括晶振初始化、時(shí)鐘初始化等。本文主要設(shè)置如下。
①串口初始化,包括波特率設(shè)置(本文設(shè)置為5 Mbit/s)、奇偶校驗(yàn)位、停止位設(shè)置。
②DMA通道初始化,包括設(shè)置串口接收的DMA通道、DMA的源地址、目的地址。
③外部中斷初始化,包括設(shè)置PC14引腳為外部中斷模式,并產(chǎn)生事件,置下降沿首次檢測(cè)標(biāo)志start_timer_flag = 0[11]。
④定時(shí)器初始化,包括設(shè)置定時(shí)器超時(shí)時(shí)間,并設(shè)置定時(shí)器接收事件。
UART接收數(shù)據(jù)流程如圖3所示。
圖3 UART接收數(shù)據(jù)流程圖
當(dāng)完成初始化后,檢測(cè)PC14引腳是否有下降沿產(chǎn)生。如果檢測(cè)到下降沿并且start_timer_flag=0,那么啟動(dòng)定時(shí)器并置start_timer_flag=1;否則下降沿產(chǎn)生EVENT事件驅(qū)動(dòng)定時(shí)器累計(jì)時(shí)間清零。當(dāng)沒(méi)有下降沿產(chǎn)生時(shí),定時(shí)器超時(shí)進(jìn)入超時(shí)中斷服務(wù)程序。首先,關(guān)閉定時(shí)器;然后,進(jìn)行串口報(bào)文的處理,重新初始化DMA并置start_timer_flag = 0。
為了更好地理解上述設(shè)計(jì)方案,本節(jié)結(jié)合波形關(guān)系圖進(jìn)行詳細(xì)的性能分析。波形關(guān)系圖如圖4所示。
當(dāng)串口接收數(shù)據(jù)時(shí),串口數(shù)據(jù)波形如圖4(a)所示。首先,總線會(huì)檢測(cè)到一個(gè)低電平,代表有數(shù)據(jù)需要發(fā)送。該低電平就是RXD引腳的起始位。由于PC14外部引腳與RXD相連,所以PC14的波形與RXD引腳的波形一致。外部引腳波形如圖4(b)所示。將PC14設(shè)為外部中斷模式,而且是下降沿產(chǎn)生外部中斷,則當(dāng)RXD的起始位或串口數(shù)據(jù)位由“1”變“0”時(shí),會(huì)產(chǎn)生下降沿,PC14會(huì)產(chǎn)生外部中斷。外部中斷波形如圖4(c)所示。該外部中斷會(huì)產(chǎn)生一個(gè)EVENT事件。由于此事件與TC0的輸入事件相關(guān)聯(lián),TC0檢測(cè)到此事件后清除定時(shí)器的累計(jì)時(shí)間,然后重新從零開始計(jì)時(shí)。當(dāng)串口沒(méi)有數(shù)據(jù)要接收時(shí),總線保持高電平,即串口的RXD引腳一直保持在“1”狀態(tài)。此時(shí),沒(méi)有EVENT事件去清除定時(shí)器TC0的累計(jì)時(shí)間,導(dǎo)致定時(shí)器溢出產(chǎn)生定時(shí)中斷。該過(guò)程的定時(shí)器波形如圖4(d)所示。本文中設(shè)置的定時(shí)器超時(shí)時(shí)間是20 μs。在定時(shí)中斷服務(wù)程序中,重新使能DMA接收通道,以等待下一幀報(bào)文的到來(lái),并進(jìn)行串口報(bào)文的處理。
圖4 波形關(guān)系圖
為了驗(yàn)證上述分析的正確性,搭建5 bit/s串口通信測(cè)試環(huán)境,如圖5所示。
圖5 測(cè)試環(huán)境示意圖
①主備串口RS-485芯片進(jìn)行物理連接,即把主Atmel芯片的RS-485引腳與備Atmel的RS-485引腳相連。
②配置外部中斷引腳,即把RXD引腳與PC14引腳相連。
③為了監(jiān)視TC0何時(shí)進(jìn)入中斷服務(wù)程序,設(shè)置PC13為GPIO。當(dāng)TC0進(jìn)入超時(shí)中斷服務(wù)程序時(shí)置高電平,退出中斷服務(wù)程序時(shí)置低電平。
④驗(yàn)證程序是通過(guò)TC0超時(shí)中斷處理報(bào)文,而非DMA中斷處理報(bào)文。配置DMA接收緩沖區(qū)數(shù)值為300 B,但是主Atmel只發(fā)送200 B,通過(guò)示波器查看PC13是否能輸出脈沖信號(hào)。
⑤當(dāng)備Atmel接收到處理數(shù)據(jù)后,返回200 B至主Atmel。
測(cè)試結(jié)果分析如圖6所示。
圖6 測(cè)試結(jié)果分析圖
本文在分析串口通過(guò)DMA進(jìn)行數(shù)據(jù)接收的優(yōu)缺點(diǎn)基礎(chǔ)上,提出了一種通過(guò)外部中斷與定時(shí)器配合的通信方案。該方案既兼顧了DMA傳輸不需要CPU干預(yù)的優(yōu)點(diǎn),又解決了DMA只能接收固定長(zhǎng)度數(shù)據(jù)的缺點(diǎn);在節(jié)省了CPU處理時(shí)間的同時(shí),提高了串口接收數(shù)據(jù)的效率,有效擴(kuò)展了DMA在串口通信中接收不定長(zhǎng)報(bào)文的應(yīng)用。但此方案需要額外占用一個(gè)GPIO引腳和定時(shí)器,在芯片資源有限的情況下需要謹(jǐn)慎考慮。