0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

STM32F1的SPI模塊協(xié)議介紹

冬至子 ? 來(lái)源:ITRelief ? 作者:Sachefgh Xu ? 2023-07-24 15:32 ? 次閱讀

SPI是是一種高速的,全雙工,同步的總線通信方式。STM32F1低中容量設(shè)備的SPI模塊支持主從兩種模式。

一、SPI協(xié)議介紹

1.硬件連接

SPI使用三條數(shù)據(jù)總線和一條片選線: MOSI、MISO、SCK、NSS(CS)

MOSI(SDO):主設(shè)備輸出/從設(shè)備輸入。用于將數(shù)據(jù)從主機(jī)輸出到從機(jī)。

MISO(SDI):主設(shè)備輸入/從設(shè)備輸出。數(shù)據(jù)經(jīng)此由從機(jī)至主機(jī),主機(jī)接收數(shù)據(jù)。

SCK:時(shí)鐘信號(hào)線,用于通訊同步。時(shí)鐘信號(hào)由主機(jī)提供

NSS:片選信號(hào)線。由主機(jī)通過(guò)此線使能從機(jī)。在一主多從的通訊模式下,只能同時(shí)有一個(gè)從機(jī)被使能。

SPI器件間的連接很簡(jiǎn)單,如圖,只要名字相同線相連即可,主也可以比較方便地反轉(zhuǎn)。

圖片

2.通信時(shí)序

SPI傳輸模式的精髓在時(shí)鐘極性(CPOL)和時(shí)鐘相位(CPHA)

CPOL控制空閑狀態(tài)下時(shí)鐘總線SCK的電平:

CPOL=0(LOW);時(shí)鐘線空閑為低電平

CPOL=1(HIGH);時(shí)鐘線空閑為高

CPHA控制采樣位置和信號(hào)跳變位置:

圖片

※SPI傳輸從高位(MSB)開(kāi)始還是低位(LSB)開(kāi)始可以由用戶設(shè)置

二、STM32F1的SPI模塊

1.在CubeMX中進(jìn)行配置

數(shù)據(jù)位可選擇8或16

CPHA可選擇從第一個(gè)數(shù)據(jù)沿開(kāi)始(CPHA=0)或從第二個(gè)數(shù)據(jù)沿開(kāi)始(CPHA=1)

可選擇高位先發(fā)送或是低位先發(fā)送

可選擇是否使用NSS以及NSS功能(輸入、輸出用)。用戶也可以用普通IO的中斷輸入/輸出功能模擬NSS,這種方法相對(duì)更加靈活。

按照個(gè)人開(kāi)發(fā)經(jīng)驗(yàn),SPI一般配置為雙線雙向全雙工情況比較多。

※STM32的 NSS引腳說(shuō)明和工作極其復(fù)雜,建議開(kāi)發(fā)者禁用硬件NSS,自行定義普通GPIO實(shí)現(xiàn)片選功能。(NSS腳禁用后可以進(jìn)行GPIO配置當(dāng)作普通IO控制實(shí)現(xiàn)CS功能)

2.相關(guān)寄存器

圖片

圖片

圖片

圖片

圖片

圖片

圖片

圖片

圖片

圖片

圖片

圖片

API:

1.初始化結(jié)構(gòu)體LL_SPI_InitTypeDef

