日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于STM32的SPI基本介绍

發(fā)布時(shí)間:2025/3/21 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于STM32的SPI基本介绍 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

STM32---SPI(DMA)通信的總結(jié)(庫函數(shù)操作)

本文主要由7項(xiàng)內(nèi)容介紹SPI并會(huì)在最后附上測(cè)試源碼供參考:

1.?????SPI的通信協(xié)議

2.?????SPI通信初始化(以STM32為從機(jī),LPC1114為主機(jī)介紹)

3.?????SPI的讀寫函數(shù)

4.?????SPI的中斷配置

5.?????SPI的SMA操作

6.?????測(cè)試源碼

7.?????易出現(xiàn)的問題及原因和解決方法

一、?????SPI的通信協(xié)議

SPI(Serial Peripheral Interface)是一種串行同步通訊協(xié)議,由一個(gè)主設(shè)備和一個(gè)或多個(gè)從設(shè)備組成,主設(shè)備啟動(dòng)一個(gè)與從設(shè)備的同步通訊,從而完成數(shù)據(jù)的交換。SPI?接口一般由4根線組成,CS片選信號(hào)(有的單片機(jī)上也稱為NSS),SCLK時(shí)鐘信號(hào)線,MISO數(shù)據(jù)線(主機(jī)輸入從機(jī)輸出),MOSI數(shù)據(jù)線(主機(jī)輸出從機(jī)輸入),CS?決定了唯一的與主設(shè)備通信的從設(shè)備,如沒有CS?信號(hào),則只能存在一個(gè)從設(shè)備,主設(shè)備通過產(chǎn)生移位時(shí)鐘信號(hào)來發(fā)起通訊。通訊時(shí)主機(jī)的數(shù)據(jù)由MISO輸入,由MOSI?輸出,輸入的數(shù)據(jù)在時(shí)鐘的上升或下降沿被采樣,輸出數(shù)據(jù)在緊接著的下降或上升沿被發(fā)出(具體由SPI的時(shí)鐘相位和極性的設(shè)置而決定)。

?

?

?

二、?????以STM32為例介紹SPI通信

1.?????STM32f103?帶有3個(gè)SPI模塊其特性如下:


?

2???????SPI?初始化

初始化SPI?主要是對(duì)SPI要使用到的引腳以及SPI通信協(xié)議中時(shí)鐘相位和極性進(jìn)行設(shè)置,其實(shí)STM32的工程師已經(jīng)幫我們做好了這些工作,調(diào)用庫函數(shù),根據(jù)自己的需要來修改其中的參量來完成自己的配置即可,主要的配置是如下幾項(xiàng):

l??引腳的配置

?SPI1的SCLK, MISO ,MOSI分別是PA5,PA6,PA7引腳,這幾個(gè)引腳的模式都配置成GPIO_Mode_AF_PP?復(fù)用推挽輸出(關(guān)于GPIO的8種工作模式如不清楚請(qǐng)自己百度,在此不解釋),如果是單主單從,CS引腳可以不配置,都設(shè)置成軟件模式即可。


?

l??通信參數(shù)的設(shè)置


?

?

1.?????SPI_Direction_2Lines_FullDuplex把SPI設(shè)置成全雙工通信;

2.?????在SPI_Mode?里設(shè)置你的模式(主機(jī)或者從機(jī)),

3.?????SPI_DataSize是來設(shè)置數(shù)據(jù)傳輸?shù)膸袷降腟PI_DataSize_8b是指8位數(shù)據(jù)幀格式,也可以設(shè)置為SPI_DataSize_16b,即16位幀格式

4.?????SPI_CPOL和SPI_CPHA是兩個(gè)很重要的參數(shù),是設(shè)置SPI通信時(shí)鐘的極性和相位的,一共有四種模式


?

?

在庫函數(shù)中?CPOL有兩個(gè)值SPI_CPOL_High(=1)和SPI_CPOL_Low ( =0).

CPHA有兩個(gè)值SPI_CPHA_1Edge (=0)?和SPI_CPHA_2Edge(=1)

CPOL表示時(shí)鐘在空閑狀態(tài)的極性是高電平還是低電平,而CPHA則表示數(shù)據(jù)是在什么時(shí)刻被采樣的,手冊(cè)中如下:


?

?

我的程序中主、從機(jī)的這兩位設(shè)置的相同都是設(shè)置成1,即空閑時(shí)時(shí)鐘是高電平,數(shù)據(jù)在第二個(gè)時(shí)鐘沿被采樣,實(shí)驗(yàn)顯示數(shù)據(jù)收發(fā)都正常。

要特別注意極性和相位的設(shè)置否則,數(shù)據(jù)傳輸會(huì)出現(xiàn)錯(cuò)位的現(xiàn)象

