文章目錄
- 1.參考教程
- 2. 4種時間模式
- 3. 3個編程接口
- 3.1 `HAL_StatusTypeDef HAL_SPI_Transmit(...)` :
- 3.1.1 參數說明
- 3.1.2 例子
- 3.2 `HAL_StatusTypeDef HAL_SPI_Receive(...)` :
- 3.2.1參數說明
- 3.2.2 例子
- 3.3 `HAL_StatusTypeDef HAL_SPI_TransmitReceive(...)` :
- 3.3.1 參數說明
- 3.3.2 例子
- 4. spi應用-flash數據寫入
- 4.1 flash數據寫入過程
- 4.2 流程
- 5. 流程實現
- 5.1 寫使能
- 5.2 扇區擦除
- 5.3 頁編程
- 6. 代碼實現
- 5. spi應用-flash數據加載
- 5.1 流程
- 5.2 代碼實現
1.參考教程
[STM32 HAL庫][SPI]外部flash實驗
[STM32 HAL庫][SPI]外部flash數據存取
2. 4種時間模式
3. 3個編程接口
3.1 HAL_StatusTypeDef HAL_SPI_Transmit(...)
:
用于通過 SPI 總線發送數據,返回 HAL_StatusTypeDef
類型狀態值 ,作用為“發送”。
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi,uint8_t *pData,uint16_t Size,uint32_t Timeout)
3.1.1 參數說明
參數名 | 說明 |
---|---|
hspi | 填寫 SPI 句柄的指針 |
pData | 填寫要發送的數據 |
Size | 填寫要發送的數據的數量,以字節為單位 |
Timeout | 超時時間,單位是 ms;HAL_MAX_DELAY 表示無限長的超時時間 |
3.1.2 例子
- 通信場景:主機(單片機)向從機1發送數據
0x5a, 0x33
- 硬件連接:涉及主機與從機的
MOSI
(主機輸出從機輸入)、MISO
(主機輸入從機輸出 ,從機1此處未動作 )、SCK
(時鐘 )、NSS
(從機選擇 ,NSS1 選中從機1 )引腳 - 代碼邏輯:
- 定義發送數據數組
uint8_t dataToSend[] = {0x5a, 0x33};
- 通過
HAL_GPIO_WritePin
函數拉低引腳選中從機1 - 調用
HAL_SPI_Transmit
函數發送數據 - 數據發送后,通過
HAL_GPIO_WritePin
函數拉高引腳取消選中從機1
- 定義發送數據數組
3.2 HAL_StatusTypeDef HAL_SPI_Receive(...)
:
用于通過 SPI 總線接收數據,返回 HAL_StatusTypeDef
類型狀態值 ,作用為“接收”。
HAL_StatusTypeDef HAL_SPI_Receive(&hspi1, uint8_t *pData, uint16_t Size, uint32_t Timeout)
3.2.1參數說明
參數名 | 說明 |
---|---|
參數hspi | 填寫SPI句柄的指針 |
參數pData | 填寫接收緩沖區 |
參數Size | 填寫要發送的數據的數量,以字節為單位 |
參數Timeout | 超時時間,單位是ms;HAL_MAX_DELAY表示無限長的超時時間 |
3.2.2 例子
- 功能描述:從從機1接收2個字節的數據
- 硬件連接:主機(單片機)與從機1通過MOSI、MISO、SCK、NSS1引腳連接,從機還有從機2、從機3,引腳連接邏輯同從機1
- 代碼邏輯:
- 定義接收緩沖區
uint8_t dataRcvd[] = {0xff, 0xff};
- 通過
HAL_GPIO_WritePin(..., GPIO_PIN_RESET);
函數拉低引腳選中從機1 - 調用
HAL_SPI_Receive(&hspi1, dataRcvd, 2, HAL_MAX_DELAY);
函數,參數含SPI句柄&hspi1
、接收緩沖區dataRcvd
、數據長度2
(字節)、超時時間HAL_MAX_DELAY
(無限超時 ) - 數據接收后,通過
HAL_GPIO_WritePin(..., GPIO_PIN_SET);
函數拉高引腳取消選中從機1
- 定義接收緩沖區
- 時序圖:展示NSS1(低電平選中 )、SCK(時鐘信號 )、MOSI(發送
0xff
、0xff
波形 )、MISO(接收0x1f
、0x27
波形 )的時序關系 ,呈現SPI接收數據時各信號的變化 。
3.3 HAL_StatusTypeDef HAL_SPI_TransmitReceive(...)
:
用于通過 SPI 總線同時進行發送和接收數據操作,返回 HAL_StatusTypeDef
類型狀態值 ,作用為“發送同時接收”。
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
發送數據的同時接收數據
3.3.1 參數說明
參數名 | 說明 |
---|---|
參數hspi | 填寫SPI句柄的指針 |
參數pTxData | 填寫要發送的數據 |
參數pRxData | 填寫接收數據緩沖區 |
參數Size | 發送數據的數量=接收數據的數量,以字節為單位 |
參數Timeout | 超時時間,單位是ms |
3.3.2 例子
- 功能描述:發送
{0x5a, 0x33}
,同時接收 2 個字節數據 - 硬件連接:主機(單片機)與從機 1 通過
MOSI
(主機輸出從機輸入 )、MISO
(主機輸入從機輸出 )、SCK
(時鐘 )、NSS1
(從機選擇 )引腳連接,從機還有從機 2、從機 3 ,引腳連接邏輯同從機 1 - 代碼邏輯:
- 定義發送數據數組
uint8_t txData[] = {0x5a, 0x33};
- 定義接收緩沖區
uint8_t rxData[2];
- 通過
HAL_GPIO_WritePin(..., GPIO_PIN_RESET);
函數拉低引腳選中從機 1 - 調用
HAL_SPI_TransmitReceive(&hspi1, txData, rxData, 2, HAL_MAX_DELAY);
函數,參數含 SPI 句柄&hspi1
、發送數據數組txData
、接收緩沖區rxData
、數據長度2
(字節)、超時時間HAL_MAX_DELAY
(無限超時 ) - 數據收發后,通過
HAL_GPIO_WritePin(..., GPIO_PIN_SET);
函數拉高引腳取消選中從機 1
- 定義發送數據數組
- 時序圖:展示
NSS1
(低電平選中 )、SCK
(時鐘信號 )、MOSI
(發送0x5a
、0x33
波形 )、MISO
(接收0x1f
、0x27
波形 )的時序關系 ,呈現 SPI 同時收發數據時各信號的變化 。
4. spi應用-flash數據寫入
4.1 flash數據寫入過程
4.2 流程
5. 流程實現
5.1 寫使能
抽水機的寫使能是發送0x06
5.2 扇區擦除
扇區擦除的指令碼是0x20,所以首先發送0x20,后面接著24位的扇區首地址
5.3 頁編程
頁編程指令碼是0x02,后面跟著24位地址(往哪里寫地址就發誰的地址),再后面是發要寫入的數據,一次性可以寫多個數據
6. 代碼實現
static void SaveLEDState(uint8_t ledState)
{// #1. 寫使能uint8_t writeEnableCmd[] = {0x06};HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, writeEnableCmd, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);// #2. 扇區擦除uint8_t sectorErase[] = {0x20, 0x00, 0x00, 0x00};HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, sectorErase, 4, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);HAL_Delay(100);// #3. 寫使能HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_SPI_Transmit(&hspi1, writeEnableCmd, 1, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);// #4. 頁編程uint8_t pageProgCmd[5];//要發送5個字節pageProgCmd[0] = 0x02; //頁編程指令碼是0x02pageProgCmd[1] = 0x00; //地址pageProgCmd[2] = 0x00; //地址pageProgCmd[3] = 0x00; //地址pageProgCmd[4] = ledState; //要發送的數據HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, pageProgCmd, 5, HAL_MAX_DELAY);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); HAL_Delay(10); }
在主函數寫上 SaveLEDState( ledState);
就可以保存燈的狀態數據。
5. spi應用-flash數據加載
5.1 流程
讀取數據的指令碼是0x03,先發0x03,后面跟24位地址,再往后從總線上讀取數據。
首先聲明數組,用于存放要發送的數據。先發送讀取命令,然后接收數據。最后返回讀取的數據。
5.2 代碼實現
// 函數:讀取LED狀態(從Flash等存儲設備)
// 功能:通過SPI總線發送讀命令,接收并返回存儲的LED狀態數據
static uint8_t LoadLEDState(void)
{// 讀命令及地址:0x03為讀數據指令,后三個0x00為起始地址uint8_t readDataCmd[] = {0x03, 0x00, 0x00, 0x00}; uint8_t ledState; // 用于存儲讀取到的LED狀態數據// 選通從設備:拉低GPIOA_PIN_4(SPI從設備片選信號)HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 通過SPI發送讀命令:向從設備發送讀數據指令及地址,長度4字節,無限超時等待HAL_SPI_Transmit(&hspi1, readDataCmd, 4, HAL_MAX_DELAY); // 通過SPI接收數據:從從設備接收1字節數據(LED狀態),存入ledState,無限超時等待HAL_SPI_Receive(&hspi1, &ledState, 1, HAL_MAX_DELAY); // 取消選通:拉高GPIOA_PIN_4,釋放從設備片選HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); return ledState; // 返回讀取到的LED狀態
}