typedef struct
{
  uint32_t TransferDirection;/*
  數(shù)據(jù)線配置;通過(guò)調(diào)用LL_SPI_SetTransferDirection()實(shí)現(xiàn);
  @ref:       LL_SPI_FULL_DUPLEX //全雙工,雙線雙向
              LL_SPI_SIMPLEX_RX  //雙線雙向模式下禁止輸出,僅能輸入
              LL_SPI_HALF_DUPLEX_RX //單線,僅能接收
              LL_SPI_HALF_DUPLEX_TX //單線,僅能發(fā)送
              ※單線模式下,工作于Master時(shí)使用MOSI腳;Slave時(shí)為MISO腳
  */
  uint32_t Mode;/*
  設(shè)置主從模式,通過(guò)LL_SPI_SetMode()實(shí)現(xiàn);
  @ref:       LL_SPI_MODE_MASTER //主模式,配置時(shí)若NSS由軟件管理會(huì)將電平置高
              LL_SPI_MODE_SLAVE
  */
  uint32_t DataWidth;/*
  設(shè)置數(shù)據(jù)長(zhǎng)度;通過(guò)LL_SPI_SetDataWidth()實(shí)現(xiàn);
  @ref:       LL_SPI_DATAWIDTH_8BIT  //8位
              LL_SPI_DATAWIDTH_16BIT  //16位
  */
  uint32_t ClockPolarity;/*
  設(shè)置時(shí)鐘極性(CPOL),通過(guò)LL_SPI_SetClockPolarity()實(shí)現(xiàn)
  @ref:       LL_SPI_POLARITY_LOW //低電平(CPOL=0)
              LL_SPI_POLARITY_HIGH  //高電平(CPOL=1)
  */
  uint32_t ClockPhase;/*
  設(shè)置時(shí)鐘相位,通過(guò)LL_SPI_SetClockPhase()實(shí)現(xiàn)
  @ref:       LL_SPI_PHASE_1EDGE //CPHA =0
              LL_SPI_PHASE_2EDGE //CPHA=1
  */
  uint32_t NSS;/*
  配置NSS(CS),通過(guò)LL_SPI_SetNSSMode()實(shí)現(xiàn);
  @ref:       LL_SPI_NSS_SOFT //通過(guò)軟件管理NSS;※此時(shí)NSS引腳無(wú)法進(jìn)行I/O操作控制
                 //CubeMx配置為Disable時(shí)配置為此模式(相當(dāng)于禁用了NSS)
                 //此時(shí)可以通過(guò)操作SPI_CR1- >SSI位控制該位電平;LL庫(kù)未提供函數(shù);
              LL_SPI_NSS_HARD_INPUT //說(shuō)不清除,手冊(cè)和庫(kù)函數(shù)說(shuō)明沖突,建議不用
              LL_SPI_NSS_HARD_OUTPUT//同樣,不建議配置
              //鑒于片選復(fù)雜性,推薦開(kāi)發(fā)者直接通過(guò)GPIO直接模擬NSS(CS)功能,可用原NSS
  */
  uint32_t BaudRate;/*
  配置波特率分頻,通過(guò)LL_SPI_SetBaudRatePrescaler()實(shí)現(xiàn);
  @ref:        LL_SPI_BAUDRATEPRESCALER_DIVx //x2^n,max=128
*/
  uint32_t BitOrder;/*
  配置發(fā)送位順序,通過(guò)LL_SPI_SetTransferBitOrder()實(shí)現(xiàn);
  @ref:      LL_SPI_LSB_FIRST  //低位先
             LL_SPI_MSB_FIRST  //高位先
  */
  uint32_t CRCCalculation;/*!< Specifies if the CRC calculation is enabled or not.
  This parameter can be a value of @ref SPI_LL_EC_CRC_CALCULATION.
This feature can be modified afterwards using unitary functions @ref LL_SPI_EnableCRC() and @ref LL_SPI_DisableCRC().*/

  uint32_t CRCPoly;/*!< Specifies the polynomial used for the CRC calculation.
This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF.
 This feature can be modified afterwards using unitary function @ref LL_SPI_SetCRCPolynomial().*/
} LL_SPI_InitTypeDef;

2.初始化函數(shù)

ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct);/*
初始化SPI;
*/
void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct)/*
初始化SPI配置結(jié)構(gòu)體
*/
ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx)/*
初始化SPI模塊
*/

3.開(kāi)啟/關(guān)閉模塊

__STATIC_INLINE void LL_SPI_Enable(SPI_TypeDef *SPIx);/*
開(kāi)啟SPI模塊
*/
__STATIC_INLINE void LL_SPI_Disable(SPI_TypeDef *SPIx);/*
關(guān)閉SPI模塊
*/
__STATIC_INLINE uint32_t LL_SPI_IsEnabled(SPI_TypeDef *SPIx);/*
檢測(cè)開(kāi)啟狀態(tài)
*/

※與UART不同,目前版本CubeMX自動(dòng)生成代碼不會(huì)開(kāi)啟SPI,需用戶手動(dòng)開(kāi)啟

關(guān)閉SPI需要在傳輸完成后

4.標(biāo)志位/狀態(tài)位

圖片

MODF:主模式失效錯(cuò)誤標(biāo)志。在NSS引腳硬件模式管理下,主設(shè)備的NSS腳被拉低時(shí);或者在NSS引腳軟件模式管理下,SSI位被置0時(shí)被置位。同時(shí)SPI模塊被關(guān)閉。 在使用LL庫(kù)時(shí)若不使用NSS功能,則不會(huì)出現(xiàn)置位情況