一般主從機(jī)的這兩個(gè)位要設(shè)置的一樣,但是網(wǎng)上也有人說不能設(shè)置成一樣的,在后文中我對(duì)主從機(jī)極性和相位的配置的16種情況都做了測(cè)試,結(jié)果見下文。

下圖很好的描述了4種模式下的時(shí)序狀況


?

?

?

引用網(wǎng)友的一句話:

?

?SPI主模塊和與之通信的外設(shè)備時(shí)鐘相位和極性應(yīng)該一致。個(gè)人理解這句話有?2層意思:其一,主設(shè)備SPI時(shí)鐘和極性的配置應(yīng)該由外設(shè)的從設(shè)備來決定;其二,二者的配置應(yīng)該保持一致,即主設(shè)備的SDO同從設(shè)備的SDO配置一致,主設(shè)備的?SDI同從設(shè)備的SDI配置一致。因?yàn)橹鲝脑O(shè)備是在SCLK的控制下,同時(shí)發(fā)送和接收數(shù)據(jù),并通過2個(gè)雙向移位寄存器來交換數(shù)據(jù)。?

5.?????SPI_BaudRatePrescaler??波特率的設(shè)置

這在主機(jī)模式中,這一位的設(shè)置直接決定了通信的傳輸速率,而從機(jī)的設(shè)置不會(huì)影響數(shù)據(jù)傳輸?shù)乃俾?#xff0c;手冊(cè)中有這樣一句話:


?

?

(實(shí)際測(cè)試中發(fā)現(xiàn):當(dāng)STM32作為從機(jī)時(shí),它對(duì)波特率的設(shè)置會(huì)影響數(shù)據(jù)的通信,特別是在大數(shù)據(jù)兩傳輸時(shí),當(dāng)主機(jī)SPI時(shí)鐘設(shè)置為15M時(shí),STM32從機(jī)如果是2分頻即18M則會(huì)在多次傳輸時(shí)出現(xiàn)錯(cuò)誤,我記得在資料中看到過有前輩的經(jīng)驗(yàn)貼說SPI從機(jī)的時(shí)鐘設(shè)置不能高于SPI主機(jī)的時(shí)鐘設(shè)置,雖然理論上從機(jī)的時(shí)鐘設(shè)置不影響SPI通信,但是在試驗(yàn)中我也驗(yàn)證,當(dāng)STM32從機(jī)時(shí)鐘設(shè)為4分頻?9M,低于15M時(shí),通信就不會(huì)出現(xiàn)問題。所以SPI從機(jī)波特率的設(shè)置最好低于SPI主機(jī)波特率的設(shè)置。)

6.?????SPI_FirstBit?這一位是設(shè)置首先傳輸?shù)母咦止?jié)還是低字節(jié)

SPI_FirstBit_MSB?是先傳輸高字節(jié),SPI_FirstBit_LSB?是先傳輸?shù)妥止?jié)

注意在初始化函數(shù)里還有兩項(xiàng)重要的內(nèi)容就是在初始化之前先使能SPI的時(shí)鐘和在初始化配置完成后使能SPI。


?

?

(………..初始化配置……………)

?

?
?

三、?????SPI的讀寫函數(shù)

SPI有一個(gè)16位的數(shù)據(jù)寄存器SPI_DR,它對(duì)應(yīng)兩個(gè)緩沖區(qū),1個(gè)發(fā)送緩沖區(qū),1個(gè)接收緩沖區(qū),當(dāng)在控制寄存器里SPI_CR1里對(duì)DFF位設(shè)置數(shù)據(jù)幀格式為8位時(shí),發(fā)送和接收只用到SPI_DR[7:0]這8位,15-8位被強(qiáng)制為0,幀格式設(shè)置成16位時(shí)全用。

?

讀寫過程在手冊(cè)中是這樣描述的:


?

?

簡(jiǎn)而言之,

發(fā)送時(shí),可以通過檢測(cè)SPI_SR中的TXE位,當(dāng)數(shù)據(jù)寄存器里有數(shù)據(jù)時(shí),TXE位是0,當(dāng)數(shù)據(jù)全部從數(shù)據(jù)寄存器的發(fā)送緩沖區(qū)傳輸?shù)揭莆患拇嫫鲿r(shí)TXE位被置1,這時(shí)候可以再往數(shù)據(jù)寄存器里寫入數(shù)據(jù)??梢酝ㄟ^

while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)?來檢測(cè)。

?SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)??是庫函數(shù),可以檢測(cè)SPI的一些狀態(tài)位。

