<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

淺析FLASH讀寫----SPI原理及應用

ss ? 作者:工程師譚軍 ? 2018-10-07 11:32 ? 次閱讀
SPI Flash
首先它是個Flash,Flash是什么東西就不多說了(非易失性存儲介質),分為NOR和NAND兩種(NOR和NAND的區別本篇不做介紹)。SPI一種通信接口。那么嚴格的來說SPI Flash是一種使用SPI通信的Flash,即,可能指NOR也可能是NAND。但現在大部分情況默認下人們說的SPI Flash指的是SPI NorFlash。早期Norflash的接口是parallel的形式,即把數據線和地址線并排與IC的管腳連接。但是后來發現不同容量的Norflash不能硬件上兼容(數據線和地址線的數量不一樣),并且封裝比較大,占用了較大的PCB板位置,所以后來逐漸被SPI(串行接口)Norflash所取代。同時不同容量的SPI Norflash管腳也兼容封裝也更小。,至于現在很多人說起NOR flash直接都以SPI flash來代稱。
NorFlash根據數據傳輸的位數可以分為并行(Parallel,即地址線和數據線直接和處理器相連)NorFlash和串行(SPI,即通過SPI接口和處理器相連)NorFlash;區別主要就是:1、SPI NorFlash每次傳輸一bit位的數據,parallel連接的NorFlash每次傳輸多個bit位的數據(有x8和x16bit兩種); 2、SPI NorFlash比parallel便宜,接口簡單點,但速度慢。
NandFlash是地址數據線復用的方式,接口標準統一(x8bit和x16bit),所以不同容量再兼容性上基本沒什么問題。但是目前對產品的需求越來越小型化以及成本要求也越來越高,所以SPI NandFlash漸漸成為主流,并且采用SPI NANDFlash方案,主控也可以不需要傳統NAND控制器,只需要有SPI接口接口操作訪問,從而降低成本。另外SPI NandFlash封裝比傳統的封裝也小很多,故節省了PCB板的空間。
怎么用說白了對于Flash就是讀寫擦,也就是實現flash的驅動。先簡單了解下spi flash的物理連接。
之前介紹SPI的時候說過,SPI接口目前的使用是多種方式(具體指的是物理連線有幾種方式),Dual SPI、Qual SPI和標準的SPI接口(這種方式肯定不會出現在連接外設是SPI Flash上,這玩意沒必要全雙工),對于SPI Flash來說,主要就是Dual和Qual這兩種方式。具體項目具體看了,理論上在CLK一定的情況下, 線數越多訪問速度也越快。我們項目采用的Dual SPI方式,即兩線。
淺析FLASH讀寫----SPI原理及應用

應用環境如下: 控制器 STM32F103

FLASH M25P64

讀寫方式 SPI

編程環境 MDK

以SPI方式讀寫FLASH的基本流程如下:

(1)設置SPI的工作模式。

(2)flash初始化。

(3)SPI寫一個字節、寫使能函數、寫數據函數,讀數據函數等編寫。

(4)主函數編寫。

一 設置SPI工作模式。

宏定義

#define SPI_FLASH_CS_LOW() GPIO_ResetBits(GPIOA,GPIO_Pin_4)

#define SPI_FLASH_CS_HIGH() GPIO_SetBits(GPIOA,GPIO_Pin_4)

/* M25P64 SPI Flash supported commands */

#define WRSR 0x01 /* Write Status Register instruction */

#define WREN 0x06 /* Write enable instruction */

#define WRDI 0x04 /* Write disable instruction */

#define READ 0x03 /* Read from Memory instruction */

#define RDSR 0x05 /* Read Status Register instruction */

#define RDID 0x9F /* Read identification */

#define FAST_READ 0x0B /* Fast read Status Register instruction */

#define SE 0xD8 /* Sector Erase instruction */

#define BE 0xC7 /* Bulk Erase instruction */

#define PP 0x02 /* Page prigrame instruction */

#define RES 0xAB /* Sector Erase instruction */

#define WIP_FLAG 0x01 /* Write In Progress (WIP) flag */

#define DUMMY_BYTE 0xA5