※RXNE:接收緩沖非空。與USART類似,當(dāng)※接收數(shù)據(jù)寄存器完全完成一次數(shù)據(jù)接收時(shí),該位被置位?!鶎?duì)讀取數(shù)據(jù)寄存器RDR的讀取操作可以硬件清零該位。

※TXE:發(fā)送緩沖空。當(dāng)發(fā)送數(shù)據(jù)寄存器數(shù)據(jù)被送出時(shí),該位被置位。對(duì)發(fā)送數(shù)據(jù)寄存器TDR的寫(xiě)入操作可以硬件清零該位。

BSY:忙標(biāo)志。SPI在通訊時(shí)該位為1。該位完全由硬件控制。在主模式的雙向接收模式下 (MSTR=1、BDM=1并且BDOE=0),在接收期間BSY標(biāo)志保持為低。不要使用BSY標(biāo)志處理每一個(gè)數(shù)據(jù)項(xiàng)的發(fā)送和接收,最好使用TXE和RXNE標(biāo)志。

OVR:溢出錯(cuò)誤。接收數(shù)據(jù)時(shí),當(dāng)發(fā)送端設(shè)備已經(jīng)發(fā)送了數(shù)據(jù)字節(jié),而STM32還沒(méi)有清除前一個(gè)數(shù)據(jù)字節(jié)產(chǎn)生的RXNE時(shí),即為溢出錯(cuò)誤。

當(dāng)溢出時(shí),讀SPI_DR寄存器返回的是之前未讀的數(shù)據(jù),所有隨后傳送的數(shù)據(jù)都被丟棄。

※與USART不同,SPI模塊TXE與RXNE位是只讀的,其值由硬件管理。

__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_BSY(SPI_TypeDef *SPIx);/*
檢測(cè)BSY是否置位,該位無(wú)法軟件控制
*/
__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_OVR(SPI_TypeDef *SPIx);/*
檢測(cè)OVR是否置位(發(fā)生過(guò)載錯(cuò)誤)
*/
__STATIC_INLINE void LL_SPI_ClearFlag_OVR(SPI_TypeDef *SPIx);/*
置位OVR
*/
__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_TXE(SPI_TypeDef *SPIx);/*
檢測(cè)TXE是否置位
*/
__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_RXNE(SPI_TypeDef *SPIx);/*
檢測(cè)RXNE是否置位
*/
__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_MODF(SPI_TypeDef *SPIx);
__STATIC_INLINE void LL_SPI_ClearFlag_MODF(SPI_TypeDef *SPIx);

5.中斷控制

__STATIC_INLINE void LL_SPI_EnableIT_ERR(SPI_TypeDef *SPIx);/*
使能ERR錯(cuò)誤中斷*/
__STATIC_INLINE void LL_SPI_DisableIT_ERR(SPI_TypeDef *SPIx);/*
禁用ERR錯(cuò)誤中斷*/
__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_ERR(SPI_TypeDef *SPIx);/*
檢測(cè)是否開(kāi)啟ERR中斷*/

__STATIC_INLINE void LL_SPI_EnableIT_RXNE(SPI_TypeDef *SPIx);/*
使能RXNE接收緩沖非空中斷*/
__STATIC_INLINE void LL_SPI_DisableIT_RXNE(SPI_TypeDef *SPIx);/*
禁用RXNE接收緩沖非空中斷*/
__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_RXNE(SPI_TypeDef *SPIx)/*
檢測(cè)是否開(kāi)啟RXNE接收緩沖非空中斷*/

__STATIC_INLINE void LL_SPI_EnableIT_TXE(SPI_TypeDef *SPIx);/*
使能TXE發(fā)送緩沖空中斷*/
__STATIC_INLINE void LL_SPI_DisableIT_TXE(SPI_TypeDef *SPIx);/*
禁用TXE發(fā)送緩沖空中斷*/
__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_TXE(SPI_TypeDef *SPIx)/*
檢測(cè)是否開(kāi)啟TXE發(fā)送緩沖空中斷*/

6.SPI 收/發(fā)函數(shù)

__STATIC_INLINE uint8_t LL_SPI_ReceiveData8(SPI_TypeDef *SPIx);/*
從接收寄存器(緩沖區(qū))DR中讀取8位數(shù)據(jù);
*/
__STATIC_INLINE uint16_t LL_SPI_ReceiveData16(SPI_TypeDef *SPIx);/*
從接收寄存器(緩沖區(qū))DR中讀取16位數(shù)據(jù);
*/

