spi概述
SPI是串行外設接口(Serial Peripheral Interface)的縮寫,是一種高速的,全雙工,同步的通信總線,并且在芯片的管腳上只占用四根線,節(jié)約了芯片的管腳,同時為PCB的布局上節(jié)省空間,提供方便,正是出于這種簡單易用的特性,越來越多的芯片集成了這種通信協(xié)議,比如 EEPROM,F(xiàn)LASH,實時時鐘,AD轉換器。 W25Q64 是一款SPI接口的Flash芯片,其存儲空間為 64Mbit,相當于8M字節(jié)。W25Q64可以支持 SPI 的模式 0 和模式 3,也就是 CPOL=0/CPHA=0 和CPOL=1/CPHA=1 這兩種模式。
視頻教程
https://www.bilibili.com/video/BV16W4y147R1/
樣品申請
https://www.wjx.top/vm/wFGhGPF.aspx#
csdn課程
課程更加詳細。
https://download.csdn.net/course/detail/37144
生成例程
這里準備了自己繪制的開發(fā)板進行驗證。
SPI配置
在開發(fā)板中有arduino接口,配置這幾個接口為spi。
本次實驗使用的SPI與Flash通信,配置如下。 SPI的通信原理很簡單,它以主從方式工作,這種模式通常有一個主設備和一個或多個從設備,需要至少4根線,事實上3根也可以(單向傳輸時)。也是所有基于SPI的設備共有的,它們是MISO(主設備數(shù)據(jù)輸入)、MOSI(主設備數(shù)據(jù)輸出)、SCLK(時鐘)、CS(片選)。 (1)MISO– Master Input Slave Output,主設備數(shù)據(jù)輸入,從設備數(shù)據(jù)輸出; (2)MOSI– Master Output Slave Input,主設備數(shù)據(jù)輸出,從設備數(shù)據(jù)輸入; (3)SCLK – Serial Clock,時鐘信號,由主設備產(chǎn)生; (4)CS – Chip Select,從設備使能信號,由主設備控制。
負責通訊的3根線了。通訊是通過數(shù)據(jù)交換完成的,這里先要知道SPI是串行通訊協(xié)議,也就是說數(shù)據(jù)是一位一位的傳輸?shù)摹_@就是SCLK時鐘線存在的原因,由SCLK提供時鐘脈沖,SDI,SDO則基于此脈沖完成數(shù)據(jù)傳輸。數(shù)據(jù)輸出通過 SDO線,數(shù)據(jù)在時鐘上升沿或下降沿時改變,在緊接著的下降沿或上升沿被讀取。完成一位數(shù)據(jù)傳輸,輸入也使用同樣原理。因此,至少需要8次時鐘信號的改變(上沿和下沿為一次),才能完成8位數(shù)據(jù)的傳輸。 時鐘信號線SCLK只能由主設備控制,從設備不能控制。同樣,在一個基于SPI的設備中,至少有一個主設備。這樣的傳輸方式有一個優(yōu)點,在數(shù)據(jù)位的傳輸過程中可以暫停,也就是時鐘的周期可以為不等寬,因為時鐘線由主設備控制,當沒有時鐘跳變時,從設備不采集或傳送數(shù)據(jù)。SPI還是一個數(shù)據(jù)交換協(xié)議:因為SPI的數(shù)據(jù)輸入和輸出線獨立,所以允許同時完成數(shù)據(jù)的輸入和輸出。芯片集成的SPI串行同步時鐘極性和相位可以通過寄存器配置,IO模擬的SPI串行同步時鐘需要根據(jù)從設備支持的時鐘極性和相位來通訊。 最后,SPI接口的一個缺點:沒有指定的流控制,沒有應答機制確認是否接收到數(shù)據(jù)。
NOR Flash
NOR Flash是一種非易失閃存技術,是Intel在1988年創(chuàng)建。是市場上兩種主要的非易失閃存技術之一。 以GD25Q64E為例,該 Flash為64M-bit大小,即8192K-Byte。
W25Q64將8M的容量分為127個塊(Block),每個塊大小為64K字節(jié),每個塊又分為16個扇區(qū)(Sector),每個扇區(qū)4K個字節(jié)。W25Q64的最小擦除單位為一個扇區(qū),也就是每次必須擦除4K個字節(jié)。 即4K16128=8192K=8M
W25Q64的原理及應用
復位初始化
對于復位,需要發(fā)送0x66和0x99
代碼中的初始化。
/* Reset Operations */
#define RESET_ENABLE_CMD 0x66
#define RESET_MEMORY_CMD 0x99
/**
* @brief Initializes the W25Q128FV interface.
* @retval None
*/
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 */
for(int i=0;i< 2;i++){
spi_SendRcvByte(SPI0,cmd[i]);
}
// HAL_SPI_Transmit(&hspi1, cmd, 2, W25Qx_TIMEOUT_VALUE);
W25Qx_Disable();
}
ID
對于兆易創(chuàng)新W25Q64,主要有三種查詢ID方式。
可以使用90H查詢設備ID,以判斷是否是W25Q64設備。
/* Identification Operations */
#define READ_ID_CMD 0x9F
/**
* @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);
for(int i=0;i< 4;i++)
spi_SendRcvByte(SPI0,cmd[i]);
for(int i=0;i< 2;i++)
{
ID[i]=spi_SendRcvByte(SPI0,0x00);
}
W25Qx_Disable();
}
讀取數(shù)據(jù)
對于兆易創(chuàng)新W25Q64,讀取數(shù)據(jù)使用0x03指令,后面添加需要讀取的數(shù)據(jù)地址。 數(shù)據(jù)可以一直進行讀取,當不需要讀取數(shù)據(jù)時候將片選CS拉高,關閉時鐘SCLK即可。
#define READ_CMD 0x03
/**
* @brief Reads an amount of data from the QSPI memory.
* @param pData: Pointer to data to be read
* @param ReadAddr: Read start address
* @param Size: Size of data to read
* @retval QSPI memory status
*/
uint8_t BSP_W25Qx_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)
{
uint8_t cmd[4];
uint8_t status;
/* Configure the command */
cmd[0] = READ_CMD;
cmd[1] = (uint8_t)(ReadAddr > > 16);
cmd[2] = (uint8_t)(ReadAddr > > 8);
cmd[3] = (uint8_t)(ReadAddr);
W25Qx_Enable();
/* Send the read ID command */
// HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);
for(int i= 0;i< 4;i++)
spi_SendRcvByte(SPI0,cmd[i]);
/* Reception of the data */
// if (HAL_SPI_Receive(&hspi1, pData,Size,W25Qx_TIMEOUT_VALUE) != HAL_OK)
// {
// return W25Qx_ERROR;
// }
for(int i= 0;i< Size;i++)
pData[i]=spi_SendRcvByte(SPI0,0x00);
if (status != 0x00)
{
return W25Qx_ERROR;
}
W25Qx_Disable();
return W25Qx_OK;
}
以讀取10個數(shù)據(jù)為例子,波形如下所示。
BSP_W25Qx_Read(rData2,0x1000,0x00a);
擦除扇區(qū)
最小的擦除單位是扇區(qū),擦除指令為0x20和3字節(jié)的地址。
#define SECTOR_ERASE_CMD 0x20
/**
* @brief Erases the specified block of the QSPI memory.
* @param BlockAddress: Block address to erase
* @retval QSPI memory status
*/
uint8_t BSP_W25Qx_Erase_Block(uint32_t Address)
{
uint8_t cmd[4];
uint32_t tickstart=0 ;
cmd[0] = SECTOR_ERASE_CMD;
cmd[1] = (uint8_t)(Address > > 16);
cmd[2] = (uint8_t)(Address > > 8);
cmd[3] = (uint8_t)(Address);
/* Enable write operations */
BSP_W25Qx_WriteEnable();
/*Select the FLASH: Chip Select low */
W25Qx_Enable();
/* Send the read ID command */
// HAL_SPI_Transmit(&hspi1, cmd, 4, W25Qx_TIMEOUT_VALUE);
for(int i =0;i< 4;i++)
spi_SendRcvByte(SPI0,cmd[i]);
/*Deselect the FLASH: Chip Select high */
W25Qx_Disable();
delay_1ms(1);
/* Wait the end of Flash writing */
while(BSP_W25Qx_GetStatus() == W25Qx_BUSY)
{
tickstart++;
/* Check for the Timeout */
if(tickstart > W25Q128FV_SECTOR_ERASE_MAX_TIME)
{
return W25Qx_TIMEOUT;
}
}
return W25Qx_OK;
}
寫數(shù)據(jù)
對于寫數(shù)據(jù)到flash中,使用0x02指令進行寫數(shù)據(jù),后面還需要指定24位地址,才能進行寫數(shù)據(jù)。
#define PAGE_PROG_CMD 0x02
/**
* @brief Writes an amount of data to the QSPI memory.
* @param pData: Pointer to data to be written
* @param WriteAddr: Write start address
* @param Size: Size of data to write,No more than 256byte.
* @retval QSPI memory status
*/
uint8_t BSP_W25Qx_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
{
uint8_t cmd[4];
uint32_t end_addr, current_size, current_addr;
uint32_t tickstart =0;
/* Calculation of the size between the write address and the end of the page */
current_addr = 0;
while (current_addr <= WriteAddr)//判斷地址屬于哪一扇區(qū)開始
{
current_addr += W25Q128FV_PAGE_SIZE;//0x100- > 256 bytes
}
current_size = current_addr - WriteAddr;
/* Check if the size of the data is less than the remaining place in the page */
if (current_size > Size)
{
current_size = Size;
}
/* Initialize the adress variables *///寫入地址大小范圍
current_addr = WriteAddr;
end_addr = WriteAddr + Size;
/* Perform the write page by page */
do
{
/* Configure the command */
cmd[0] = PAGE_PROG_CMD;
cmd[1] = (uint8_t)(current_addr > > 16);
cmd[2] = (uint8_t)(current_addr > > 8);
cmd[3] = (uint8_t)(current_addr);
/* Enable write operations */
BSP_W25Qx_WriteEnable();
W25Qx_Enable();
/* Send the command */
// if (HAL_SPI_Transmit(&hspi1,cmd, 4, W25Qx_TIMEOUT_VALUE) != HAL_OK)
// {
// return W25Qx_ERROR;
// }
for(int i=0;i< 4;i++)
spi_SendRcvByte(SPI0,cmd[i]);
/* Transmission of the data */
// if (HAL_SPI_Transmit(&hspi1, pData,current_size, W25Qx_TIMEOUT_VALUE) != HAL_OK)
// {
// return W25Qx_ERROR;
// }
for(int i=0;i< current_size;i++)
spi_SendRcvByte(SPI0,pData[i]);
W25Qx_Disable();
/* Wait the end of Flash writing */
while(BSP_W25Qx_GetStatus() == W25Qx_BUSY)
{
tickstart++;
/* Check for the Timeout */
if(tickstart > W25Qx_TIMEOUT_VALUE)
{
return W25Qx_TIMEOUT;
}
}
/* Update the address and size variables for next page programming */
current_addr += current_size;
上一篇:基于GD32E503主控芯片實現(xiàn)直流數(shù)控電源的設計
下一篇:STM32CUBEMX開發(fā)GD32F303(2)----讀保護與寫保護
- 熱門資源推薦
- 熱門放大器推薦
設計資源 培訓 開發(fā)板 精華推薦
- LTC3589 演示板、具有排序和 I2C 的 8 輸出穩(wěn)壓器
- 基于PTN5100 USB Type-C Power Delivery PHY的典型應用
- LTC3857EGN-1 高效率雙路 1V/1.2V 降壓轉換器的典型應用電路,具有電感器 DCR 電流檢測
- GS431B精密穩(wěn)壓器的典型應用
- 使用 MaxLinear, Inc 的 SP6656 的參考設計
- LTC3407EDD 演示板,雙路同步降壓型 DC/DC 轉換器,Vin = 2.5V - 5.5V,Vout1 = 1.2V / 1.5V / 1.8V @ 600mA,Vout2 = 2.5V @ 600mA
- The Skull CTF:猜謎頭顱游戲工具
- 使用 LTC2367CDE-16、16 位、500ksps、偽差分單極 SAR ADC 的典型應用
- AD5322 雙路 12 位緩沖數(shù)模轉換器的典型應用
- 使用 Analog Devices 的 LTC1439CG 的參考設計
- 消息稱三星在美“特斯拉專供”2nm 生產(chǎn)線 2026H2 投運,初期產(chǎn)能每月 1~1.5 萬片晶圓
- 黑客如何入侵軟件定義的汽車
- 中國首款國芯腦機智能頭環(huán)正式發(fā)布:非侵入式腦機 全自主國產(chǎn)芯片
- 自動駕駛中Transformer大模型會取代深度學習嗎?
- 這家面板廠在車載OLED領域或再迎新大單
- 激光雷達和攝像頭,誰會是機器人主要的“眼睛”?
- 毫米波雷達技術參數(shù)有哪些?毫米波雷達如何用于機器人導航
- 毫米波雷達技術有哪些優(yōu)勢?如何提高毫米波雷達測距精度
- 工業(yè)邊緣設備的安全啟動,TPM 2.0與可信執(zhí)行環(huán)境(TEE)的硬件級防護
- 工業(yè)機器人視覺系統(tǒng)的深度學習優(yōu)化,YOLOv8、3D點云匹配的實時性提升