#define SIZE sizeof(TEXT_Buffer)

#define SPI_FLASH_PAGESIZE 0x100

#define FLASH_WriteAddress 0x000000

#define FLASH_ReadAddress FLASH_WriteAddress

#define FLASH_SectorToErase FLASH_WriteAddress

#define M25P64_FLASH_ID 0x202017

#define countof(a) (sizeof(a) / sizeof(*(a)))

#define BufferSize (countof(Tx_Buffer)-1)

SPI初始化

void Init_SPI1(void)

{

SPI_InitTypeDef SPI_InitStructure;

GPIO_InitTypeDef GPIO_InitStructure;

/* Enable SPI and GPIO clocks */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA , ENABLE);

/* Configure SPI pins: SCK, MISO and MOSI */

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);

/* Configure I/O for Flash Chip select */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* Deselect the FLASH: Chip Select high */

SPI_FLASH_CS_HIGH();

/* SPI configuration */

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //雙工模式

SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //SPI主模式

SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8bit數據

SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //CLK空閑時為高電平

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //CLK上升沿采樣,因為上升沿是第二個邊沿動作,所以也可以理解為第二個邊沿采樣

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //片選用軟件控制

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; //SPI頻率:72M/4 = 18M

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //高位在前

SPI_InitStructure.SPI_CRCPolynomial = 7; //crc7,stm32spi帶硬件ecc

SPI_Init(SPI1, &SPI_InitStructure);

/* Enable the SPI */

SPI_Cmd(SPI1, ENABLE);

SPI_FLASH_SendByte(0xFF); // 啟動傳輸

}

二 FLASH初始化

void Init_FLASH(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

/* Enable GPIO clocks */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOA , ENABLE);

/* PA0--SPI_FLASH_HOLD */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* PC4-- SPI_FLASH_WP */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOC, &GPIO_InitStructure);

GPIO_SetBits(GPIOA,GPIO_Pin_0);

GPIO_ResetBits(GPIOC,GPIO_Pin_4);

Init_SPI1();

}

三 函數編寫

/* 通過SPIx發送一個數據,同時接收一個數據*/

u8 SPI_FLASH_SendByte(u8 byte)

{

/* Loop while DR register in not emplty */

while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);//如果發送寄存器數據沒有發送完,循環等待

/* Send byte through the SPI1 peripheral */

SPI_I2S_SendData(SPI1, byte); //往發送寄存器寫入要發送的數據

/* Wait to receive a byte */

while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);//如果接收寄存器沒有收到數據,循環

/* Return the byte read from the SPI bus */

return SPI_I2S_ReceiveData(SPI1);

}

/* brief Enables the write access to the FLASH. */

void SPI_FLASH_WriteEnable(void)

{

/* Select the FLASH: Chip Select low */

SPI_FLASH_CS_LOW();

/* Send “Write Enable” instruction */

SPI_FLASH_SendByte(WREN);

/* Deselect the FLASH: Chip Select high */

SPI_FLASH_CS_HIGH();

}

/*brief Erases the specified FLASH sector. */

void SPI_FLASH_SectorErase(u32 SectorAddr)

{

/* Send write enable instruction */

SPI_FLASH_WriteEnable();

/* Sector Erase */

/* Select the FLASH: Chip Select low */

SPI_FLASH_CS_LOW();

/* Send Sector Erase instruction */

SPI_FLASH_SendByte(SE);

/* Send SectorAddr high nibble address byte */

SPI_FLASH_SendByte((SectorAddr & 0xFF0000) 》》 16);

/* Send SectorAddr medium nibble address byte */

SPI_FLASH_SendByte((SectorAddr & 0xFF00) 》》 8);

/* Send SectorAddr low nibble address byte */

SPI_FLASH_SendByte(SectorAddr & 0xFF);

/* Deselect the FLASH: Chip Select high */

SPI_FLASH_CS_HIGH();

}

/*brief Writes more than one byte to the FLASH with a single WRITE cycle */

void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)