接收時(shí),可以通過檢測(cè)SPI_SR中的RXNE位,當(dāng)數(shù)據(jù)寄存器里有數(shù)據(jù)時(shí),RXNE位是0,當(dāng)數(shù)據(jù)全部從數(shù)據(jù)寄存器的接收緩沖區(qū)傳輸?shù)揭莆患拇嫫鲿r(shí)RXNE位被置1,這時(shí)候可以從數(shù)據(jù)寄存器里讀出數(shù)據(jù)??梢酝ㄟ^

while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);???來檢測(cè)。源程序如下,

SPI?讀寫一個(gè)字節(jié),讀寫一體


?

?

?

當(dāng)能成功發(fā)送和接收一個(gè)字節(jié)時(shí),發(fā)送數(shù)組數(shù)據(jù)就變的簡(jiǎn)單了,只需要一個(gè)for循環(huán),和指針變量的遞增即可。以下僅為參考:

有一點(diǎn)特別注意,從機(jī)數(shù)據(jù)傳輸時(shí)要依賴主機(jī)的時(shí)鐘,所以主機(jī)在接收從機(jī)發(fā)送的數(shù)據(jù)時(shí)要往從機(jī)發(fā)送啞巴字節(jié),這個(gè)字節(jié)可以自己定義?0xff,0xfe等什么字節(jié)都可以

?

讀寫分開的函數(shù)

?

void SPI_Ecah_Buffer_Send(u8* pBuffer, u16 NumByteToRead)

{

???????for(int i = 0; i < NumByteToRead; i++)

???????{

??????????????SPI_Conmunication_SendByte(*pBuffer);

??????????????pBuffer++;

???????}

}

?

void SPI_Buffer_Receive(u8* pBuffer, u16 NumByteToRead)

{

???????while (NumByteToRead--)

???????{?????

??????????????*pBuffer = SPI_Conmunication_SendByte (Dummy_Byte);

??????????????pBuffer++;

???????}

}

讀寫一體的函數(shù)

?

void SPI_Ecah_Buffer_Send(u8* str , u8* pBuffer, u16 NumByteToRead)

{

???????for(int i = 0; i < NumByteToRead; i++)

???????{

??????????????*str = SPI_Conmunication_SendByte(*pBuffer);

??????????????pBuffer++;

??????????????str++;

???????}

}

?

?

?

四、?????SPI的中斷配置

在SPI的SPI_CR2?中可以配置,STM32的SPI的通信一共有8個(gè)中斷其中最常用的是如下4個(gè)。

TXEIE:發(fā)送緩沖區(qū)空中斷使能

在發(fā)送過程中,數(shù)據(jù)全部從數(shù)據(jù)寄存器的發(fā)送緩沖區(qū)傳輸?shù)揭莆患拇嫫鲿r(shí)TXE位被置1這時(shí)如果使能了TXEIE?就會(huì)觸發(fā)發(fā)送完成的中斷請(qǐng)求。在中斷服務(wù)函數(shù)里可以做你想做的事情,也可以用一個(gè)標(biāo)志位,在外面完成相應(yīng)的操作。

(使用中斷時(shí)要特別注意,及時(shí)的清除中斷標(biāo)志,為下一次能夠觸發(fā)中斷做準(zhǔn)備。而清除中斷的操作可以放在中斷服務(wù)函數(shù)中,或者其他你認(rèn)為何時(shí)的地方。)

RXNEIE:接收緩沖區(qū)非空中斷使能

接收同發(fā)送。

TXDMAEN:發(fā)送緩沖區(qū)DMA使能

RXDMAEN:接收緩沖區(qū)DMA使能

?

手冊(cè)中有這樣一句話,“不能同時(shí)設(shè)置TXEIETXDMAEN”這一點(diǎn)要特別注意。也就是說如果你在SPI的通信中不用DMA則使能TXEIE的中斷,禁能TXDMAEN的中斷,如果在SPI中使用DMA傳輸,則禁能TXEIE?的中斷,只使能TXDMAEN?的中斷。

?

五、?????SPIDMA操作

DMA(Direct Memory Access)直接內(nèi)存存取,直接存儲(chǔ)器存取用來提供在外設(shè)和存儲(chǔ)器之間或者存儲(chǔ)器和存儲(chǔ)器之間的高速數(shù)據(jù)傳輸。無須CPU任何干預(yù),通過DMA數(shù)據(jù)可以快速地移動(dòng)。使用DMA最大的特點(diǎn)就是數(shù)據(jù)傳輸不經(jīng)過CPU這就節(jié)省了CPU的資源,讓CPU能有更多的時(shí)間來做其他的事情。

