• 正文
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

再聊一次GPIO模擬串口

5小時前
326
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

4年前寫過一篇關(guān)于GPIO模擬串口的文章:GPIO模擬串口

4年來陸陸續(xù)續(xù)有人聯(lián)系我要示例代碼,可見GPIO模擬串口是一個實(shí)際需求。最近我也又碰到了該需求,因為客戶用的MCU本身只有2個串口,而實(shí)際需要3個串口,所以需要額外模擬一個出來。

于是把之前的代碼又重新移植并測試了下,之前代碼發(fā)送的時候波特率可以達(dá)到115200bps,但是接收卻不行。當(dāng)時沒有細(xì)致分析過原因,這次認(rèn)真的分析了一下。

這次使用的MCU主頻運(yùn)行在48Mhz,模擬串口發(fā)送的邏輯和實(shí)現(xiàn)比較簡單,按照1/波特率周期,在定時器中斷服務(wù)函數(shù)里去發(fā)送串口對應(yīng)的bit位即可。實(shí)測波特率可以支持到256000bps。

接收的邏輯是:當(dāng)RX引腳檢測到下降沿時,進(jìn)入GPIO中斷,然后開啟一個定時器,第一次定時器周期設(shè)置為1/波特率的一半(目的是為了在中心處判斷是否為低電平,以表示是否為起始位),再之后就可以設(shè)置定時器周期為1/波特率,每隔此周期在定時器中斷服務(wù)函數(shù)里去采樣RX引腳電平,將數(shù)據(jù)接收完畢。

為什么接收時,波特率高了之后就數(shù)據(jù)異常呢? 未修改代碼之前,我測試波特率最高只能支持到19200bps,

我們在接收定時器中斷服務(wù)函數(shù)里加入點(diǎn)代碼,在串口每一個bit位處理前后進(jìn)行一次GPIO翻轉(zhuǎn)。通過波形來分析接收的處理時序:

加入上述代碼后,接收波特率最高只能支持到14400bps了,以下是波形圖,其中Channel 0是翻轉(zhuǎn)IO的波形,Channel 1是串口接收引腳波形

從上圖中我們首先看到第一個IO翻轉(zhuǎn)時間為14us,明顯高于后續(xù)其他翻轉(zhuǎn)時間。這個原因經(jīng)分析是代碼里用了一個除法運(yùn)算導(dǎo)致的。

我們優(yōu)化一下代碼,不用每次都在這里做一次除法。改完之后時間從原來的14us縮短為2us。除法導(dǎo)致運(yùn)行時間長具體可以查看之前的文章:在KEIL中勾選微庫后,延時函數(shù)為什么不準(zhǔn)了?

另外發(fā)現(xiàn)RX下降沿到IO口開始反轉(zhuǎn)的時間是50.8us,理論值應(yīng)該是35us才對。

為什么延遲了這么多呢?問題出在這里,這里也用了除法,同樣的我們也做一下修改

改完之后,這個時間就到了39us,偏差就小了很多。

可以進(jìn)一步優(yōu)化,在進(jìn)入下降沿中斷里一開始就先配置并啟動定時器

這樣對應(yīng)的時間還可以更準(zhǔn)確一點(diǎn)。

經(jīng)過以上修改后,19200bps接收正常,但是38400bps波特率還是異常,我們看一下波形:

問題出在第一個起始位采樣點(diǎn)有3us偏移,導(dǎo)致后續(xù)的采樣點(diǎn)相比自身的中心點(diǎn)偏的越來越大,以至于第2字節(jié)數(shù)據(jù)的起始位沒有來得及處理,進(jìn)而導(dǎo)致后續(xù)的數(shù)據(jù)處理錯誤。

我們將采樣首次的采樣時間做進(jìn)一步優(yōu)化,讓其更靠近中心點(diǎn),

這樣修改后波特率可以達(dá)到56000bps,但是再增加到57600bbps后還是有問題。其實(shí)原因也很簡單。還是因為首次1/2周期采集依然有偏差,隨著后續(xù)不斷按照1/波特率周期去采集,誤差越來越大。

我們進(jìn)一步做優(yōu)化,將后續(xù)按照固定周期去采集的方式改為動態(tài)調(diào)整周期值,最簡單的方式是周期大小做交替變化,這樣到最后一個字節(jié)就不會偏差那么大。

改完之后可以支持到57600bps,但是115200bps還是不行。

通過觀測波形可以看到,第一個IO翻轉(zhuǎn)下降沿到第二個IO翻轉(zhuǎn)下降沿的時間間隔出現(xiàn)了錯誤,理論應(yīng)該是9us,但實(shí)際只有5us。

經(jīng)分析原因是隨著波特率的提高,定時器的周期越來越短,當(dāng)波特率為115200bps時,1/波特率的一半 周期只有約4us,而起始位的代碼執(zhí)行時間已經(jīng)接近4us,所以定時器周期還沒有更新生效的時候,原來的一半周期中斷又來了。代碼優(yōu)化如下,首先更改周期。

這樣就可以達(dá)到115200bps的波特率:

以上記錄本次調(diào)試過程中遇到的問題及解決辦法。總結(jié)一下:要想GPIO模擬串口能夠提高波特率,需要通過精確的定時器配置、精簡的中斷服務(wù)程序、動態(tài)誤差補(bǔ)償?shù)却胧﹣韺?shí)現(xiàn)。關(guān)注公眾號:掃碼加入嵌入式交流群:

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

TopSemic,讓芯片使用更簡單。 專注分享:嵌入式,單片機(jī),STM32,ARM,RTOS,Linux, 軟硬件,半導(dǎo)體,電子技術(shù)等相關(guān)內(nèi)容。