概述
SPI是串行外設接口(Serial Peripheral Interface)的縮寫,是一種 高速的 , 全雙工 ,同步的通信總線,并且在芯片的管腳上只占用四根線,節約了芯片的管腳,同時為PCB的布局上節省空間,提供方便,正是出于這種簡單易用的特性,越來越多的芯片集成了這種通信協議,比如AT91RM9200。 SPI是一種高速、高效率的串行接口技術。通常由一個主模塊和一個或多個從模塊組成,主模塊選擇一個從模塊進行同步通信,從而完成數據的交換。SPI是一個環形結構,通信時需要至少4根線(事實上在單向傳輸時3根線也可以)。
接口
SPI的通信原理很簡單,它以主從方式工作,這種模式通常有一個主設備和一個或多個從設備,需要至少4根線,事實上3根也可以(單向傳輸時)。也是所有基于SPI的設備共有的,它們是MISO(主設備數據輸入)、MOSI(主設備數據輸出)、SCLK(時鐘)、CS(片選)。
- MISO– Master Input Slave Output,主設備數據輸入,從設備數據輸出;
- MOSI– Master Output Slave Input,主設備數據輸出,從設備數據輸入;
- SCLK – Serial Clock,時鐘信號,由主設備產生;
- CS – Chip Select,從設備使能信號,由主設備控制。
其中,CS是從芯片是否被主芯片選中的控制信號,也就是說只有片選信號為預先規定的使能信號時(高電位或低電位),主芯片對此從芯片的操作才有效。這就使在同一條總線上連接多個SPI設備成為可能。 接下來就負責通訊的3根線了。通訊是通過數據交換完成的,這里先要知道SPI是串行通訊協議,也就是說數據是一位一位的傳輸的。這就是SCLK時鐘線存在的原因,由SCLK提供時鐘脈沖,SDI,SDO則基于此脈沖完成數據傳輸。數據輸出通過 SDO線,數據在時鐘上升沿或下降沿時改變,在緊接著的下降沿或上升沿被讀取。完成一位數據傳輸,輸入也使用同樣原理。因此,至少需要8次時鐘信號的改變(上沿和下沿為一次),才能完成8位數據的傳輸。 時鐘信號線SCLK只能由主設備控制,從設備不能控制。同樣,在一個基于SPI的設備中,至少有一個主設備。這樣的傳輸方式有一個優點,在數據位的傳輸過程中可以暫停,也就是時鐘的周期可以為不等寬,因為時鐘線由主設備控制,當沒有時鐘跳變時,從設備不采集或傳送數據。SPI還是一個數據交換協議:因為SPI的數據輸入和輸出線獨立,所以允許同時完成數據的輸入和輸出。芯片集成的SPI串行同步時鐘極性和相位可以通過寄存器配置,IO模擬的SPI串行同步時鐘需要根據從設備支持的時鐘極性和相位來通訊。 最后,SPI接口的一個缺點:沒有指定的流控制,沒有應答機制確認是否接收到數據。
SPI四種通信模式
不同的從設備可能在出廠是就是配置為某種模式,這是不能改變的;但我們的通信雙方必須是工作在同一模式下,所以我們可以對我們的主設備的SPI模式進行配置,通過CPOL(時鐘極性)和CPHA(時鐘相位)來 控制我們主設備的通信模式,具體如下: 時鐘極性(CPOL)定義了時鐘空閑狀態電平: CPOL=0,表示當SCLK=0時處于空閑態,所以有效狀態就是SCLK處于高電平時 CPOL=1,表示當SCLK=1時處于空閑態,所以有效狀態就是SCLK處于低電平時 時鐘相位(CPHA)定義數據的采集時間。 CPHA=0,在時鐘的第一個跳變沿(上升沿或下降沿)進行數據采樣。,在第2個邊沿發送數據 CPHA=1,在時鐘的第二個跳變沿(上升沿或下降沿)進行數據采樣。,在第1個邊沿發送數據 例如: Mode0:CPOL=0,CPHA=0:此時空閑態時,SCLK處于低電平,數據采樣是在第1個邊沿,也就是SCLK由低電平到高電平的跳變,所以數據采樣是在上升沿(準備數據),(發送數據)數據發送是在下降沿。
Mode1:CPOL=0,CPHA=1:此時空閑態時,SCLK處于低電平,數據發送是在第1個邊沿,也就是SCLK由低電平到高電平的跳變,所以數據采樣是在下降沿,數據發送是在上升沿。
Mode2:CPOL=1,CPHA=0:此時空閑態時,SCLK處于高電平,數據采集是在第1個邊沿,也就是SCLK由高電平到低電平的跳變,所以數據采集是在下降沿,數據發送是在上升沿。
Mode3:CPOL=1,CPHA=1:此時空閑態時,SCLK處于高電平,數據發送是在第1個邊沿,也就是SCLK由高電平到低電平的跳變,所以數據采集是在上升沿,數據發送是在下降沿。
SPI模式 | CPOL | CPOA | 空閑時SCK時鐘 | 采樣時刻 |
---|---|---|---|---|
0 | 0 | 0 | 低電平 | 奇數邊沿 |
1 | 0 | 1 | 低電平 | 偶數邊沿 |
2 | 1 | 0 | 高電平 | 奇數邊沿 |
3 | 1 | 1 | 高電平 | 偶數邊沿 |
這樣兩兩組合就出現了4種通訊模式,但是通信原理是一樣的。
示例
使用之前的文章作為案例:STM32CUBEMX(13)--SPI,W25Q128外部Flash移植。 https://editor.csdn.net/md/?articleId=117756829 使用BSP_W25Qx_Init進行初始化,BSP_W25Qx_Read_ID進行讀取設備ID。
uint8_t BSP_W25Qx_Init(void)
{
/* Reset W25Qxxx */
BSP_W25Qx_Reset();
return BSP_W25Qx_GetStatus();
}
/**
* @brief This function reset the W25Qx.
* @retval None
*/
static void BSP_W25Qx_Reset(void)
{
uint8_t cmd[2] = {RESET_ENABLE_CMD,RESET_MEMORY_CMD};
W25Qx_Enable();
/* Send the reset command */
HAL_SPI_Transmit(&hspi1, cmd, 2, W25Qx_TIMEOUT_VALUE);
W25Qx_Disable();
}
/**
* @brief Reads current status of the W25Q128FV.
* @retval W25Q128FV memory status
*/
static uint8_t BSP_W25Qx_GetStatus(void)
{
uint8_t cmd[] = {READ_STATUS_REG1_CMD};
uint8_t status;
W25Qx_Enable();
/* Send the read status command */
HAL_SPI_Transmit(&hspi1, cmd, 1, W25Qx_TIMEOUT_VALUE);
/* Reception of the data */
HAL_SPI_Receive(&hspi1,&status, 1, W25Qx_TIMEOUT_VALUE);
W25Qx_Disable();
/* Check the value of the register */
if((status & W25Q128FV_FSR_BUSY) != 0)
{
return W25Qx_BUSY;
}
else
{
return W25Qx_OK;
}
}
/**
* @brief Read Manufacture/Device ID.
* @param return value address
* @retval None
*/
void BSP_W25Qx_Read_ID(uint8_t *ID)
{
uint8_t cmd[4] = {READ_ID_CMD,0x00,0x00,0x00};
W25Qx_Enable();
/* Send the read ID command */
HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);
/* Reception of the data */
HAL_SPI_Receive(&hspi1,ID, 2, W25Qx_TIMEOUT_VALUE);
W25Qx_Disable();
}
定義如下。
/* Reset Operations */
#define RESET_ENABLE_CMD 0x66
#define RESET_MEMORY_CMD 0x99
/* Identification Operations */
#define READ_ID_CMD 0x90
首先進行初始化,函數為BSP_W25Qx_Init(),其中含有2個函數,分別是BSP_W25Qx_Reset()和BSP_W25Qx_GetStatus();在BSP_W25Qx_Reset()中為發生0x66和0x99,在BSP_W25Qx_GetStatus()中為發生0x05,之后獲取一個uint8_t類型的數據。 之后進行讀取ID,函數為BSP_W25Qx_Read_ID(),首先發送4個字節的數據,分別是0x90,0x00,0x00,0x00,之后讀取設備ID,為2個字節的數據,W25Q128的ID為0XEF17。 HAL_SPI_Transmit,HAL_SPI_Received都是半工通信,HAL_SPI_Transmits使用的時候MOSI上有數據,忽略MISO,HAL_SPI_Received反之,HAL_SPI_TransmitReceive是全雙工通信,發送數據的同時也在接收數據,故在HAL_SPI_Receive讀取的時候,雖然也有發送數據,但是忽略。 通過示波器抓取的波形如下所示。 首先查看初始化設備發送的0x66和0x99的波形。 在查看讀取設備ID發送的0x90,0x00,0x00,0x00的波形。 在查看設備發送給主機的ID波形。 HAL_SPI_Transmit,HAL_SPI_Received都是半工通信,故在HAL_SPI_Receive讀取的時候,雖然也有發送數據,但是忽略。
審核編輯:湯梓紅
-
通信協議
+關注
關注
28文章
883瀏覽量
40308 -
接口
+關注
關注
33文章
8598瀏覽量
151157 -
SPI
+關注
關注
17文章
1706瀏覽量
91583
發布評論請先 登錄
相關推薦
評論