{

/* Enable the write access to the FLASH */

SPI_FLASH_WriteEnable();

/* Select the FLASH: Chip Select low */

SPI_FLASH_CS_LOW();

/* Send “Write to Memory ” instruction */

SPI_FLASH_SendByte(PP);

/* Send WriteAddr high nibble address byte to write to */

SPI_FLASH_SendByte((WriteAddr & 0xFF0000) 》》 16);

/* Send WriteAddr medium nibble address byte to write to */

SPI_FLASH_SendByte((WriteAddr & 0xFF00) 》》 8);

/* Send WriteAddr low nibble address byte to write to */

SPI_FLASH_SendByte(WriteAddr & 0xFF);

while(NumByteToWrite--)

{

SPI_FLASH_SendByte(*pBuffer);

pBuffer++;

}

/* Deselect the FLASH: Chip Select high */

SPI_FLASH_CS_HIGH();

}

/*brief Writes block of data to the FLASH. In this function, the number of */

void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)

{

u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;

Addr = WriteAddr % SPI_FLASH_PAGESIZE;

count = SPI_FLASH_PAGESIZE - Addr;

NumOfPage = NumByteToWrite / SPI_FLASH_PAGESIZE;

NumOfSingle = NumByteToWrite % SPI_FLASH_PAGESIZE;

if (Addr == 0) /* WriteAddr is SPI_FLASH_PAGESIZE aligned */

{

if (NumOfPage == 0) /* NumByteToWrite 《 SPI_FLASH_PAGESIZE */

{

SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);

}

else /* NumByteToWrite 》 SPI_FLASH_PAGESIZE */

{

while (NumOfPage--)

{

SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PAGESIZE);

WriteAddr += SPI_FLASH_PAGESIZE;

pBuffer += SPI_FLASH_PAGESIZE;

}

SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);

}

}

else /* WriteAddr is not SPI_FLASH_PAGESIZE aligned */

{

if (NumOfPage == 0) /* NumByteToWrite 《 SPI_FLASH_PAGESIZE */

{

if (NumOfSingle 》 count) /* (NumByteToWrite + WriteAddr) 》 SPI_FLASH_PAGESIZE */

{

temp = NumOfSingle - count;

SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);

WriteAddr += count;

pBuffer += count;

SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);

}

else

{

SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);

}

}

else /* NumByteToWrite 》 SPI_FLASH_PAGESIZE */

{

NumByteToWrite -= count;

NumOfPage = NumByteToWrite / SPI_FLASH_PAGESIZE;

NumOfSingle = NumByteToWrite % SPI_FLASH_PAGESIZE;

SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);

WriteAddr += count;

pBuffer += count;

while (NumOfPage--)

{

SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PAGESIZE);

WriteAddr += SPI_FLASH_PAGESIZE;

pBuffer += SPI_FLASH_PAGESIZE;

}

if (NumOfSingle != 0)

{

SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);

}

}

}

}

/*brief Reads a block of data from the FLASH. */

void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)

{

/* Select the FLASH: Chip Select low */

SPI_FLASH_CS_LOW();

/* Send “Read from Memory ” instruction */

SPI_FLASH_SendByte(READ);

/* Send ReadAddr high nibble address byte to read from */

SPI_FLASH_SendByte((ReadAddr & 0xFF0000) 》》 16);

/* Send ReadAddr medium nibble address byte to read from */

SPI_FLASH_SendByte((ReadAddr& 0xFF00) 》》 8);

/* Send ReadAddr low nibble address byte to read from */

SPI_FLASH_SendByte(ReadAddr & 0xFF);

while (NumByteToRead--) /* while there is data to be read */

{

/* Read a byte from the FLASH */

*pBuffer = SPI_FLASH_SendByte(DUMMY_BYTE);

/* Point to the next location where the byte read will be saved */

pBuffer++;

}

/* Deselect the FLASH: Chip Select high */

SPI_FLASH_CS_HIGH();

}

/*brief Reads FLASH identification. */

u32 SPI_FLASH_ReadID(void)

