嵌入式硬件通信接口協(xié)議-UART(四)設(shè)計(jì)起止式的應(yīng)用層協(xié)議
解析思路是:
本文引用地址:http://www.ex-cimer.com/article/201903/398678.htm1.確保環(huán)形緩沖區(qū)有足夠一個(gè)幀結(jié)構(gòu)的數(shù)據(jù)量,否則返數(shù)據(jù)量不足的錯(cuò)誤;
2.接著讀出一個(gè)字節(jié)判斷幀頭標(biāo)志是否為0x55,否則返幀頭錯(cuò)誤;
3.再次讀一個(gè)字節(jié)作為幀長(zhǎng)度數(shù)據(jù),且長(zhǎng)度至少3個(gè)字節(jié)(2個(gè)CRC校驗(yàn)值+至少1字節(jié)數(shù)據(jù)包),否則返幀長(zhǎng)度錯(cuò)誤;
4.讀出幀長(zhǎng)度數(shù)據(jù),如果此時(shí)環(huán)形緩沖區(qū)的可讀數(shù)量比長(zhǎng)度數(shù)值小,出現(xiàn)這情況的原因可能是幀長(zhǎng)度字段在發(fā)送期間出現(xiàn)異常,或是對(duì)端設(shè)備串口傳輸慢而未完整傳輸一幀,此時(shí)可做適當(dāng)?shù)难訒r(shí)等待,如果超時(shí)退出,且返幀長(zhǎng)度錯(cuò)誤;
5.繼續(xù)讀出2個(gè)字節(jié)作為CRC校驗(yàn)值,且需要注意先收到的是crc16L,先收到小端數(shù)值;
6.緊接著把數(shù)據(jù)包讀出,此時(shí)讀的長(zhǎng)度應(yīng)該是第4步中的幀長(zhǎng)度數(shù)據(jù)少2個(gè)字節(jié);
7.最后對(duì)數(shù)據(jù)包計(jì)算一個(gè)CRC校驗(yàn)值,對(duì)比接收到的校驗(yàn)值,校驗(yàn)值不一致則返錯(cuò)誤校驗(yàn)碼。
函數(shù)返回值符合以下枚舉的錯(cuò)誤碼:
被解析數(shù)據(jù)源
看到這里也許仍有疑問(wèn),用于解析的數(shù)據(jù)源哪來(lái)?數(shù)據(jù)什么時(shí)候被寫(xiě)進(jìn)環(huán)形緩沖區(qū)內(nèi)?
參考上一篇《嵌入式硬件通信接口-使用RingBuffer處理數(shù)據(jù)(二)詳細(xì)設(shè)計(jì)過(guò)程》介紹的關(guān)于向環(huán)形緩沖區(qū)寫(xiě)入一個(gè)字節(jié),但dclib_ringbuffer這個(gè)模塊屬于應(yīng)用庫(kù)模塊層,而如果直接把dclib_rb_writebyte這一個(gè)接口放在串口接收中斷里執(zhí)行,這就破壞了系統(tǒng)的架構(gòu)層次,對(duì)工程代碼的維護(hù)和移植是個(gè)麻煩事,因此采用回調(diào)函數(shù)的方式。
嵌入式開(kāi)發(fā)工程師都知道,一般在使用官方的庫(kù)時(shí),經(jīng)常會(huì)遇到需要自己實(shí)現(xiàn)一些回調(diào)函數(shù),從而利用注冊(cè)接口把回調(diào)函數(shù)傳遞給庫(kù)或者驅(qū)動(dòng)層,使庫(kù)或者驅(qū)動(dòng)層在執(zhí)行時(shí)調(diào)用該回調(diào)函數(shù)。
根據(jù)這個(gè)思路,同樣的這里也采用回調(diào)函數(shù)的形式,回調(diào)函數(shù)內(nèi)完成了把串口接收到的數(shù)據(jù)寫(xiě)入環(huán)形緩沖區(qū)內(nèi)。
回調(diào)函數(shù)的實(shí)現(xiàn)源碼截圖:
事實(shí)上僅僅調(diào)用了dclib_ringbuffer功能里的寫(xiě)一字節(jié)接口dclib_rb_writebyte,回調(diào)函數(shù)傳進(jìn)來(lái)的參數(shù)dat就是串口接收到的數(shù)據(jù)。
有了回調(diào)函數(shù),還要把這個(gè)回調(diào)函數(shù)的地址傳給底層驅(qū)動(dòng),這也就是常說(shuō)的“注冊(cè)”的過(guò)程,注冊(cè)接口在固件板級(jí)接口層里串口模塊dcbsp_uart實(shí)現(xiàn),注冊(cè)接口時(shí)dclib_uart_callback_reg函數(shù):
又偏題了,關(guān)于回調(diào)函數(shù)在此不做深入論述。
簡(jiǎn)而言之,環(huán)形緩沖區(qū)寫(xiě)入一字節(jié)的執(zhí)行過(guò)程,放在回調(diào)函數(shù)里,當(dāng)串口接收中斷觸發(fā)后,中斷里會(huì)根據(jù)注冊(cè)的回調(diào)函數(shù)地址,進(jìn)而執(zhí)行回調(diào)函數(shù),實(shí)現(xiàn)對(duì)環(huán)形緩沖區(qū)寫(xiě)入一個(gè)字節(jié)數(shù)據(jù)。如此操作的理由是不改變工程代碼的分層架構(gòu),并且便于維護(hù)與移植!
為了縮減篇幅,最后貼上測(cè)試代碼的部分:
最后也附上調(diào)試期間串口打印的解析結(jié)果:
起止式幀結(jié)構(gòu)的講解稍有匆忙,篇幅也略大,文中基礎(chǔ)技術(shù)要點(diǎn)未能細(xì)致講解,后續(xù)統(tǒng)籌規(guī)劃再做單獨(dú)介紹!
接下來(lái)在此幀結(jié)構(gòu)基礎(chǔ)上,講述如何設(shè)計(jì)在數(shù)據(jù)包放置應(yīng)用層的交互指令,敬請(qǐng)期待下回分!
評(píng)論