生活随笔
收集整理的這篇文章主要介紹了
《STM32从零开始学习历程》——SPI读取FLASH ID
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
《STM32從零開始學習歷程》@EnzoReventon
SPI讀取FLSAH ID
相關鏈接: SPI物理層及FLASH芯片介紹 SPI協議層 SPI特性及架構
參考資料: [野火EmbedFire]《STM32庫開發實戰指南——基于野火霸天虎開發板》 [正點原子]STM32F4開發指南-庫函數版本_V1.2 [ST]《STM32F4xx中文參考手冊》 SPI協議及總線協議介紹 W25Q128產品數據手冊
1 實現功能
本實驗為學習SPI的入門實驗,主要功能是實現使用SPI發送讀取FLASH ID的指令來讀取FLASH ID。
2 硬件設計
本文使用的外設為SPI1(正點原子F4探索者開發板)、FLASH以及USART1。 USART用來調試程序,我們還是使用USART1,因此將PB9,PB10與TX,RX相連接即可。
查閱正點原子F4探索者開發板硬件手冊,了解SPI引腳與GPIO的對應情況。 由上圖可以看出:SPI的SCK,MISO,MOSI分別與芯片的PB3,PB4,PB5連接,片選信號F_CS與PB14相連接,因此在后面程序配置的時候需要注意不能配置錯引腳。
3 軟件設計流程
① 使能SPIx和IO口時鐘 RCC_AHBxPeriphClockCmd() / RCC_APBxPeriphClockCmd(); ② 初始化IO口為復用功能 void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); ③ 設置引腳復用映射: GPIO_PinAFConfig(); ② 初始化SPIx,設置SPIx工作模式 void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct); ③ 使能SPIx void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState); ④ 編寫字節發送函數:uint8_t SPI_FLASH_ByteWrite(uint8_t data)
發送數據(指令):void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
接收返回的數據:uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) ;
⑤ 查看SPI傳輸狀態 SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE);
⑥ 編寫SPI發送函數 控制片選引腳:GPIO_ResetBits()、GPIO_SetBits(); ⑦ 主函數調用 ⑧ 優化程序(超時函數、宏定義)
4 代碼分析
宏定義
#define FLASH_SPI SPI1
#define FLASH_SPI_CLK RCC_APB2Periph_SPI1
#define FLASH_SPI_CLK_INIT RCC_APB2PeriphClockCmd #define FLASH_SPI_SCK_PIN GPIO_Pin_3
#define FLASH_SPI_SCK_GPIO_PORT GPIOB
#define FLASH_SPI_SCK_GPIO_CLK RCC_AHB1Periph_GPIOB
#define FLASH_SPI_SCK_SOURCE GPIO_PinSource3
#define FLASH_SPI_SCK_AF GPIO_AF_SPI1 #define FLASH_SPI_MOSI_PIN GPIO_Pin_5
#define FLASH_SPI_MOSI_GPIO_PORT GPIOB
#define FLASH_SPI_MOSI_GPIO_CLK RCC_AHB1Periph_GPIOB
#define FLASH_SPI_MOSI_SOURCE GPIO_PinSource5
#define FLASH_SPI_MOSI_AF GPIO_AF_SPI1 #define FLASH_SPI_MISO_PIN GPIO_Pin_4
#define FLASH_SPI_MISO_GPIO_PORT GPIOB
#define FLASH_SPI_MISO_GPIO_CLK RCC_AHB1Periph_GPIOB
#define FLASH_SPI_MISO_SOURCE GPIO_PinSource4
#define FLASH_SPI_MISO_AF GPIO_AF_SPI1 #define FLASH_SPI_CS_PIN GPIO_Pin_14
#define FLASH_SPI_CS_GPIO_PORT GPIOB
#define FLASH_SPI_CS_GPIO_CLK RCC_AHB1Periph_GPIOB
#define SPIT_FLAG_TIMEOUT ((uint32_t)0x1000)
初始化時鐘、GPIO、引腳復用
== == == == == == == == == == == == == == == == == == == == == == == ==
SPI GPIO初始化 復用函數
== == == == == == == == == == == == == == == == == == == == == == == ==
* /
static void SPI_GPIO_Config ( void )
{ GPIO_InitTypeDef GPIO_InitStructure
; FLASH_SPI_CLK_INIT ( FLASH_SPI_CLK
, ENABLE
) ; RCC_AHB1PeriphClockCmd ( FLASH_SPI_SCK_GPIO_CLK
| FLASH_SPI_MOSI_GPIO_CLK
| FLASH_SPI_MISO_GPIO_CLK
| FLASH_SPI_CS_GPIO_CLK
, ENABLE
) ; GPIO_PinAFConfig ( FLASH_SPI_SCK_GPIO_PORT
, FLASH_SPI_SCK_SOURCE
, FLASH_SPI_SCK_AF
) ; GPIO_PinAFConfig ( FLASH_SPI_MOSI_GPIO_PORT
, FLASH_SPI_MOSI_SOURCE
, FLASH_SPI_MOSI_AF
) ; GPIO_PinAFConfig ( FLASH_SPI_MISO_GPIO_PORT
, FLASH_SPI_MISO_SOURCE
, FLASH_SPI_MISO_AF
) ; GPIO_InitStructure
. GPIO_Pin
= FLASH_SPI_SCK_PIN
; GPIO_InitStructure
. GPIO_Mode
= GPIO_Mode_AF
; GPIO_InitStructure
. GPIO_Speed
= GPIO_Speed_50MHz
; GPIO_InitStructure
. GPIO_OType
= GPIO_OType_PP
; GPIO_InitStructure
. GPIO_PuPd
= GPIO_PuPd_NOPULL
; GPIO_Init ( FLASH_SPI_SCK_GPIO_PORT
, & GPIO_InitStructure
) ; GPIO_InitStructure
. GPIO_Pin
= FLASH_SPI_MOSI_PIN
; GPIO_Init ( FLASH_SPI_MOSI_GPIO_PORT
, & GPIO_InitStructure
) ; GPIO_InitStructure
. GPIO_Pin
= FLASH_SPI_MISO_PIN
; GPIO_Init ( FLASH_SPI_MOSI_GPIO_PORT
, & GPIO_InitStructure
) ; GPIO_InitStructure
. GPIO_Pin
= FLASH_SPI_CS_PIN
; GPIO_InitStructure
. GPIO_Mode
= GPIO_Mode_OUT
; GPIO_InitStructure
. GPIO_Speed
= GPIO_Speed_50MHz
; GPIO_InitStructure
. GPIO_OType
= GPIO_OType_PP
; GPIO_InitStructure
. GPIO_PuPd
= GPIO_PuPd_NOPULL
; GPIO_Init ( FLASH_SPI_CS_GPIO_PORT
, & GPIO_InitStructure
) ; }
SPI功能初始化
void SPI_Mode_Config ( void )
{ SPI_InitTypeDef SPI_InitStructure
; SPI_InitStructure
. SPI_BaudRatePrescaler
= SPI_BaudRatePrescaler_2
; SPI_InitStructure
. SPI_CPHA
= SPI_CPHA_1Edge
; SPI_InitStructure
. SPI_CPOL
= SPI_CPOL_Low
; SPI_InitStructure
. SPI_CRCPolynomial
= 7 ; SPI_InitStructure
. SPI_DataSize
= SPI_DataSize_8b
; SPI_InitStructure
. SPI_Direction
= SPI_Direction_2Lines_FullDuplex
; SPI_InitStructure
. SPI_FirstBit
= SPI_FirstBit_MSB
; SPI_InitStructure
. SPI_Mode
= SPI_Mode_Master
; SPI_InitStructure
. SPI_NSS
= SPI_NSS_Soft
; SPI_Init ( FLASH_SPI
, & SPI_InitStructure
) ; SPI_Cmd ( FLASH_SPI
, ENABLE
) ; }
使能GPIO初始化以及SPI功能初始化
void SPI_FLASH_Init ( void )
{ SPI_GPIO_Config ( ) ; SPI_Mode_Config ( ) ;
}
SPI FLASH 字節寫入函數
uint8_t
SPI_FLASH_ByteWrite ( uint8_t data
)
{ SPITimeOut
= ( ( uint32_t
) ( 10 * SPIT_FLAG_TIMEOUT
) ) ; while ( SPI_I2S_GetFlagStatus ( FLASH_SPI
, SPI_I2S_FLAG_TXE
) == RESET
) { SPITimeOut
-- ; if ( SPITimeOut
== 0 ) { return SPI_TIMEOUT_UserCallback ( 1 ) ; } } SPI_I2S_SendData ( FLASH_SPI
, data
) ; SPITimeOut
= ( ( uint32_t
) ( 10 * SPIT_FLAG_TIMEOUT
) ) ; while ( SPI_I2S_GetFlagStatus ( FLASH_SPI
, SPI_I2S_FLAG_RXNE
) == RESET
) { SPITimeOut
-- ; if ( SPITimeOut
== 0 ) { return SPI_TIMEOUT_UserCallback ( 2 ) ; } } return SPI_I2S_ReceiveData ( FLASH_SPI
) ; }
SPI讀取FLASH ID函數 查閱手冊,如果想要讀取FLASH的ID,需要給FLASH的第一個字節發送ABh,其余發送FF。
uint8_t
SPI_FLASH_Read_ID ( void )
{ uint8_t id
; FLASH_SPI_CS_LOW ( ) ; SPI_FLASH_ByteWrite ( 0xAB ) ; SPI_FLASH_ByteWrite ( 0xFF ) ; SPI_FLASH_ByteWrite ( 0xFF ) ; SPI_FLASH_ByteWrite ( 0xFF ) ; id
= SPI_FLASH_ByteWrite ( 0xFF ) ; FLASH_SPI_CS_HIGH ( ) ; return id
; }
超時函數,返回錯誤代碼函數
static uint32_t
SPI_TIMEOUT_UserCallback ( uint8_t errorCode
)
{ printf ( "\r\nSPI 等待超時!errorCode = %d\r\n" , errorCode
) ; return errorCode
;
}
主函數
int main ( void )
{ NVIC_PriorityGroupConfig ( NVIC_PriorityGroup_2
) ; delay_init ( 168 ) ; uart_init ( 115200 ) ; LED_Init ( ) ; SPI_FLASH_Init ( ) ; printf ( "\r\n===================================\r\n" ) ; printf ( "this is id : 0x%x" , SPI_FLASH_Read_ID ( ) ) ; while ( 1 ) { }
}
5 實驗效果
下載程序至開發板,通過串口調試助手可以看到返回的FLASH ID為0x17h。
總結
以上是生活随笔 為你收集整理的《STM32从零开始学习历程》——SPI读取FLASH ID 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。