Serial Peripheral Interface Bus(SPI)

目錄

  • 前言
  • 一、SPI協議簡介
    • SPI物理層
    • SPI協議層
      • 一、基本通訊程序
      • 2. 通訊的攔截和停止信號
      • 3.資料有效性
      • 4. CPOL/CPHA 及通訊模式
  • 、STM32cubeMX設定
  • 三、STM32 HAL庫中的SPI
    • 1.SPI初始化結構體

一、SPI協議簡介

SPI 協議是由摩托羅拉公司提出的通訊協議(Serial Peripheral Interface)即通訊外圍設備面是全高速雙工的通訊協議,它被廣泛地在通訊設備與MCU之間使用,它被廣泛地在ADC、LCD等設備與MCU之間使用,3 條總線分別為SCK、MOSI、MISO,觸發選用SS

SPI物理層

  1. SS(Slave Select) SS(從設備選擇信號線,常稱為選片信號線,也稱為NSS、CS,以下用NSS表示,當有多個SPI從設備與SPI主機連接時,設備的選擇其他信號線) SCK 及任何一條信號線,我在每一個設備的SPI、MISO 線上,即從設備上,都共同使用這3 條信號;而從設備本身的這個NS NS 上有多少條信號線,本協議的多少個設備通過路由,有多少個從設備上選址,即線路上的設備地址,即上的設備並進行通訊協議;沒有設備地址,使用NSS信號線來探測,當主機要選擇從設備的時候,該從設備的信號線設置為低調它,即從該設備被選中有效片選,接著開始與被人的設備進行SPI通訊,所以SPI通訊以NSS線置NSS低作為被線信號,以簡單的說此PIN是主人使用Slave要接收訊號以及Master去跟Slave要數據需要觸發的腳位(類似I2C的地址概念)
  2. SCK(Serial Clock):信號線時鐘,用於通訊數據同步,它由通訊主機設備產生,決定通訊的頻率,不同的支持的最高頻率不一樣,如STM32的SPI時鐘頻率最大為fpclk/2 ,兩個設備之間通訊時,通訊設備之間的通訊低速
  3. MOSI(主設備輸出/從輸入)主輸出:主設備輸出線,主機資源的資料設備從鏈路信號,從機由線索線輸入讀入發送的資料,即這條線索的方向為主機到從機
  4. MISO Master Input,,Slave Output):從主設備輸出的資料輸入(從線索輸入設備,從線索輸入)方向為從機到主機

二、SPI協議層

一、基本通訊程序

是一個機器與信號源的信號源都來自主機,NSS、CK、MOS I 由主機控制產生而 MISO 的由主機產生,通過信號線讀取從機的信號線,MOSI (SS) 為各種稀有的 MISO 時間段才有效,我和 MISO 傳輸一個短期的資料

CPOL/CPHA 及通訊模式

SPI 的一些寫法,不過簡單概括如下:

  1. CKPOL (時鐘極性) = CPOL = POL = Polarity = (時鐘)
  2. CKPHA(時鐘相位)= CPHA = PHA = Phase = (時鐘)相位
  3. SCK=SCLK=SPI的時鐘
  • Edge=邊沿,即隨時沿用的時刻,即上升沿或下降沿(下降沿)週期,有兩個沿,分別稱為:
  • 前沿=前一個邊沿=第一個邊沿,對於開始電壓是1,那麼就是1變成0的時候,對於開始電壓是0,那麼就是0變成1的時候;
  • 後沿=後一個沿=第二個邊沿,對於開始電壓是1,就是開始變成1的時候(同樣是在第一次1變成0之後,才可能有後面的0變成1),對於開始電壓是0,那麼就是1變成0的時候;

PS:這個CPOL/CP這個需要規範或者看正確處使用的傳感器的傳感器等產品的HA用於互通通信

AS5047P以為例

此處有明確的才能

三、STM32CubeMX建出SPI

所以下圖因為這個使用的原因會導致1因此會這樣可以用來代替上圖是84MHz,用於把SPI CLK 284/256MHz的速度來使用

四、STM32 HAL庫中的SPI

1.SPI初始化結構體

其他外設一樣,STM32 HAL庫提供了SPI初始化結構體及初始化函式來配置SPI外設,初始化結構體及式定義在庫檔案

  • STM32F4xx_hal_spi.h
  • STM32F4xx_hal_spi.c

從STM32CubeMX建檔出來會含初始化部分

static void MX_SPI2_Init(void)
{

/* USER CODE BEGIN SPI2_Init 0 */

/* USER CODE END SPI2_Init 0 */

/* USER CODE BEGIN SPI2_Init 1 */

/* USER CODE END SPI2_Init 1 */
/* SPI2 parameter configuration*/
hspi2.Instance = SPI2;//這邊是選用SPI2
hspi2.Init.Mode = SPI_MODE_MASTER;/*設定SPI 的主/從機端模式*/
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_16BIT;*設定SPI 的資料幀長度,可選8/16 位*/
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_HARD_OUTPUT;//這邊看需求設定可用內建
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;//這個是直接關西到傳輸速度
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */

/* USER CODE END SPI2_Init 2 */

}

2.介面函式

HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);

HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);

HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout);

HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size);

HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size);

HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi);

HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi);

HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi);

PS:這邊在接收部分需要使用物件Datasheet 怎麼傳輸AS5047P號後可以像封包一樣看到我發送的消息,由第2個接收到的,所以如果是使用TransmitReceive本方的大小試填入2

SPI_DMA範例

這邊比較推薦寫法如下
在HAL_SPI_TransmitReceive_DMA涵式內找到/* Enable the SPI Error Interrupt Bit */下面位置加上CS腳位拉High或拉Low來達成訊息同步

HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData,uint16_t Size)

******************以上省略***********
  /* Enable the SPI Error Interrupt Bit */
  __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
  /* Enable Tx DMA Request */
  SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);

error :
  /* Process Unlocked */
  __HAL_UNLOCK(hspi);
  return errorcode;

並且在Callback涵式中把腳位拉起來

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
}

void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
}

             

Leave a Comment

Your email address will not be published. Required fields are marked *

Shopping Cart