非常不錯的文章|GPIO模擬串口

你是否遇到過某個MCU串口不夠的情況?  這時我們可以考慮用GPIO去模擬,如何具體實現呢?
首選我們需要了解串口的傳輸協議,
UART使用異步模式工作,不需要時鐘信號,其一般格式為:起始位+數據位+校驗位+停止位。其中起始位1位,數據位5~8位,校驗位0或1位,停止位1、1.5或2位。不過最常用的格式是1位起始位、8位數據位、沒有奇偶校驗、1位停止位,簡記為8/N/1
8/N/1格式的時序圖如下:
非常不錯的文章|GPIO模擬串口的圖1
空閑時數據線上規定為邏輯1。
開始傳輸數據時先發送起始位,規定為邏輯0,接收端會檢測這個下降沿,以便之后開始采樣接收數據。
起始位之后是數據位,規定先發送最低位,即LSB First。因為UART沒有時鐘信號,故使用波特率來確定每一位的長度,不過為保證檢測的準確性,實際采樣頻率會高于波特率,一般每一位會進行若干次采樣,取中間的采樣值作為這一位的結果。
奇偶校驗位一般不使用。
停止位一般使用1位,規定為邏輯1,除了表示傳輸結束外,停止位還可以起到時鐘同步的作用。
需要注意的是,這里的邏輯0并不一定是0V,這與使用的電平標準有關。對于TTL電平而言,邏輯0是0V,邏輯1是高電平(一般為3.3V或5V);對于RS-232電平而言,邏輯0是3V~15V,邏輯1是-3~-15V。
除了TX、RX、GND信號外,UART中還會有諸如RTS、CTS等流控信號,因為用得不是很多,此處就不總結了。
以發送0x23(無奇偶校驗)為例來說明,傳輸時序如下:
非常不錯的文章|GPIO模擬串口的圖2
注意是LSB First,也就是最低位先傳輸哦。
0x23,二進制表示為00100011,傳輸順序為1->1->0->0->0->1->0->0
掌握清楚這個時序那么也就好用GPIO模擬了,除了需要兩個GPIO,還需要兩個定時器(分別用于接收和發送時序控制),另外需要說明的是,為方便起見,采樣頻率這里就設置成了波特率。
1) 對于接收,當RX引腳檢測到下降沿時,進入GPIO中斷,然后開啟一個定時器,第一次定時器周期設置為1/波特率的一半(目的是為了在中心處判斷是否為低電平,以表示是否為起始位),再之后就可以設置定時器周期為1/波特率,每隔此周期在定時器中斷里去采樣RX引腳電平,將數據接收完畢
2)對于發送,首先發送一個起始位,之后以1/波特率為周期,在定時器中斷里去發送比特位即可。
我在NXP的MCU上做了實現,經過測試波特率可以達到38400. 有需要代碼的添加管理員微信獲取(見本文最后二維碼)。
以下是對程序的簡單說明:
1)gpio_uart_demo_init() 里可以配置UART的相關參數,如波特率,奇偶校驗,數據位長度
2)void gpio_uart_read(uint8_t *bufptr, uint32_t size, void (*rx_callback)(void)) 這個函數為uart 接收函數,第一個參數為數據存放buffer,第二個數據為接收長度,第三個參數為callback函數。注意目前的實現是調用此函數后,當接收完指定長度數據后,會停止接收數據。 如果之后要繼續接收,需要再次調用這個函數。
3)void gpio_uart_write(uint8_t *databuf, uint32_t num,void (*tx_callback)(void))這個函數為uart發送函數,第一個參數為發送數據buffer,第二個數據為發送長度,第三個參數為callback函數。
4)移植到其他不同平臺非常容易,只需要修改下GPIO和定時器配置即可。
本文編輯轉載自TopSemic嵌入式,轉載目的在于傳遞更多信息,并不代表本網贊同其觀點和對其真實性負責。版權歸原作者所有,如涉及作品內容、版權和其它問題,請在30日內與本公眾號聯系微信(kunyi346416,我們將在第一時間刪除內容!


登錄后免費查看全文
立即登錄
App下載
技術鄰APP
工程師必備
  • 項目客服
  • 培訓客服
  • 平臺客服

TOP