[原創]CC2540通過UART接收115200bps數據的方法


這個問題比較有意思,而且具有一定的普遍性,寫出來和大家一起分享。

最近做了一個物聯網項目,目的是為原有的一個只能通過UART接口控制的設備添加藍牙功能。

采用的主體結構是把CC2540模塊和設備通過UART連接,然后在CC2540上實現相應的Profile,手機通過Profile和CC2540通訊,而CC2540通過UART接口和設備通訊。這樣子經過CC2540的轉換,就可以實現用手機APP對設備進行控制了。

cc2540是TI的 藍牙4.0(BLE)SOC芯片,特性如下:

  • 256KB FALSH
  • 16KB RAM
  • 32MHz的單周期增強型51 Core
  • 藍牙協議棧和用戶的應用程序可以在單芯片上運行
  • 極低的功耗

其實整個項目都很普通,沒有什么難度。除了一個地方,就是用CC2540捕捉UART數據。這里的設備數據包大小不定,最大不超過1KB。

接收UART數據不是很簡單嘛?單片機都能做,為嘛這個地方會有問題呢?

因為CC2540是一顆SOC芯片,也就是個System on chip。CC2540除了運行用戶的應用程序以外,還運行藍牙4.0的協議棧,收發無線數據包相關的事件都是由協議棧自動處理。

好的,問題來了。根據TI的資料,每次處理數據包相關事件可能需要占用CPU長達幾個毫秒的時間,並且在這個時間中是完全關閉中斷的。

而平時我們從UART接收數據,最常用就是通過中斷。配置好設備的寄存器,使得每次UART收到數據就產生一次中斷,然后在中斷中對數據進行讀取。

115200bps的速率下1秒大約有 115200/8=14400Byte的數據發送,1ms也就是14Byte。如果通過中斷的方式來接收數據,假設CPU處理運行協議棧花了1ms時間,而這時恰好有數據過來。就會丟失14Byte,這肯定是沒法用的。so,此路不通。

幸好還有更好的方法,也就是通過DMA接收數據

DMA(Direct Memory Access,直接內存存取) 是所有現代電腦的重要特色,它允許不同速度的硬件裝置來溝通,而不需要依於 CPU 的大量中斷負載。否則,CPU 需要從來源把每一片段的資料復制到暫存器,然后把它們再次寫回到新的地方。在這個時間中,CPU 對於其他的工作來說就無法使用。

DMA的特色就是可以不經過CPU來傳輸數據,正適合當前這種CPU分身乏術的情況。經查DataSheet,CC2540一共有4個DMA通道,無線協議棧用掉了一個。

通過把DMA的觸發源設置為UART接收到數據,傳輸源地址設置為UART數據寄存器,傳輸目的地址設置為一片Buf,並設置為每次傳輸源地址不變,目的地址自增。就可以在DMA實現DMA自動搬運UART數據了。

不過不管開辟多大的DMA接收Buf,也總有滿的時候。當DMA Buf滿了,或者需要對DMA Buf中數據進行處理的時候,就需要暫停DMA傳輸。而這時如果有數據進入,就會丟失。

為了解決這個問題,這里使用經典的Ping-Pang DMA操作方法。

Ping-Pang通過開啟雙DMA通道,實現任意時刻都有一個DMA通道在接受數據中,不會丟數據。而且通過Ping-Pang切換,DMA Buf不會滿,也就可以持續接收。

這里具體實現上先開辟兩次要(a,b)一主要(x)三個緩沖區,並建立兩個DMA通道,分別把DMA數據傳輸到兩個次要緩沖區ab中。通過一個定時器在兩個DMA通道之間來進行切換。每次切換到新的次要緩沖區之后,就把舊的次要緩沖區中的數據導出到主要接收緩沖x中。這樣就可以在x中對數據進行處理,並且過程中不會丟失數據。

不過這里還有一個坑,那就是怎樣獲得DMA傳輸數據的長度

使用Ping-Pang 方法操作DMA時,需要不斷導出已經保存在DMA Buf中的數據。這時就需要知道DMA Buf中數據的長度。有些芯片的DMA控制器有相關接口,可以直接從寄存器中讀取到傳輸計數值。不過CC2540沒有這個功能。。。TI啊TI,你這樣做事情做一半,真的好么-_-#

這里顯然不可以通過把DMA接收緩沖初始化為0,然后判斷非0數據的長度來實現,因為UART接收到的數據可能是0。

后來想了個方法來解決。思路就是開始每一輪DMA傳輸之前把DMA接收緩沖區的數據初始化為固定值,比如0x00。然后把DMA控制器配置為每次傳輸雙字節數據[1]。通過查詢DataSheet,UART控制器的數據寄存器后面一字節是波特率寄存器的一部分,這是一個固定值而且不為零。這樣DMA每次傳輸會傳輸1字節UART接收的數據+1字節固定數據到接收Buf中。通過分析收到固定數據的長度,就可以知道DMA收到數據的長度。

這里一共有三個地方需要注意的:

  • 通過DMA接收數據
  • DMA Ping-Pong操作
  • 通過給數據添加"尾巴"來實現DMA傳輸計數

通過以上方法,就完美的解決了UART接收數據的問題。現在帶無線協議棧的Soc芯片被廣泛使用,這一類芯片的接收數據問題,都可以通過這樣的思路來解決。

AlexaZhou.xyz版權所有,轉載請注明


  1. DMA控制器一般可以配置為觸發源每次觸發,傳輸單字節,雙字節,四字節數據。 ↩︎


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM