摘要
在嵌入式系統開發中,非易失性存儲是必不可少的一部分。W25Q64作為SPI Flash存儲器的一種,以其較高的存儲密度和擦寫次數受到廣泛應用。本文將深入探討STM32通過SPI驅動W25Q64的實戰技巧和方法,包括硬件連接、SPI配置、讀寫操作,以及實際代碼示例。
1. SPI通信基礎
SPI是一種串行通信協議,其特點包括:
- 同步通信:數據傳輸由時鐘信號控制。
- 主從模式:一個主設備控制多個從設備。
- 全雙工:可以同時發送和接收數據。
2. W25Q64 Flash存儲器特性
W25Q64是一款8Mbit的SPI Flash存儲器,主要特性包括:
- 容量:8Mbit,相當于1MB。
- 組織:分為128個扇區,每個扇區包含16頁,每頁256字節。
- 接口:SPI。
- 擦寫次數:高達100萬次。
3. 硬件連接
W25Q64與STM32的硬件連接如下:
CS
(片選)連接到STM32 GPIO(如PA4)。SCK
(時鐘)連接到STM32 SPI時鐘引腳(如PA5)。MOSI
(數據發送)連接到STM32 SPI數據發送引腳(如PA7)。MISO
(數據接收)連接到STM32 SPI數據接收引腳(如PA6)。VCC
連接到3.3V。GND
連接到地。
4. SPI配置
4.1 SPI初始化
SPI初始化是SPI通信的第一步,需要配置SPI的工作模式、數據大小、時鐘極性、時鐘相位等。
void SPI_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI1, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_Init(SPI1, &SPI_InitStructure);SPI_Cmd(SPI1, ENABLE);
}
5. W25Q64操作
5.1 W25Q64初始化
W25Q64初始化主要包括SPI初始化和片選信號的配置。
void W25Q64_Init(void) {SPI_Init(); // 初始化SPI// 其他W25Q64特定初始化代碼...
}
5.2 讀取W25Q64 ID
讀取W25Q64的ID是一個簡單的操作,可以用來驗證設備是否連接正確。
uint16_t W25Q64_ReadID(void) {uint16_t id = 0;SPI_CS_Low(); // 選中W25Q64SPI_SendByte(0x90); // 發送讀ID指令id = SPI_ReceiveByte() << 8; // 接收高字節id |= SPI_ReceiveByte(); // 接收低字節SPI_CS_High(); // 取消選中W25Q64return id;
}
5.3 寫入W25Q64
寫入W25Q64之前,需要先發送寫使能指令,然后執行頁編程。
void W25Q64_WriteByte(uint32_t addr, uint8_t data) {SPI_CS_Low(); // 選中W25Q64SPI_SendByte(0x06); // 發送寫使能指令SPI_SendByte(0x02); // 發送頁編程指令SPI_SendByte(addr >> 16); // 發送地址高字節SPI_SendByte(addr >> 8); // 發送地址中字節SPI_SendByte(addr); // 發送地址低字節SPI_SendByte(data); // 發送數據SPI_CS_High(); // 取消選中W25Q64// 等待寫入完成...
}
5.4 從W25Q64讀取數據
從W25Q64讀取數據是一個直接的過程,通過發送讀數據指令和地址即可。
uint8_t W25Q64_ReadByte(uint32_t addr) {uint8_t data;SPI_CS_Low(); // 選中W25Q64SPI_SendByte(0x03); // 發送讀數據指令SPI_SendByte(addr >> 16); // 發送地址高字節SPI_SendByte(addr >> 8); // 發送地址中字節SPI_SendByte(addr); // 發送地址低字節data = SPI_ReceiveByte(); // 接收數據SPI_CS_High(); // 取消選中W25Q64return data;
}
6. 完整示例代碼
以下是STM32通過SPI讀寫W25Q64的完整示例代碼。
int main(void) {// 系統初始化SystemInit();// 初始化W25Q64W25Q64_Init();// 讀取W25Q64 IDuint16_t id = W25Q64_ReadID();printf("W25Q64 ID: 0x%X\r\n", id);// 測試寫入和讀取uint32_t testAddr = 0x000000; // 測試地址uint8_t testData = 0xAA; // 測試數據W25Q64_WriteByte(testAddr, testData); // 寫入數據// 延遲一段時間,等待數據寫入完成for (volatile int i = 0; i < 0x100000; i++);// 讀取數據uint8_t readData = W25Q64_ReadByte(testAddr);if (readData == testData) {printf("Write and Read Test Passed.\r\n");} else {printf("Write and Read Test Failed.\r\n");}while(1) {// 其他應用代碼}
}
7. 結論
本文詳細介紹了STM32通過SPI接口驅動W25Q64 Flash存儲器的實戰技巧和方法。通過硬件連接、SPI配置、讀寫操作的詳細步驟和代碼示例,讀者可以快速掌握SPI通信的實現,并能夠應用到自己的項目中。在實際開發中,根據具體的硬件配置和需求進行適當的調整和優化。
?作者簡介:熱愛科研的嵌入式開發者,修心和技術同步精進
?歡迎關注我的知乎:對error視而不見
代碼獲取、問題探討及文章轉載可私信。
? 愿你的生命中有夠多的云翳,來造就一個美麗的黃昏。
🍎獲取更多嵌入式資料可點擊鏈接進群領取,謝謝支持!👇
點擊領取更多詳細資料