嵌入式軟件就是某一項(xiàng)目的源碼文件集合,源碼文件的數(shù)量,根據(jù)項(xiàng)目復(fù)雜程度的不同而有規(guī)模和層次的差別。
就拿簡單的一個(gè)芯片廠商提供的demo來說,代碼也會(huì)被細(xì)分到寄存器操作(Drv層)、板級(jí)支持包接口(Bsp層)、功能模塊驗(yàn)證(App層)等各層,但是這里的“分層”很多時(shí)候都不太明顯,因?yàn)樗鼉H僅是個(gè)demo,所謂的“分層”更多的還是人為給它做的定義。
真正意義的分層,是從代碼的編碼規(guī)范、程序的執(zhí)行邏輯來體現(xiàn)的。
關(guān)于分層設(shè)計(jì)的意義在這暫不做太多的探討,只是做個(gè)引子,來講講SPI接口的設(shè)計(jì)過程,如何設(shè)計(jì)一套擁有自己規(guī)范和方便移植的SPI接口。
SPI在分層架構(gòu)中的設(shè)計(jì)思路
剛剛提到分層設(shè)計(jì)的思路,那么SPI作為一個(gè)通信接口,如果按照分層設(shè)計(jì)的思路,如何把接口設(shè)計(jì)得更合理,更方便?
此處需要設(shè)計(jì)的SPI是介于“應(yīng)用”和“驅(qū)動(dòng)”之間的,“應(yīng)用”就是項(xiàng)目業(yè)務(wù)需求的功能模塊將數(shù)據(jù)、數(shù)據(jù)包等傳給SPI接口,而“驅(qū)動(dòng)”是SPI接口拿到數(shù)據(jù)包后,把數(shù)據(jù)轉(zhuǎn)變?yōu)镾PI的時(shí)序發(fā)送出去。
當(dāng)我們拿到一款芯片,大多數(shù)情況下官方提供的demo程序已經(jīng)給我們實(shí)現(xiàn)好了很多的驅(qū)動(dòng)(或者自己從網(wǎng)絡(luò)資源中Download),各個(gè)接口的驅(qū)動(dòng),已經(jīng)被封裝成函數(shù)或者庫供我們直接調(diào)用。
想象一下我們的項(xiàng)目工程,如果需要操作芯片硬件接口的時(shí)候,直接調(diào)用官方提供的接口函數(shù),雖然能實(shí)現(xiàn)功能,但是在需要更換芯片平臺(tái)的時(shí)候,就需要在繁雜的、與業(yè)務(wù)需求相關(guān)的應(yīng)用層里找和去修改為目標(biāo)驅(qū)動(dòng)接口。
這里就牽扯到了分層設(shè)計(jì)的優(yōu)勢所在:由于平臺(tái)的更換,驅(qū)動(dòng)接口已經(jīng)變了樣,那么對代碼的移植就會(huì)變得非常費(fèi)力,不僅是腦力活,更是體力活(即使可以批量替換,你也需要仔細(xì)核對接口,更要解決接口的差異性)。
而此時(shí)如果是分層設(shè)計(jì)的,在應(yīng)用和驅(qū)動(dòng)中間有個(gè)BSP層,應(yīng)用層調(diào)用的只是BSP層,完全不涉及驅(qū)動(dòng)、寄存器,不涉及與芯片平臺(tái)相關(guān)的接口,那么即使平臺(tái)怎么更換、驅(qū)動(dòng)怎么改變,你只需要改變BSP層的具體實(shí)現(xiàn),相對就輕松很多了。
從上一篇《嵌入式硬件通信接口協(xié)議-SPI(一)協(xié)議基礎(chǔ)》對SPI協(xié)議的介紹,設(shè)計(jì)BSP層的時(shí)候,根據(jù)SPI可配置項(xiàng)來設(shè)計(jì)接口功能。設(shè)計(jì)BSP層的SPI功能函數(shù)時(shí)考慮接口模式、數(shù)據(jù)寬度、時(shí)鐘極性與相位、時(shí)鐘速率、數(shù)據(jù)bit位大小端選擇、管腳定義。
設(shè)計(jì)BSP層時(shí),首先想到的是接口初始化和數(shù)據(jù)收發(fā)。設(shè)計(jì)初始化,把SPI可配置項(xiàng)放在函數(shù)接口,作參數(shù)傳遞;設(shè)計(jì)數(shù)據(jù)收發(fā),傳數(shù)據(jù)的同時(shí)也把SPI端口號(hào)作為參數(shù)之一,因?yàn)槲覀兌贾?a target="_blank">MCU可能會(huì)有多個(gè)SPI接口,將SPI端口號(hào)作為參數(shù)也是比較必要。
SPI接口本身就是可以實(shí)現(xiàn)1對N的串行總線,為什么在使用過程中有時(shí)要分別使用不同的SPI端口來接不同的外圍器件呢?
主要原因是SPI的可配置項(xiàng)的不一致,有些外圍器件對SPI時(shí)鐘信號(hào)SCLK的極性要求為高、低不一樣,時(shí)鐘相位不一樣,并且通信數(shù)據(jù)bit位大小端選擇的不一樣,這些接口配置項(xiàng)的差異,導(dǎo)致了有些場景下操作不同器件時(shí)需要使用不同的SPI端口。
SPI時(shí)序使用IO引腳模擬
從零開始設(shè)計(jì)自有的一套SPI板級(jí)支持包(BSP)接口,那就從初始化開始。這里設(shè)計(jì)的是模擬SPI,所以會(huì)調(diào)用GPIO設(shè)置的接口。
當(dāng)前使用的芯片平臺(tái)是STM32F103系列,雖然此時(shí)已經(jīng)完全可以調(diào)用官方的StdPeriphDrivers V3.5.0版本的標(biāo)準(zhǔn)外設(shè)庫。調(diào)用接口庫不是目的,成為“調(diào)庫俠”其實(shí)很簡單。此處重新寫的模擬實(shí)現(xiàn)方式,旨在說明在BSP層,實(shí)現(xiàn)自有系統(tǒng)的軟件架構(gòu),為系統(tǒng)集成提供底層接口。同時(shí)也是在深入學(xué)習(xí)和了解SPI接口的時(shí)序特性。
初始化函數(shù)接口里暫時(shí)做了SPI端口號(hào)、數(shù)據(jù)寬度、接口時(shí)鐘模式、數(shù)據(jù)位優(yōu)先模式這四個(gè)參數(shù),基本上這四個(gè)參數(shù)已經(jīng)可以完成對大部分應(yīng)用需求。在編碼初期先不急于填入過多的配置項(xiàng),首先按照最簡單的默認(rèn)方式編碼,保證程序邏輯可以跑通。
其中用到的管腳定義,是在完成原理圖或者完成原型機(jī)驗(yàn)證時(shí),基本就確定了管腳的使用,因此管腳的定義一般的都是放在BSP層的頭文件中。這樣更便于移植和開發(fā)。
數(shù)據(jù)發(fā)送時(shí),先寫發(fā)送一個(gè)字節(jié)的數(shù)據(jù),數(shù)據(jù)是“踩”著SPI接口時(shí)鐘信號(hào)SCLK的“節(jié)拍”逐個(gè)bit位發(fā)送出去,因此在發(fā)送數(shù)據(jù)的時(shí)候也是需要主機(jī)操作時(shí)鐘信號(hào)SCLK和數(shù)據(jù)信號(hào)MOSI:
SPI的數(shù)據(jù)發(fā)送接口dcbsp_spi_sendbyte函數(shù)實(shí)現(xiàn)了將1個(gè)字節(jié)的數(shù)據(jù)通過GPIO輸出,實(shí)現(xiàn)了SPI接口的時(shí)序,其中關(guān)鍵的是SCLK信號(hào)輸出、1字節(jié)數(shù)據(jù)的移位輸出、SCLK信號(hào)做延時(shí)輸出脈沖。
而發(fā)送多數(shù)據(jù)的接口就可以采用dcbsp_spi_sendbyte函數(shù)來逐字節(jié)發(fā)送完成。
另外接收數(shù)據(jù)的接口,同樣參考著字節(jié)發(fā)送接口的思路,數(shù)據(jù)的接收過程也是“踩”著SPI接口時(shí)鐘信號(hào)SCLK的“節(jié)拍”逐個(gè)bit位傳輸,這個(gè)過程主機(jī)繼續(xù)提供SCLK,然后讀取MISO信號(hào)的電平,再將讀到的電平逐bit緩存在一個(gè)變量里:
就這樣,利用GPIO進(jìn)行電平的輸出的讀取,實(shí)現(xiàn)了SPI接口的部分時(shí)序。這些接口的內(nèi)部實(shí)現(xiàn)過程,因人而異、因平臺(tái)變化而微調(diào),但是對外接口不動(dòng),對上層應(yīng)用來說,這就是同一個(gè)接口同一個(gè)東西,上層的應(yīng)用層程序改動(dòng)就很小了。
對于每次移植,BSP層提供了一定架構(gòu)接口,層次清晰改動(dòng)小,所以對于一個(gè)嵌入式開發(fā)者而言,寫好BSP層也很重要。
總結(jié),本文主要想分享的是設(shè)計(jì)嵌入式軟件時(shí),分出BSP層,作為應(yīng)用和驅(qū)動(dòng)的中間層,以便于在項(xiàng)目移植過程中,應(yīng)用的完美匹配。文中的代碼未完,關(guān)于驅(qū)動(dòng)類的代碼,其執(zhí)行結(jié)果必須在示波器等儀器下觀測,仍需確認(rèn)執(zhí)行的效率和時(shí)序的實(shí)現(xiàn)效果!
-
嵌入式
+關(guān)注
關(guān)注
5093文章
19178瀏覽量
307717
發(fā)布評論請先 登錄
相關(guān)推薦
嵌入式常見的通信接口/協(xié)議有哪些?
嵌入式分層架構(gòu)的相關(guān)資料分享
為何要進(jìn)行嵌入式軟件架構(gòu)設(shè)計(jì)?如何設(shè)計(jì)?
對嵌入式系統(tǒng)中的架構(gòu)設(shè)計(jì)的理解
嵌入式系統(tǒng)串口通信分層結(jié)構(gòu)設(shè)計(jì)與實(shí)現(xiàn)
嵌入式常用接口協(xié)議
![<b class='flag-5'>嵌入式</b>常用<b class='flag-5'>接口</b><b class='flag-5'>協(xié)議</b>](https://file.elecfans.com/web1/M00/45/D8/o4YBAFp5e9OAY1mbAAFtoOz4TDQ504.png)
嵌入式硬件通信接口協(xié)議中的串行通信接口-SPI
![<b class='flag-5'>嵌入式</b><b class='flag-5'>硬件</b><b class='flag-5'>通信</b><b class='flag-5'>接口</b><b class='flag-5'>協(xié)議</b>中的串行<b class='flag-5'>通信</b><b class='flag-5'>接口</b>-<b class='flag-5'>SPI</b>](https://file.elecfans.com/web1/M00/82/9E/o4YBAFxBSq2ASIYiAAB0-bMNXBE021.jpg)
嵌入式常見的通信接口/協(xié)議
![<b class='flag-5'>嵌入式</b>常見的<b class='flag-5'>通信</b><b class='flag-5'>接口</b>/<b class='flag-5'>協(xié)議</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
嵌入式分層概括總結(jié)
![<b class='flag-5'>嵌入式</b><b class='flag-5'>分層</b>概括總結(jié)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
嵌入式硬件通信接口協(xié)議-SPI(一)協(xié)議基礎(chǔ)
![<b class='flag-5'>嵌入式</b><b class='flag-5'>硬件</b><b class='flag-5'>通信</b><b class='flag-5'>接口</b><b class='flag-5'>協(xié)議</b>-<b class='flag-5'>SPI</b>(一)<b class='flag-5'>協(xié)議</b>基礎(chǔ)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論