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

再聊一次GPIO模擬串口

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

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

4年來(lái)陸陸續(xù)續(xù)有人聯(lián)系我要示例代碼,可見GPIO模擬串口是一個(gè)實(shí)際需求。最近我也又碰到了該需求,因?yàn)榭蛻粲玫?a class="article-link" target="_blank" href="/e/1604036.html">MCU本身只有2個(gè)串口,而實(shí)際需要3個(gè)串口,所以需要額外模擬一個(gè)出來(lái)。

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

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

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

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

我們?cè)诮邮斩〞r(shí)器中斷服務(wù)函數(shù)里加入點(diǎn)代碼,在串口每一個(gè)bit位處理前后進(jìn)行一次GPIO翻轉(zhuǎn)。通過(guò)波形來(lái)分析接收的處理時(shí)序:

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

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

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

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

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

改完之后,這個(gè)時(shí)間就到了39us,偏差就小了很多。

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

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

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

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

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

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

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

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

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

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

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

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

相關(guān)推薦

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

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