{

u32 Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;

/* Select the FLASH: Chip Select low */

SPI_FLASH_CS_LOW();

/* Send “RDID ” instruction */

SPI_FLASH_SendByte(0x9F);

/* Read a byte from the FLASH */

Temp0 = SPI_FLASH_SendByte(DUMMY_BYTE);

/* Read a byte from the FLASH */

Temp1 = SPI_FLASH_SendByte(DUMMY_BYTE);

/* Read a byte from the FLASH */

Temp2 = SPI_FLASH_SendByte(DUMMY_BYTE);

/* Deselect the FLASH: Chip Select high */

SPI_FLASH_CS_HIGH();

Temp = (Temp0 《《 16) | (Temp1 《《 8) | Temp2;

return Temp;

}

四 主函數

void SPI1_Test(void)

{

/* Get SPI Flash ID */

FLASH_ID = SPI_FLASH_ReadID();

FLASH_ID = SPI_FLASH_ReadID();

if (FLASH_ID == M25P64_FLASH_ID)

{

/* Write Tx_Buffer data to SPI FLASH memory */

SPI_FLASH_BufferWrite(Tx_Buffer, FLASH_WriteAddress, BufferSize);

delay_ms(20);

DbgOutputstr(“Write message is ok!\r\n”);

/* Read data from SPI FLASH memory */

memset(Rx_Buffer,0,sizeof(Rx_Buffer));

SPI_FLASH_BufferRead(Rx_Buffer, FLASH_ReadAddress, BufferSize);

DbgOutputstr(“the message you write is:\r\n”);

DbgOutputstr((char *)Rx_Buffer);

DbgOutputstr(“\r\n”);//插入換行

/* Erase SPI FLASH Sector to write on */

SPI_FLASH_SectorErase(FLASH_SectorToErase);

delay_ms(10);

/* Read data from SPI FLASH memory No data -----Erase is ok */

memset(Rx_Buffer,0,sizeof(Rx_Buffer));

SPI_FLASH_BufferRead(Rx_Buffer, FLASH_ReadAddress, BufferSize);

DbgOutputstr(“the message you write is:\r\n”);

DbgOutputstr((char *)Rx_Buffer);

DbgOutputstr(“\r\n”);//插入換行

DbgOutputstr(“\r\n”);//插入換行

delay_ms(1000);

}

}


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • FlaSh
    +關注

    關注

    10

    文章

    1567

    瀏覽量

    146907
  • SPI
    SPI
    +關注

    關注

    17

    文章

    1625

    瀏覽量

    89981