__STATIC_INLINE void LL_SPI_TransmitData8(SPI_TypeDef *SPIx, uint8_t TxData);/*
向發(fā)送寄存器(緩沖區(qū))DR中寫(xiě)入8位數(shù)據(jù)
*/
__STATIC_INLINE void LL_SPI_TransmitData16(SPI_TypeDef *SPIx, uint16_t TxData);/*
向發(fā)送寄存器(緩沖區(qū))DR中寫(xiě)入16位數(shù)據(jù)
*/

SPI模塊DMA的使用

相關(guān)函數(shù):

待實(shí)驗(yàn)

__STATIC_INLINE void LL_USART_EnableDMAReq_RX(USART_TypeDef *SPIx);/*
使能接收DMA,啟用后DR有數(shù)據(jù)時(shí)將允許發(fā)送DMA請(qǐng)求;具體見(jiàn)示例用法*/
__STATIC_INLINE void LL_USART_DisableDMAReq_RX(USART_TypeDef *SPIx);/*
禁用接收DMA*/
__STATIC_INLINE uint32_t LL_USART_IsEnabledDMAReq_RX(USART_TypeDef *SPIx);/*
檢測(cè)是否使能接收DMA*/

__STATIC_INLINE void LL_USART_EnableDMAReq_TX(USART_TypeDef *SPIx);/*
使能發(fā)送DMA*/
__STATIC_INLINE void LL_USART_DisableDMAReq_TX(USART_TypeDef *SPIx);/*
禁用發(fā)送DMA*/
__STATIC_INLINE uint32_t LL_USART_IsEnabledDMAReq_TX(USART_TypeDef *SPIx);/*
檢測(cè)是否使能發(fā)送DMA*/
/**************************************************/
__STATIC_INLINE uint32_t LL_USART_DMA_GetRegAddr(USART_TypeDef *SPIx);/*
返回SPI模塊數(shù)據(jù)寄存器DR地址;無(wú)論是否啟用DMA均可用
*/

發(fā)送時(shí),在每次TXE被設(shè)置為’1’時(shí)發(fā)出DMA請(qǐng)求,此時(shí)軟件控制DMA寫(xiě)數(shù)據(jù)至SPI_DR寄存器,TXE標(biāo)志因此而被清除。

接收時(shí),在每次RXNE被設(shè)置為’1’時(shí)發(fā)出DMA請(qǐng)求,在開(kāi)啟情況下DMA控制器從SPI_DR寄存器讀出數(shù)據(jù),RXNE標(biāo)志因此而被清除。

LL的DMA使用與UART相似,可以參考之前的文章。

SPI在雙向全雙工傳輸數(shù)據(jù)的時(shí)候,每發(fā)出一字節(jié)數(shù)據(jù)的同時(shí)也會(huì)接收一字節(jié)數(shù)據(jù),因此在作為主機(jī)接收的時(shí)候,應(yīng)當(dāng)考慮 如何處理接收到的無(wú)用數(shù)據(jù)。否則會(huì)出現(xiàn)OVR。

另外,由于在雙向模式下配置為主機(jī)時(shí),只有當(dāng)SPI在寫(xiě)數(shù)據(jù)時(shí)時(shí)鐘信號(hào)才能產(chǎn)生。處于master工作模式下,SPI的時(shí)鐘只有在往DR寄存器里面寫(xiě)數(shù)據(jù)的時(shí)候才會(huì)產(chǎn)生,讀是不會(huì)產(chǎn)生的。所以要讀取slave shift out的數(shù)據(jù),master必須先發(fā)一個(gè)“DUMMY”數(shù)據(jù)以產(chǎn)生時(shí)鐘。