SPI的DMA操作,就是在SPI->TXE為1時(shí),會(huì)向?qū)?yīng)的DMA通道發(fā)出請(qǐng)求,DMA通道會(huì)發(fā)出應(yīng)答信號(hào),SPI收到應(yīng)答信號(hào)后撤銷請(qǐng)求信號(hào),DMA撤銷應(yīng)答信號(hào),并把內(nèi)存值裝入SPI_DR的發(fā)送緩區(qū),SPI的傳送開始。

DMA

的初始化

?

?

DMA_PeripheralBaseAddr是值外設(shè)數(shù)據(jù)的地址,用SPI1故DMA外設(shè)地址對(duì)應(yīng)的是SPI1_DR_Addr,

DMA_MemoryBaseAddr是內(nèi)存地址,它的值可以使,你要發(fā)送的數(shù)據(jù)所存放的數(shù)組的名,因?yàn)閿?shù)組名代表的是數(shù)組數(shù)據(jù)存放的首地址,在SPI-DMA的發(fā)送中可以理解為把DMATX[]數(shù)組里的數(shù)據(jù)傳送到SPI1_DR_Addr

DMA_DIR?是指數(shù)據(jù)傳輸?shù)姆较?#xff0c;其值發(fā)送時(shí)其值為DMA_DIR_PeripheralDST?即外設(shè)是目的地,方向是DMATX—> SPI1_DR_Addr,

在接受收時(shí)其值為DMA_DIR_PeripheralSRC,即外設(shè)是數(shù)據(jù)的來源,傳輸方向是?SPI1_DR_Addr—>用戶指定的數(shù)據(jù)存儲(chǔ)數(shù)組。

DMA_BufferSize?用來設(shè)置傳輸數(shù)據(jù)的個(gè)數(shù),在STM32的DMA中其值的范圍是0—65536.

DMA_Mode?指?DMA的傳輸模式?DMA_Mode_Normal為正常工作模式

DMA_Mode_Circular?是循環(huán)工作模式,這里對(duì)循環(huán)模式的解釋我認(rèn)為有位網(wǎng)友解釋的很不錯(cuò)如下:

“循環(huán)的意思是指DMA的傳輸數(shù)量計(jì)數(shù)器會(huì)重置初值,由于DMA每傳一個(gè)數(shù)據(jù),傳輸數(shù)量計(jì)數(shù)器減一,只有在傳輸數(shù)量計(jì)數(shù)器的值不為零時(shí),才會(huì)響應(yīng)請(qǐng)求。在循環(huán)模式下,當(dāng)傳輸計(jì)數(shù)器的值減為0后,會(huì)重新裝載;而內(nèi)存(緩存)地址則不管循環(huán)非循環(huán)模式,都會(huì)在每次傳輸完成后重置為基地址。所以,如果我們把DMA設(shè)置會(huì)正常模式,那么在下次傳輸前,只需對(duì)DMA的傳輸數(shù)量計(jì)數(shù)器重新寫入就行。循環(huán)模式一般用于數(shù)據(jù)更新,比如ADC采用需要不停更新數(shù)據(jù)?!?/span>

在初始化完成之后要開啟DMA的中斷,在我的程序中開啟的是DMA傳輸完成中斷。


?

?

DMA傳輸有3個(gè)中斷標(biāo)志位,常用的是傳輸完成的中斷。如下:


?

?

這樣在傳輸完設(shè)定的數(shù)據(jù)個(gè)數(shù)之后就會(huì)觸發(fā)傳輸完成的中斷,用戶可以再中斷服務(wù)函數(shù)中,進(jìn)行相應(yīng)的操作,有一點(diǎn)特別注意,就是要及時(shí)清除中斷標(biāo)志位,為下次能夠正常觸發(fā)中斷做準(zhǔn)備。


?

?

在我的中斷服務(wù)函數(shù)中有一個(gè)標(biāo)志位SpiCommon,被置1后再中斷之外進(jìn)行其他的處理,同時(shí)調(diào)用DMA_ClearITPendingBit(DMA1_IT_TC2)來及時(shí)清除中斷標(biāo)志。

在進(jìn)行DMA的數(shù)據(jù)傳輸時(shí)要先禁能DMA的通道,重置傳輸數(shù)據(jù)個(gè)數(shù)的值,數(shù)據(jù)的存儲(chǔ)位置等,再使能DMA的通道,等待DMA的傳輸完成。

我的操作時(shí)這樣的,先往DMATX[]里寫入相應(yīng)的數(shù)據(jù),然后如下

?

這樣可能有一點(diǎn)不好的地方,因?yàn)橹桓淖兞薙piTXSize的值,卻又重新執(zhí)行了DMATXInit()?函數(shù),可能此處能夠再改善一下。

總結(jié)

以上是生活随笔為你收集整理的基于STM32的SPI基本介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。