收藏 人收藏

    評論

    相關推薦

    基于FPGA的SPI Flash控制器的設計方案

    傳統的Flash讀寫是通過CPU軟件編程實現,其讀寫速度較慢,且占用CPU資源,另外由于Flash芯片本身功能指令較多,使得對芯片進行直接操作變得非常困難。本文提出一個基于FPGA的
    發表于 09-24 09:12 ?5677次閱讀
    基于FPGA的<b class='flag-5'>SPI</b> <b class='flag-5'>Flash</b>控制器的設計方案

    STM32CubeMx入門教程(6):SPI讀寫FLAH的應用

    導語“本教程將使用CubeMX初始化SPI,使用SPI對W25Q64 FLASH進行讀寫操作,通過HAL庫的讀寫應用來數據
    發表于 07-12 11:32 ?1712次閱讀
    STM32CubeMx入門教程(6):<b class='flag-5'>SPI</b><b class='flag-5'>讀寫</b>FLAH的應用

    SPI如何讀寫串行FLASH?

    SPI有哪幾種通訊模式?SPI如何讀寫串行FLASH?
    發表于 02-17 07:50

    使用NUC970_NonOS_BSP中讀寫SPI Flash例程,SPI Flash讀寫失敗的原因?

    使用 NUC970_NonOS_BSP 中讀寫SPI Flash例程,操作SPI Flash(型:AT45DB041D),讀失敗,提示寫成功
    發表于 09-01 06:43

    基于紅牛開發板的spi flash讀寫圖片

    你的MCU上有外部總線接口,SPI flash就是通過SPI口對flash進行讀寫。速度上,總線flas
    發表于 09-01 17:16 ?16次下載
    基于紅牛開發板的<b class='flag-5'>spi</b> <b class='flag-5'>flash</b><b class='flag-5'>讀寫</b>圖片

    SPI flash是什么,關于SPI FLASH讀寫問題

    SPI一種通信接口。那么嚴格的來說SPI Flash是一種使用SPI通信的Flash,即,可能指NOR也可能是NAND。
    的頭像 發表于 09-18 14:38 ?10.2w次閱讀
    <b class='flag-5'>SPI</b> <b class='flag-5'>flash</b>是什么,關于<b class='flag-5'>SPI</b> <b class='flag-5'>FLASH</b>的<b class='flag-5'>讀寫</b>問題

    淺析spi flash驅動及其程序

    怎么用說白了對于Flash就是讀寫擦,也就是實現flash的驅動。先簡單了解下spi flash的物理連接。
    的頭像 發表于 10-07 11:26 ?1.8w次閱讀
    <b class='flag-5'>淺析</b><b class='flag-5'>spi</b> <b class='flag-5'>flash</b>驅動及其程序

    STM32F0xx_SPI讀寫(Flash) 配置詳細過程

    STM32F0xx_SPI讀寫(Flash)配置詳細過程
    的頭像 發表于 04-07 11:40 ?4819次閱讀
    STM32F0xx_<b class='flag-5'>SPI</b><b class='flag-5'>讀寫</b>(<b class='flag-5'>Flash</b>) 配置詳細過程

    STM32_ SPI讀寫Flash

    STM32_SPI讀寫Flash
    的頭像 發表于 04-08 10:26 ?5045次閱讀
    STM32_ <b class='flag-5'>SPI</b><b class='flag-5'>讀寫</b><b class='flag-5'>Flash</b>

    實現簡單的SPI讀寫FLASH

    實現簡單的SPI讀寫FLASH一、前言繼上篇文章SPI的相關知識,本章主要介紹使用SPI協議實現簡單的
    發表于 11-26 19:21 ?22次下載
    實現簡單的<b class='flag-5'>SPI</b><b class='flag-5'>讀寫</b><b class='flag-5'>FLASH</b>

    單片機學習筆記————STM32使用SPI讀寫串行Flash(三)

    第一步:讀寫相關函數在向 FLASH 芯片存儲矩陣寫入數據前,首先要使能寫操作,通過“Write Enable”命令即可寫使能。1.寫使能命令/** * @brief 向Flash發送寫使能命令
    發表于 12-22 19:15 ?4次下載
    單片機學習筆記————STM32使用<b class='flag-5'>SPI</b><b class='flag-5'>讀寫</b>串行<b class='flag-5'>Flash</b>(三)

    STM32F103學習筆記——SPI讀寫Flash(二)

    介紹1.軟件設計流程SPI讀寫Flash流程:初始化通訊引腳及端口時鐘;使能SPI時鐘;配置SPI結構體;編寫基本
    發表于 12-22 19:30 ?10次下載
    STM32F103學習筆記——<b class='flag-5'>SPI</b><b class='flag-5'>讀寫</b><b class='flag-5'>Flash</b>(二)

    SPI控制EF3內置FLASH讀寫

    電子發燒友網站提供《SPI控制EF3內置FLASH讀寫.pdf》資料免費下載
    發表于 09-27 10:19 ?1次下載
    <b class='flag-5'>SPI</b>控制EF3內置<b class='flag-5'>FLASH</b><b class='flag-5'>讀寫</b>

    SPI控制EF2內置FLASH讀寫

    電子發燒友網站提供《SPI控制EF2內置FLASH讀寫.pdf》資料免費下載
    發表于 09-26 15:16 ?3次下載
    <b class='flag-5'>SPI</b>控制EF2內置<b class='flag-5'>FLASH</b><b class='flag-5'>讀寫</b>

    基于FPGA的SPI Flash控制器的設計方案

    一個基于FPGA的SPI Flash讀寫硬件實現方案,該方案利用硬件對SPI Flash進行控制,能夠非常方便地完成
    的頭像 發表于 07-15 16:55 ?1474次閱讀
    基于FPGA的<b class='flag-5'>SPI</b> <b class='flag-5'>Flash</b>控制器的設計方案
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>