建議配置STM32為雙向主機(jī)、從機(jī); 配置為主機(jī)接收前讀取一次DR,再發(fā)送DUMMY(建議發(fā)0x00或0xFF,不要增加沒(méi)必要的干擾)

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)寄存器

    關(guān)注

    0

    文章

    33

    瀏覽量

    7732
  • SPI接口
    +關(guān)注

    關(guān)注

    0

    文章

    258

    瀏覽量

    34288
  • CPHA
    +關(guān)注

    關(guān)注

    0

    文章

    8

    瀏覽量

    9364
  • USART串口
    +關(guān)注

    關(guān)注

    0

    文章

    32

    瀏覽量

    6791
  • stm32f1
    +關(guān)注

    關(guān)注

    1

    文章

    56

    瀏覽量

    12148
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    STM32F1的I2C模塊協(xié)議簡(jiǎn)介

    I2C是一種多主從的串行通訊協(xié)議STM32F1的I2C模塊支持標(biāo)速(最高100kHz)和高速(最高400kHz)兩種工作模式。
    發(fā)表于 07-25 14:49 ?3819次閱讀
    <b class='flag-5'>STM32F1</b>的I2C<b class='flag-5'>模塊</b><b class='flag-5'>協(xié)議</b>簡(jiǎn)介

    STM32F1的MPU6050模塊軟件卡爾曼濾波資料

    STM32F1的MPU6050模塊軟件卡爾曼濾波資料
    發(fā)表于 11-13 14:54 ?23次下載

    STM32F1系列的HAL庫(kù)手冊(cè)免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是STM32F1系列單片機(jī)的HAL庫(kù)手冊(cè)免費(fèi)下載。
    發(fā)表于 11-19 14:36 ?469次下載
    <b class='flag-5'>STM32F1</b>系列的HAL庫(kù)手冊(cè)免費(fèi)下載

    STM32F1的固件庫(kù)免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是STM32F1的固件庫(kù)免費(fèi)下載。
    發(fā)表于 12-26 17:22 ?156次下載
    <b class='flag-5'>STM32F1</b>的固件庫(kù)免費(fèi)下載

    STM32F1系列DEBUG調(diào)試功能需要配置嗎?

    STM32F1系列的DEBUG調(diào)試功能需要配置嗎?
    的頭像 發(fā)表于 03-01 13:57 ?3251次閱讀

    STM32F1系列芯片中文參考手冊(cè)

    STM32F1系列芯片中文參考手冊(cè)(嵌入式開(kāi)發(fā)培訓(xùn)教程)-STM32F1系列芯片的中文用戶手冊(cè)
    發(fā)表于 07-30 09:32 ?215次下載
    <b class='flag-5'>STM32F1</b>系列芯片中文參考手冊(cè)

    STM32F1官方手冊(cè)資料(中英文)

    STM32F1官方手冊(cè)資料(中英文)
    發(fā)表于 11-05 16:28 ?69次下載

    STM32F1F4的區(qū)別

    STM32F1F4的區(qū)別
    發(fā)表于 12-04 13:51 ?24次下載
    <b class='flag-5'>STM32F1</b>和<b class='flag-5'>F</b>4的區(qū)別

    STM32F1 & SHT3x溫濕度模塊

    STM32F1 & SHT3x溫濕度模塊提示:以下程序是基于STM32F103和SHT3x系列硬件文章目錄STM32F1 & SHT3x溫濕度
    發(fā)表于 12-04 18:36 ?27次下載
    <b class='flag-5'>STM32F1</b> & SHT3x溫濕度<b class='flag-5'>模塊</b>

    STM32F1 使用easyflash操作片內(nèi)flash

    STM32F1 使用easyflash操作片內(nèi)flash
    發(fā)表于 12-09 10:06 ?15次下載
    <b class='flag-5'>STM32F1</b> 使用easyflash操作片內(nèi)flash

    AN3427_從STM32F1移植到STM32F2的應(yīng)用手冊(cè)

    AN3427_從STM32F1移植到STM32F2的應(yīng)用手冊(cè)
    發(fā)表于 11-21 17:06 ?9次下載
    AN3427_從<b class='flag-5'>STM32F1</b>移植到<b class='flag-5'>STM32F</b>2的應(yīng)用手冊(cè)

    AN4904_從STM32F1STM32F4的軟件移植

    AN4904_從STM32F1STM32F4的軟件移植
    發(fā)表于 11-21 17:06 ?3次下載
    AN4904_從<b class='flag-5'>STM32F1</b>到<b class='flag-5'>STM32F</b>4的軟件移植

    UM1847_基于STM32F1系列的STM32CubeF1軟件庫(kù)使用入門

    UM1847_基于STM32F1系列的STM32CubeF1軟件庫(kù)使用入門
    發(fā)表于 11-22 08:22 ?4次下載
    UM1847_基于<b class='flag-5'>STM32F1</b>系列的<b class='flag-5'>STM32CubeF1</b>軟件庫(kù)使用入門

    AN2629 STM32F1低功耗模式

    AN2629 STM32F1低功耗模式
    發(fā)表于 11-24 08:30 ?0次下載
    AN2629 <b class='flag-5'>STM32F1</b>低功耗模式

    單片機(jī)STM32F1資料分享

    單片機(jī)STM32F1資料分享
    發(fā)表于 05-16 18:04 ?15次下載