RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

STM32驅(qū)動(dòng)FLASH(W25Q64)

冬至子 ? 來(lái)源:TECHTIMES ? 作者:霽風(fēng)AI ? 2023-10-24 09:50 ? 次閱讀

1. 硬件連接

W25Q64 將 8M 的容量分為 128 個(gè)塊(Block) ,每個(gè)塊大小為 64K 字節(jié) ,每個(gè)塊又分為 16個(gè)扇區(qū)(Sector) ,每個(gè)扇區(qū) 4K 個(gè)字節(jié)

W25Q64 的 最少擦除單位為一個(gè)扇區(qū),也就是每次必須擦除 4K 個(gè)字節(jié)。 操作需要給 W25Q64 開(kāi)辟一個(gè)至少 4K 的緩存區(qū),對(duì) SRAM 要求比較高,要求芯片必須有 4K 以上 SRAM 才能很好的操作。

圖片

W25Q64 的擦寫周期多達(dá) 10W 次,具有 20 年的數(shù)據(jù)保存期限,支持電壓為 2.7~3.6V ,W25Q64 支持標(biāo)準(zhǔn)的 SPI,還支持雙輸出/四輸出的 SPI,最大 SPI 時(shí)鐘可以到 80Mhz(雙輸出時(shí)相當(dāng)于 160Mhz,四輸出時(shí)相當(dāng)于 320M)。

1.1 硬件連接

STM32 的引腳連接如下:這里是使用SPI1配置。

圖片

1.jpg

STM32 的 SPI 功能很強(qiáng)大, SPI 時(shí)鐘最多可以到 18Mhz,支持 DMA,可以配置為 SPI 協(xié)議或者 I2S 協(xié)議(僅大容量型號(hào)支持)。

1.2 SPI 通訊的通訊時(shí)序

SPI 協(xié)議定義了通訊的起始和停止信號(hào)、數(shù)據(jù)有效性、時(shí)鐘同步等環(huán)節(jié)。

我們以讀取 FLASH 的狀態(tài)寄存器的時(shí)序圖分析一下,時(shí)序圖也是書(shū)寫軟件模擬時(shí)序的依據(jù)。

圖片

如上圖,我們知道書(shū)寫 FLASH (來(lái)自華邦 W25X 手冊(cè))支持的是模式 0 (CPOL = 0 && CPHA == 0) 和 模式 3(CPOL = 1 && CPHA == 1)

CS、SCK、MOSI 信號(hào)都由主機(jī)控制產(chǎn)生,而 MISO 的信號(hào)由從機(jī)產(chǎn)生,主機(jī)通過(guò)該信號(hào)線讀取從機(jī)的數(shù)據(jù)。MOSI 與 MISO 的信號(hào)只在 CS 為低電平的時(shí)候才有效,在 SCK 的每個(gè)時(shí)鐘周期 MOSI 和 MISO 傳輸一位數(shù)據(jù)。

1.2.1. 通訊的起始和停止信號(hào)

在上圖,CS 信號(hào)線由高變低,為 SPI 通訊的起始信號(hào)。CS 是每個(gè)從機(jī)各自獨(dú)占的信號(hào)線,當(dāng)從機(jī)在自己的 CS 線檢測(cè)到起始信號(hào)后,就知道自己被主機(jī)選中了,開(kāi)始準(zhǔn)備與主機(jī)通訊。當(dāng) CS 信號(hào)由低變高,為 SPI 通訊的停止信號(hào),表示本次通訊結(jié)束,從機(jī)的選中狀態(tài)被取消。

1.2.2. 數(shù)據(jù)有效性

SPI 使用 MOSI 及 MISO 信號(hào)線來(lái)傳輸數(shù)據(jù),使用 SCK 信號(hào)線進(jìn)行數(shù)據(jù)同步。

圖片

MOSI 及 MISO 數(shù)據(jù)線在 SCK 的每個(gè)時(shí)鐘周期傳輸一位數(shù)據(jù)。數(shù)據(jù)傳輸時(shí),MSB 先行或 LSB 先行并沒(méi)有作硬性規(guī)定,但要保證兩個(gè) SPI 通訊設(shè)備之間使用同樣的協(xié)定,一般都會(huì)采用圖中的 MSB 先行模式。

觀察上圖,可知模式 0 和 3 都是在上升沿讀取數(shù)據(jù)。

示例:FLASH 讀取 JEDEC_ID (0x9F),SPI 模式 0,,頻率 f = 1MHz。

圖片

讀取 JEDEC_ID 時(shí),F(xiàn)LASH 回復(fù)的一個(gè)字:0xC8。

圖片

1.2.3 STM32 SPI外設(shè)

STM32 的 SPI 外設(shè)可用作通訊的主機(jī)及從機(jī),支持最高的 SCK 時(shí)鐘頻率為 f pclk / 2 (STM32F103 型號(hào)的芯片默認(rèn) f pclk1 為 72MHz,f pclk2 為 36MHz),完全支持 SPI 協(xié)議的 4 種模式,數(shù)據(jù)幀長(zhǎng)度可設(shè)置為 8 位或 16 位,可設(shè)置數(shù)據(jù) MSB 先行或 LSB 先行。它還支持雙線全雙工、雙線單向以及單線模式。

SPI架構(gòu):

圖片

通訊引腳 :

SPI 的所有硬件架構(gòu)都從上圖中左 MOSI、MISO、SCK及 NSS 線展開(kāi)的。

STM32 芯片有多個(gè) SPI 外設(shè),它們的 SPI 通訊信號(hào)引出到不同的 GPIO 引腳上,使用時(shí)必須配置到這些指定的引腳。

2. 軟件配置

這里使用 STM32 的 SPI1 的主模式,SPI 相關(guān)的庫(kù)函數(shù)和定義分布在文件 stm32f10x_spi.c 以及頭文件 stm32f10x_spi.h 中。

2.1 配置相關(guān)引腳的復(fù)用功能

第一步就要 使能 SPI1 的時(shí)鐘 , SPI1 的時(shí)鐘通過(guò) APB2ENR 的第 12 位來(lái)設(shè)置。其次要設(shè)置 SPI1 的相關(guān)引腳為 復(fù)用輸出 ,這樣才會(huì)連接到 SPI1 上否則這些 IO 口還是默認(rèn)的狀態(tài),也就是標(biāo)準(zhǔn)輸入輸出口。這里我們使用的是 PA5、 PA6、 PA7 這 3 個(gè)(SCK、 MISO、 MOSI、CS 使用軟件管理方式),所以設(shè)置這三個(gè)為 復(fù)用 IO 。

宏定義:

#define SPIM1_GPIO_PORT        GPIOA

#define SPIM1_CLK_IO    (GPIO_Pin_5)
#define SPIM1_MISO_IO    (GPIO_Pin_6)
#define SPIM1_MOSI_IO    (GPIO_Pin_7)

#define FLASH_CS_IO             (GPIO_Pin_2)
#define FLASH_CS_0()            (GPIO_ResetBits(SPIM1_GPIO_PORT, FLASH_CS_IO))      
#define FLASH_CS_1()             (GPIO_SetBits(SPIM1_GPIO_PORT, FLASH_CS_IO))

#define RCC_PCLK_SPIM1_GPIO     RCC_APB2Periph_GPIOA
#define RCC_PCLK_SPIM1_HD       RCC_APB2Periph_SPI1

IO 配置:

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: spi_gpio_init
//    功能說(shuō)明: SPI 硬件IO初始化
//    形    參:     spi_chl:SPIM 通道
//    返 回 值: 無(wú)
//    日    期: 2020-03-12
//    備    注:采用 Unix like 方式
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void spi_gpio_init(uint8_t spi_chl)
{
    GPIO_InitTypeDef gpio_config_init;

    if (spi_chl == 1)
    {
        RCC_APB2PeriphClockCmd(RCC_PCLK_SPIM1_GPIO, ENABLE);        //開(kāi)啟SPIM1 GPIO時(shí)鐘、

//        gpio_config_init.GPIO_Pin       = SPIM1_CLK_IO | SPIM1_MISO_IO | SPIM1_MOSI_IO; //SPIM1_CLK_IO IO初始化
        gpio_config_init.GPIO_Pin       = SPIM1_CLK_IO | SPIM1_MOSI_IO;
        gpio_config_init.GPIO_Mode      = GPIO_Mode_AF_PP;  //復(fù)用推挽輸出
        gpio_config_init.GPIO_Speed     = GPIO_Speed_50MHz;

        GPIO_Init(SPIM1_GPIO_PORT, &gpio_config_init);

        gpio_config_init.GPIO_Pin       = SPIM1_MISO_IO;    //SPIM1_MISO_IO IO初始化
        gpio_config_init.GPIO_Mode      = GPIO_Mode_IN_FLOATING;  //MISO浮空輸入
        gpio_config_init.GPIO_Speed     = GPIO_Speed_50MHz;
        GPIO_Init(SPIM1_GPIO_PORT, &gpio_config_init);

        GPIO_SetBits(SPIM1_GPIO_PORT, SPIM1_CLK_IO | SPIM1_MISO_IO | SPIM1_MOSI_IO);    //IO初始狀態(tài)都設(shè)置為高電平
    }       
}

2.2 初始化 SPI1,設(shè)置 SPI1 工作模式

接下來(lái)初始化 SPI1,設(shè)置 SPI1 為主機(jī)模式,設(shè)置數(shù)據(jù)格式為 8 位,然設(shè)置 SCK 時(shí)鐘極性及采樣方式。并設(shè)置 SPI1 的時(shí)鐘頻率(最大 18Mhz),以及數(shù)據(jù)的格式(MSB 在前還是 LSB 在前)。這在庫(kù)函數(shù)中是通過(guò) SPI_Init 函數(shù)來(lái)實(shí)現(xiàn)。

函數(shù)原型:

void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);

第一個(gè)參數(shù)是 SPI 標(biāo)號(hào),第二個(gè)參數(shù)結(jié)構(gòu)體類型 SPI_InitTypeDef 為相關(guān)屬性設(shè)置。

SPI_InitTypeDef 的定義如下:

typedef struct
{
uint16_t SPI_Direction;
uint16_t SPI_Mode;
uint16_t SPI_DataSize;
uint16_t SPI_CPOL;
uint16_t SPI_CPHA;
uint16_t SPI_NSS;
uint16_t SPI_BaudRatePrescaler;
uint16_t SPI_FirstBit;
uint16_t SPI_CRCPolynomial;
}SPI_InitTypeDef;

1.jpg

初始化的范例格式為:

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: spi_master_init
//    功能說(shuō)明: SPI 硬件配置參數(shù)初始化
//    形    參:     spi_chl:SPIM 通道
//    返 回 值: 無(wú)
//    日    期: 2020-03-12
//    備    注:采用 Unix like 方式
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void spi_master_init(uint8_t spi_chl)
{
    SPI_InitTypeDef  spi_config_init;
#if 1  
    if(spi_chl == 1)
    {   
        spi_flash_gpio_init();  //spi flash cs 初始化
//        sd_gpio_init(); //spi sd cs 初始化
//        nrf24l01_gpio_init();//spi nrf24l01 cs 初始化

        spi_gpio_init(1);   //spi gpio 初始化

        RCC_APB2PeriphClockCmd(RCC_PCLK_SPIM1_HD, ENABLE);  //SPI1時(shí)鐘使能

        spi_config_init.SPI_Direction           = SPI_Direction_2Lines_FullDuplex;  //設(shè)置SPI單向或者雙向的數(shù)據(jù)模式:SPI設(shè)置為雙線雙向全雙工
        spi_config_init.SPI_Mode                = SPI_Mode_Master;      //設(shè)置SPI工作模式:設(shè)置為主SPI
        spi_config_init.SPI_DataSize            = SPI_DataSize_8b;      //設(shè)置SPI的數(shù)據(jù)大小:SPI發(fā)送接收8位幀結(jié)構(gòu)
        spi_config_init.SPI_CPOL                = SPI_CPOL_Low;     //選擇了串行時(shí)鐘的穩(wěn)態(tài):空閑時(shí)鐘低
        spi_config_init.SPI_CPHA                = SPI_CPHA_1Edge;   //數(shù)據(jù)捕獲(采樣)于第1個(gè)時(shí)鐘沿
        spi_config_init.SPI_NSS                 = SPI_NSS_Soft;//SPI_NSS_Soft;      //NSS信號(hào)由硬件(NSS管腳)還是軟件(使用SSI位)管理:內(nèi)部NSS信號(hào)有SSI位控制
        spi_config_init.SPI_BaudRatePrescaler   = SPI_BaudRatePrescaler_256;        //定義波特率預(yù)分頻的值:波特率預(yù)分頻值為256
        spi_config_init.SPI_FirstBit            = SPI_FirstBit_MSB; //指定數(shù)據(jù)傳輸從MSB位還是LSB位開(kāi)始:數(shù)據(jù)傳輸從MSB位開(kāi)始
        spi_config_init.SPI_CRCPolynomial       = 7;    //CRC值計(jì)算的多項(xiàng)式

        SPI_Init(SPI1, &spi_config_init);  //根據(jù)SPI_InitStruct中指定的參數(shù)初始化外設(shè)SPIx寄存器

        SPI_Cmd(SPI1, ENABLE); //使能SPI外設(shè)

//        spi_master_send_recv_byte(1, 0xFF); //啟動(dòng)傳輸  

    }
#endif
}

2.3 SPI 傳輸數(shù)據(jù)

通信接口需要有發(fā)送數(shù)據(jù)和接受數(shù)據(jù)的函數(shù),固件庫(kù)提供的發(fā)送數(shù)據(jù)函數(shù)原型為:

void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);

往 SPIx 數(shù)據(jù)寄存器寫入數(shù)據(jù) Data,從而實(shí)現(xiàn)發(fā)送。

固件庫(kù)提供的接受數(shù)據(jù)函數(shù)原型為:

uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) ;

這從 SPIx 數(shù)據(jù)寄存器讀出接收到的數(shù)據(jù)。

收發(fā)單個(gè)字節(jié)數(shù)據(jù):

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: spi_master_send_recv_byte
//    功能說(shuō)明: SPI 收發(fā)數(shù)據(jù)
//    形    參:     spi_chl:SPIM 通道
//                send_byte:發(fā)送的數(shù)據(jù)
//    返 回 值: 無(wú)
//    日    期: 2020-03-14
//    備    注:采用 Unix like 方式
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
uint8_t spi_master_send_recv_byte(uint8_t spi_chl, uint8_t spi_byte)
{        
    uint8_t time = 0;

    if (spi_chl == 1)               
    {
        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //檢查指定的SPI標(biāo)志位設(shè)置與否:發(fā)送緩存空標(biāo)志位
        {
            time++;
            if(time >200)
            {
                return false;
            }
        }             
        SPI_I2S_SendData(SPI1, spi_byte); //通過(guò)外設(shè)SPIx發(fā)送一個(gè)數(shù)據(jù)

        time = 0;

        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)//檢查指定的SPI標(biāo)志位設(shè)置與否:接受緩存非空標(biāo)志位
        {
            time++;
            if(time >200)
            {
                return false;
            }
        }                               
            return SPI_I2S_ReceiveData(SPI1); //返回通過(guò)SPIx最近接收的數(shù)據(jù) 
    }
    else 
    {
        return false;
    }
}

收發(fā)多個(gè)字節(jié)數(shù)據(jù):

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: spi_master_send_some_bytes
//    功能說(shuō)明: SPI 發(fā)送多個(gè)字節(jié)數(shù)據(jù)
//    形    參:     spi_chl:SPIM 通道
//                pbdata:發(fā)送的數(shù)據(jù)首地址
//                send_length:發(fā)送數(shù)據(jù)長(zhǎng)度
//    返 回 值: 無(wú)
//    日    期: 2020-03-12
//    備    注:采用 Unix like 方式
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void spi_master_send_some_bytes(uint8_t spi_chl, uint8_t *pbdata, uint16_t send_length)
{
    uint16_t i = 0;

    for (i = 0; i < send_length; i++)
    {
        spi_master_send_recv_byte(spi_chl, pbdata[i]);
    }

//    while (send_length--)
//    {
//        spi_master_send_byte(spi_chl, *pbdata++);
//    }

}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: spi_master_recv_some_bytes
//    功能說(shuō)明: SPI 接收多個(gè)字節(jié)數(shù)據(jù)
//    形    參:     spi_chl:SPIM 通道
//                pbdata:接收的數(shù)據(jù)首地址
//                send_length:接收數(shù)據(jù)長(zhǎng)度
//    返 回 值: 無(wú)
//    日    期: 2020-03-12
//    備    注:采用 Unix like 方式
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void spi_master_recv_some_bytes(uint8_t spi_chl, uint8_t *pbdata, uint16_t recv_length)
{
    uint8_t *temp_data = pbdata;

    while (recv_length--)
    {
        *temp_data++ = spi_master_send_recv_byte(spi_chl, 0xFF);    //發(fā)送 0xff 為從設(shè)備提供時(shí)鐘
    }

}

2.4 查看 SPI 傳輸狀態(tài)

在 SPI 傳輸過(guò)程中,要判斷數(shù)據(jù)是否傳輸完成,發(fā)送區(qū)是否為空等等狀態(tài),
通過(guò)函數(shù) SPI_I2S_GetFlagStatus 實(shí)現(xiàn)的,判斷發(fā)送是否完成的方法是:

SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE);

3. SPI FLASH 操作

3.1 宏定義部分

#define  FLASH_WRITE_ENABLE_CMD         0x06
#define  FLASH_WRITE_DISABLE_CMD        0x04
#define  FLASH_READ_SR_CMD                0x05
#define  FLASH_WRITE_SR_CMD                0x01
#define  FLASH_READ_DATA                0x03
#define  FLASH_FASTREAD_DATA            0x0b
#define  FLASH_WRITE_PAGE                0x02
#define  FLASH_ERASE_PAGE                  0x81
#define  FLASH_ERASE_SECTOR               0x20
#define     FLASH_ERASE_BLOCK              0xd8
#define     FLASH_ERASE_CHIP               0xc7
#define  FLASH_POWER_DOWN                0xb9
#define  FLASH_RELEASE_POWER_DOWN       0xab
#define  FLASH_READ_DEVICE_ID              0x90
#define  FLASH_READ_JEDEC_ID              0x9f

#define     FLASH_SIZE   (1*1024*1024)  // 1M字節(jié)
#define        PAGE_SIZE           8192    // 256 bytes
#define     SECTOR_SIZE     512  // 4-Kbyte
#define        BLOCK_SIZE      32  // 64-Kbyte 

#define PAGE_LEN        255  //一頁(yè)256字節(jié)

3.2 中間層函數(shù)封裝

注明: 此部分函數(shù)的封裝是為了統(tǒng)一硬件 SPI 和軟件模擬 SPI 接口。

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: hal_spi_send_bytes
//    功能說(shuō)明: SPI 發(fā)送數(shù)據(jù),包含軟件和硬件通信方式
//    形    參:     mode:通信方式選擇(0:軟件SPI;1:硬件SPI)
//                pbdata:發(fā)送數(shù)據(jù)的首地址
//                send_length:發(fā)送數(shù)據(jù)長(zhǎng)度
//    返 回 值: 執(zhí)行狀態(tài)(true or false)
//    日    期: 2020-03-12
//    備    注: 中間層封裝底層接口
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
uint8_t hal_spi_send_bytes(uint8_t mode, uint8_t *pbdata, uint16_t send_length)
{
    if (mode == 0)
    {
        for (uint16_t i = 0; i < send_length; i++)
        {
            Spi_WriteByte(pbdata[i]);
        }

        return true;
    }
    else if (mode == 1)
    {
        spi_master_send_some_bytes(1, pbdata, send_length);

//        for (uint16_t i = 0; i < send_length; i++)
//        {
//            spi_master_send_recv_byte(1, pbdata[i]);
//        }

        return true;
    }
    else 
    {
        return false;
    }

}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: hal_spi_recv_bytes
//    功能說(shuō)明: SPI 接收數(shù)據(jù),包含軟件和硬件通信方式
//    形    參:     mode:通信方式選擇(0:軟件SPI;1:硬件SPI)
//                pbdata:發(fā)送數(shù)據(jù)的首地址
//                send_length:發(fā)送數(shù)據(jù)長(zhǎng)度
//    返 回 值: 執(zhí)行狀態(tài)(true or false)
//    日    期: 2020-03-12
//    備    注: 中間層封裝底層接口
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
uint8_t hal_spi_recv_bytes(uint8_t mode, uint8_t *pbdata, uint16_t recv_length)
{
    if (mode == 0)
    {
        for (uint16_t i = 0; i < recv_length; i++)
        {
             *pbdata++ = Spi_ReadByte();    //軟件模擬SPI
        }   

        return true;
    }
    else if (mode == 1)
    {
        spi_master_recv_some_bytes(1, pbdata, recv_length);    //硬件SPI

//        for (uint16_t i = 0; i < recv_length; i++)
//        {
//            *pbdata++ = spi_master_send_recv_byte(1, 0xFF);
//        }

        return true;
    }
    else 
    {
        return false;
    }

}

3.3 FLASH 部分

__align(4) uint8_t g_DataTmpBuffer[0x1000] = {0};

#define SectorBuf  g_DataTmpBuffer

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_WriteEnable
//    功能說(shuō)明: 寫使能,置位 WEL 位 WEL 位(WEL-- >1)
//    形    參: 無(wú)
//    返 回 值: 無(wú)
//    日    期: 2020-03-07
//    備    注: 
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_WriteEnable(void)
{
    uint8_t command = FLASH_WRITE_ENABLE_CMD;

    FLASH_CS_LOW;
    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);//開(kāi)啟寫使能
    FLASH_CS_HIGH;
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_WriteDisable
//    功能說(shuō)明: 寫失能,復(fù)位 WEL 位(WEL-- >0)
//    形    參: 無(wú)
//    返 回 值: 無(wú)
//    日    期: 2020-03-07
//    備    注: 
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_WriteDisable(void)
{
    uint8_t command = FLASH_WRITE_DISABLE_CMD;
    FLASH_CS_LOW;
    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
    // Spi_WriteByte(FLASH_WRITE_DISABLE_CMD);  //開(kāi)啟寫失能 04h
    FLASH_CS_HIGH;
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_WriteSR
//    功能說(shuō)明: 讀狀態(tài)寄存器
//    形    參: 無(wú)
//    返 回 值: 無(wú)
//    日    期: 2020-03-07
//    備    注: 多用于檢查 BUSY 位
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
uint8_t Flash_ReadSR(void)
{
    uint8_t ucTmpVal = 0;
    uint8_t command = FLASH_READ_SR_CMD;

    FLASH_CS_LOW;

    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1); //05h
    hal_spi_recv_bytes(SPI_COMM_MODE, &ucTmpVal, 1);

    // ucTmpVal = Spi_ReadByte();

    FLASH_CS_HIGH;

    return ucTmpVal;
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_WriteSR
//    功能說(shuō)明: 寫狀態(tài)寄存器
//    形    參:     _ucByte:寫入狀態(tài)寄存器的數(shù)值
//    返 回 值: no
//    日    期: 2020-03-07
//    備    注: 
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_WriteSR(uint8_t _ucByte)
{
    uint8_t command = FLASH_WRITE_SR_CMD;

    Flash_WriteEnable();    
    Flash_WaitNobusy();

    FLASH_CS_LOW;
    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1); //01h
    hal_spi_send_bytes(SPI_COMM_MODE, &_ucByte, 1); //寫入一個(gè)字節(jié)
    FLASH_CS_HIGH;
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_WaitNobusy
//    功能說(shuō)明: 檢查 FLASH BUSY 位狀態(tài)
//    形    參: no
//    返 回 值: no
//    日    期: 2020-03-07
//    備    注: 調(diào)用Flash_ReadSR(),判斷狀態(tài)寄存器的R0位,執(zhí)行結(jié)束操作清零
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_WaitNobusy(void)
{
    //FLASH_READ_SR_CMD 指令的發(fā)送,有的FLASH僅需發(fā)送一次,FLASH自動(dòng)回復(fù),有的FLASH無(wú)法自動(dòng)回復(fù),需要循環(huán)一直發(fā)送等待
    while(((Flash_ReadSR()) & 0x01)==0x01); //等待BUSY位清空
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_FastReadByte
//    功能說(shuō)明: flash 都數(shù)據(jù)(快速讀取:Fast read operate at the highest poossible frequency)
//    形    參:     ucpBuffer:數(shù)據(jù)存儲(chǔ)區(qū)首地址
//                _ulReadAddr: 要讀出Flash的首地址
//                _usNByte: 要讀出的字節(jié)數(shù)(最大65535B)
//    返 回 值: no
//    日    期: 2020-03-07
//    備    注: 從_ulReadAddr地址,連續(xù)讀出_usNByte長(zhǎng)度的字節(jié)
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_ReadSomeBytes(uint8_t *ucpBuffer, uint32_t _ulReadAddr, uint16_t _usNByte)
{
    uint8_t command = FLASH_READ_DATA;
    uint8_t temp_buff[3] = {0};

    temp_buff[0] = (uint8_t)(_ulReadAddr > > 16);
    temp_buff[1] = (uint8_t)(_ulReadAddr > > 8);
    temp_buff[2] = (uint8_t)(_ulReadAddr > > 0);

    FLASH_CS_LOW;

    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
    hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[0], 1);
    hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[1], 1);
    hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[2], 1);

    hal_spi_recv_bytes(SPI_COMM_MODE, ucpBuffer, _usNByte);

    // Spi_WriteByte(FLASH_READ_DATA);  //連續(xù)讀取數(shù)據(jù) 03h
    // Spi_WriteByte((uint8_t)(_ulReadAddr >>16));   //寫入24位地址
    // Spi_WriteByte((uint8_t)(_ulReadAddr >>8));
    // Spi_WriteByte((uint8_t)(_ulReadAddr >>0));

    // while(_usNByte--)
    // {
    //  *ucpBuffer = Spi_ReadByte();
    //  ucpBuffer++;
    // }

    FLASH_CS_HIGH;
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_FastReadByte
//    功能說(shuō)明: flash 都數(shù)據(jù)(快速讀?。篎ast read operate at the highest poossible frequency)
//    形    參:     ucpBuffer:數(shù)據(jù)存儲(chǔ)區(qū)首地址
//                _ulReadAddr: 要讀出Flash的首地址
//                _usNByte: 要讀出的字節(jié)數(shù)(最大65535B)
//    返 回 值: no
//    日    期: 2020-03-07
//    備    注: 從_ulReadAddr地址,連續(xù)讀出_usNByte長(zhǎng)度的字節(jié)
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_FastReadByte(uint8_t *ucpBuffer, uint32_t _ulReadAddr, uint16_t _usNByte)
{
    uint8_t command = FLASH_FASTREAD_DATA;
    uint8_t temp_buff[3] = {0};

    temp_buff[0] = (uint8_t)(_ulReadAddr > > 16);
    temp_buff[1] = (uint8_t)(_ulReadAddr > > 8);
    temp_buff[2] = (uint8_t)(_ulReadAddr > > 0);

    FLASH_CS_LOW;

    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
    hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[0], 1);
    hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[1], 1);
    hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[2], 1);

    hal_spi_recv_bytes(SPI_COMM_MODE, ucpBuffer, _usNByte);

    // Spi_WriteByte(FLASH_FASTREAD_DATA);//快速讀取數(shù)據(jù) 0bh
    // Spi_WriteByte((uint8_t)(_ulReadAddr >>16));//寫入24位地址
    // Spi_WriteByte((uint8_t)(_ulReadAddr >>8));
    // Spi_WriteByte((uint8_t)(_ulReadAddr >>0));
    // Spi_WriteByte(0xFF);//等待8個(gè)時(shí)鐘(dummy byte)
    // while(_usNByte--)
    // {
    //  *ucpBuffer = Spi_ReadByte();
    //  ucpBuffer++;
    // }

    FLASH_CS_HIGH;
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_WritePage
//    功能說(shuō)明: flash 寫數(shù)據(jù)(按頁(yè)寫入,一頁(yè)256字節(jié),寫入之前FLASH地址上必須為0xFF)
//    形    參:     ucpBuffer:數(shù)據(jù)存儲(chǔ)區(qū)首地址
//                _ulWriteAddr: 要讀寫入Flash的首地址
//                _usNByte: 要寫入的字節(jié)數(shù)(最大65535B = 64K 塊)
//    返 回 值: no
//    日    期: 2020-03-07
//    備    注: _ulWriteAddr,連續(xù)寫入_usNByte長(zhǎng)度的字節(jié)
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_WritePage(uint8_t *ucpBuffer, uint32_t _ulWriteAddr, uint16_t _usNByte)
{
    uint8_t command = FLASH_WRITE_PAGE;
    uint8_t temp_buff[3] = {0};

    temp_buff[0] = (uint8_t)(_ulWriteAddr > > 16);
    temp_buff[1] = (uint8_t)(_ulWriteAddr > > 8);
    temp_buff[2] = (uint8_t)(_ulWriteAddr > > 0);

    Flash_WriteEnable();    //寫使能
    Flash_WaitNobusy(); //等待寫入結(jié)束

    FLASH_CS_LOW;

    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
    hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[0], 1);
    hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[1], 1);
    hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[2], 1);

    hal_spi_send_bytes(SPI_COMM_MODE, ucpBuffer, _usNByte);

    // Spi_WriteByte(FLASH_WRITE_PAGE); //02h
    // Spi_WriteByte((uint8_t)(_ulWriteAddr >>16));  //寫入24位地址
    // Spi_WriteByte((uint8_t)(_ulWriteAddr >>8));
    // Spi_WriteByte((uint8_t)(_ulWriteAddr >>0));
    // while(_usNByte--)
    // {
    //  Spi_WriteByte(*ucpBuffer);  //SPI 寫入單個(gè)字節(jié)
    //  ucpBuffer++;
    // }

    FLASH_CS_HIGH;

    Flash_WaitNobusy(); //等待寫入結(jié)束
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_WriteNoCheck
//    功能說(shuō)明: flash 寫數(shù)據(jù)(不帶擦除,寫入之前必須確保寫入部分FLASH的數(shù)據(jù)全為0xFf,否則寫入失敗)
//    形    參:     ucpBuffer:數(shù)據(jù)存儲(chǔ)區(qū)首地址
//                _ulWriteAddr: 要讀寫入Flash的首地址
//                _usNByte: 要寫入的字節(jié)數(shù)(最大65535B = 64K 塊)
//    返 回 值: no
//    日    期: 2020-03-07
//    備    注: _ulWriteAddr,連續(xù)寫入_usNByte長(zhǎng)度的字節(jié),程序帶FLASH數(shù)據(jù)檢查寫入
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_WriteNoCheck(uint8_t *ucpBuffer, uint32_t _ulWriteAddr, uint16_t _usNByte)
{
    uint16_t PageByte = 256 - _ulWriteAddr % 256;//單頁(yè)剩余可寫字節(jié)數(shù)

    if(_usNByte <= PageByte)    //不大于256字節(jié)
    {
        PageByte = _usNByte;
    }

    while(1)
    {
        Flash_WritePage(ucpBuffer, _ulWriteAddr, PageByte);
        if(_usNByte == PageByte)    //寫入結(jié)束
            break;
        else
        {
            ucpBuffer += PageByte;  //下一頁(yè)寫入的數(shù)據(jù)
            _ulWriteAddr += PageByte;   //下一頁(yè)寫入的地址
            _usNByte -= PageByte;   //待寫入的字節(jié)數(shù)遞減
            if(_usNByte > 256)
            {
                PageByte = 256;
            }
            else
            {
                PageByte = _usNByte;
            }
        }
    }
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_WriteSomeBytes
//    功能說(shuō)明: flash 寫數(shù)據(jù)
//    形    參:     ucpBuffer:數(shù)據(jù)存儲(chǔ)區(qū)首地址
//                _ulWriteAddr: 要讀寫入Flash的首地址
//                _usNByte: 要寫入的字節(jié)數(shù)(最大65535B = 64K 塊)
//    返 回 值: no
//    日    期: 2020-03-07
//    備    注: _ulWriteAddr,連續(xù)寫入_usNByte長(zhǎng)度的字節(jié),程序帶FLASH數(shù)據(jù)檢查寫入
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_WriteSomeBytes(uint8_t *ucpBuffer, uint32_t _ulWriteAddr, uint16_t _usNByte)
{
    uint32_t ulSecPos = 0;              //得到扇區(qū)位置
    uint16_t usSecOff = 0;              //扇區(qū)偏移
    uint16_t usSecRemain = 0;       //剩余扇區(qū)
    uint32_t i = 0;

    ulSecPos = _ulWriteAddr / 4096;//地址所在扇區(qū)(0--511)
    usSecOff = _ulWriteAddr % 4096;//扇區(qū)內(nèi)地址偏移
    usSecRemain = 4096 - usSecOff;//扇區(qū)除去偏移,還剩多少字節(jié)

    if(_usNByte <= usSecRemain) //寫入數(shù)據(jù)大小 < 剩余扇區(qū)空間大小
    {
        usSecRemain = _usNByte;
    }

    while(1)
    {
        Flash_ReadSomeBytes(SectorBuf, ulSecPos*4096, 4096);//讀出整個(gè)扇區(qū)的內(nèi)容
        for (i = 0; i < usSecRemain; i++)   //校驗(yàn)數(shù)據(jù)
        {
            if (SectorBuf[usSecOff + i] != 0xFF)//儲(chǔ)存數(shù)據(jù)不為0xFF,需要擦除
                break;
        }

        if(i < usSecRemain) //需要擦除
        {
            Flash_EraseSector(ulSecPos);    //擦除這個(gè)扇區(qū)
            for(i = 0; i < usSecRemain; i++)    //保存寫入的數(shù)據(jù)
            {
                SectorBuf[usSecOff + i] = ucpBuffer[i];
            }
            Flash_WriteNoCheck(SectorBuf, ulSecPos*4096, 4096); //寫入整個(gè)扇區(qū)(扇區(qū)=老數(shù)據(jù)+新寫入數(shù)據(jù))
        }
        else
        {
            Flash_WriteNoCheck(ucpBuffer, _ulWriteAddr, usSecRemain);//不需要擦除,直接寫入扇區(qū)
        }
        if(_usNByte == usSecRemain) //寫入結(jié)束
        {
            Flash_WriteDisable();
            break;
        }
        else
        {
            ulSecPos++;     //扇區(qū)地址增加1
            usSecOff = 0;       //扇區(qū)偏移歸零
            ucpBuffer += usSecRemain;   //指針偏移
            _ulWriteAddr += usSecRemain;    //寫地址偏移
            _usNByte -= usSecRemain;    //待寫入的字節(jié)遞減

            if(_usNByte > 4096)
            {
                usSecRemain = 4096; //待寫入一扇區(qū)(4096字節(jié)大小)
            }
            else
            {
                usSecRemain = _usNByte;     //待寫入少于一扇區(qū)的數(shù)據(jù)
            }
        }

    }

}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_ErasePage
//    功能說(shuō)明: flash erase page
//    形    參: no
//    返 回 值: no
//    日    期: 2020-03-07
//    備    注: 有的 FLASH 支持
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_ErasePage(uint32_t _ulPageAddr)
{
    _ulPageAddr *= 256;

    Flash_WriteEnable();
    Flash_WaitNobusy();

    FLASH_CS_LOW;
    Spi_WriteByte(FLASH_ERASE_PAGE);    //頁(yè)擦除指令
    Spi_WriteByte((uint8_t)(_ulPageAddr >>16));  //寫入24位地址
    Spi_WriteByte((uint8_t)(_ulPageAddr >>8));
    Spi_WriteByte((uint8_t)(_ulPageAddr >>0));
    FLASH_CS_HIGH;

    Flash_WaitNobusy(); //等待寫入結(jié)束
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_EraseSector
//    功能說(shuō)明: flash erase sector
//    形    參: no
//    返 回 值: no
//    日    期: 2020-03-07
//    備    注: 1扇區(qū) = 4K Bytes
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_EraseSector(uint32_t _ulSectorAddr)
{
    uint8_t command = FLASH_ERASE_SECTOR;
    uint8_t temp_buff[3] = {0};

    temp_buff[0] = (uint8_t)(_ulSectorAddr > > 16);
    temp_buff[1] = (uint8_t)(_ulSectorAddr > > 8);
    temp_buff[2] = (uint8_t)(_ulSectorAddr > > 0);

    _ulSectorAddr *= 4096;  //1個(gè)扇區(qū) 4 KBytes

    Flash_WriteEnable();
    Flash_WaitNobusy();

    FLASH_CS_LOW;
    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
    hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[0], 1);
    hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[1], 1);
    hal_spi_send_bytes(SPI_COMM_MODE, &temp_buff[2], 1);


//    Spi_WriteByte(FLASH_ERASE_SECTOR);  //20h
//    Spi_WriteByte((uint8_t)(_ulSectorAddr >>16));    //寫入24位地址
//    Spi_WriteByte((uint8_t)(_ulSectorAddr >>8));
//    Spi_WriteByte((uint8_t)(_ulSectorAddr));
    FLASH_CS_HIGH;

    Flash_WaitNobusy(); //等待寫入結(jié)束
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_EraseBlock
//    功能說(shuō)明: flash erase block 
//    形    參: no
//    返 回 值: no
//    日    期: 2020-03-07
//    備    注: 1塊 = 64K Bytes
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_EraseBlock(uint32_t _ulBlockAddr)
{
    uint8_t command = FLASH_ERASE_BLOCK;
    _ulBlockAddr *= 65536;  //塊地址,一塊64K

    Flash_WriteEnable();
    Flash_WaitNobusy();

    FLASH_CS_LOW;
    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
    hal_spi_send_bytes(SPI_COMM_MODE, (uint8_t *)(_ulBlockAddr >>16), 1);
    hal_spi_send_bytes(SPI_COMM_MODE, (uint8_t *)(_ulBlockAddr >>8), 1);
    hal_spi_send_bytes(SPI_COMM_MODE, (uint8_t *)(_ulBlockAddr >>0), 1);

    // Spi_WriteByte(FLASH_ERASE_BLOCK);    //d8h
    // Spi_WriteByte((uint8_t)(_ulBlockAddr >>16));  //寫入24位地址
    // Spi_WriteByte((uint8_t)(_ulBlockAddr >>8));
    // Spi_WriteByte((uint8_t)(_ulBlockAddr));
    FLASH_CS_HIGH;

    Flash_WaitNobusy(); //等待寫入結(jié)束
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_EraseChip
//    功能說(shuō)明: flash erase chip , it makes flash  recovery FF
//    形    參: no
//    返 回 值: no
//    日    期: 2020-03-07
//    備    注: 軟件模擬SPI
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_EraseChip(void)
{
    uint8_t command = FLASH_ERASE_CHIP;

    Flash_WriteEnable();    //flash芯片寫使能
    Flash_WaitNobusy(); //等待寫操作完成

    FLASH_CS_LOW;
    hal_spi_recv_bytes(SPI_COMM_MODE, &command, 1);
    // Spi_WriteByte(FLASH_ERASE_CHIP); //c7h
    FLASH_CS_HIGH;

    Flash_WaitNobusy(); //等待寫入結(jié)束
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_PowerDown
//    功能說(shuō)明: flash into power down mode 
//    形    參: no
//    返 回 值: no
//    日    期: 2020-03-07
//  備    注: 軟件模擬SPI
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_PowerDown(void)
{
    uint8_t command = FLASH_POWER_DOWN; 

    FLASH_CS_LOW;
    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
    // Spi_WriteByte(FLASH_POWER_DOWN); //b9h
    FLASH_CS_HIGH;
    Sys_delay_us(3);    // cs go high , need to delay 3us
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_WakeUp
//    功能說(shuō)明: wake up flash from power down mode or hign performance mode
//    形    參: no
//    返 回 值: no
//    日    期: 2020-03-07
//    備    注: 軟件模擬SPI
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
void Flash_WakeUp(void)
{
    uint8_t command = FLASH_RELEASE_POWER_DOWN; 

    FLASH_CS_LOW;
    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1);
    // Spi_WriteByte(FLASH_RELEASE_POWER_DOWN);//abh
    FLASH_CS_HIGH;
    Sys_delay_us(3);    //CS go high , need delay 3us
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_ReadDeviceID
//    功能說(shuō)明: 讀取FLASH ID(manufacturer ID-1Byte + Device ID-2Byte:type+density)
//    形    參: 無(wú)
//    返 回 值: ulJedId:FLASH ID 3字節(jié)
//    日    期: 2020-03-06
//    備    注: 軟件模擬SPI
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
uint16_t Flash_ReadDeviceID(void)
{
    uint8_t command = FLASH_READ_DEVICE_ID;
    uint16_t usFlashId = 0;
    uint8_t temp_buff[3] = {0};

    FLASH_CS_LOW;

    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1); //90h
    hal_spi_send_bytes(SPI_COMM_MODE, temp_buff, 3);    //寫入24位地址;假地址
    hal_spi_recv_bytes(SPI_COMM_MODE, temp_buff, 2);

    // Spi_WriteByte(FLASH_READ_DEVICE_ID); //90h
    // Spi_WriteByte(0x00);//寫入24位地址;假地址
    // Spi_WriteByte(0x00);
    // Spi_WriteByte(0x00); //如果0x01,先輸出 Device ID
    // usFlashId |= Spi_ReadByte()< 
    // usFlashId |= Spi_ReadByte();

    FLASH_CS_HIGH;

    usFlashId = (uint16_t)(temp_buff[0] < < 8) | (temp_buff[1] < < 0);

    return usFlashId;
}

//--------------------------------------------------------------------------------------------------------
//    函 數(shù) 名: Flash_ReadJEDECID
//    功能說(shuō)明: 讀取FLASH ID(manufacturer ID-1Byte + Device ID-2Byte:type+density)
//    形    參: 無(wú)
//    返 回 值: ulJedId:FLASH ID 3字節(jié)
//    日    期: 2020-03-06
//    備    注: 軟件模擬SPI
//    作    者: by 霽風(fēng)AI
//--------------------------------------------------------------------------------------------------------
uint32_t Flash_ReadJEDECID(void)
{
    uint8_t command = FLASH_READ_JEDEC_ID;
    uint32_t flash_jed_id = 0;
    uint8_t recv_buff[3] = {0};

    FLASH_CS_LOW;

    hal_spi_send_bytes(SPI_COMM_MODE, &command, 1); //9fh
    hal_spi_recv_bytes(SPI_COMM_MODE, recv_buff, 3);

    FLASH_CS_HIGH;

    flash_jed_id = (recv_buff[0] < < 16) | (recv_buff[1] < < 8) | (recv_buff[2] < < 0);

return flash_jed_id;

}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • FlaSh
    +關(guān)注

    關(guān)注

    10

    文章

    1633

    瀏覽量

    147939
  • STM32
    +關(guān)注

    關(guān)注

    2270

    文章

    10895

    瀏覽量

    355729
  • SRAM芯片
    +關(guān)注

    關(guān)注

    0

    文章

    65

    瀏覽量

    12059
  • 狀態(tài)寄存器
    +關(guān)注

    關(guān)注

    0

    文章

    39

    瀏覽量

    7081
  • w25Q64
    +關(guān)注

    關(guān)注

    1

    文章

    15

    瀏覽量

    3017
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    STM32:SPI總線、W25Q64FLASH)的詳細(xì)介紹

    W25Q64這類似的Flash存儲(chǔ)芯片在單片機(jī)里、嵌入式系統(tǒng)里還是比較常見(jiàn),可以用來(lái)存儲(chǔ)圖片數(shù)據(jù)、字庫(kù)數(shù)據(jù)、音頻數(shù)據(jù)、保存設(shè)備運(yùn)行日志文件等。
    的頭像 發(fā)表于 03-03 17:06 ?3.3w次閱讀
    <b class='flag-5'>STM32</b>:SPI總線、<b class='flag-5'>W25Q64</b>(<b class='flag-5'>FLASH</b>)的詳細(xì)介紹

    W25Q64串行FLASH基礎(chǔ)知識(shí)大小

    W25Q64串行FLASH基礎(chǔ)知識(shí)大?。?M(Byte)(128塊(Block),每塊64K字節(jié),每塊16個(gè)扇區(qū)(Sector),每個(gè)扇區(qū)4K字 節(jié),每個(gè)扇區(qū)16頁(yè),每頁(yè)256個(gè)字節(jié))特點(diǎn)
    發(fā)表于 07-22 09:32

    W25Q64是什么?怎樣去使用W25Q64

    W25Q64是什么?怎樣去使用W25Q64呢?Flash與EEPROM的區(qū)別有哪些呢?
    發(fā)表于 12-20 06:32

    介紹W25Q64驅(qū)動(dòng)函數(shù)

    可說(shuō)的。關(guān)于FATFS的移植下一篇文章介紹。本篇文章主要介紹W25Q64驅(qū)動(dòng)函數(shù)。W25Q64容量是64Mbit的flash
    發(fā)表于 01-26 07:53

    w25Q64中文手冊(cè)

    w25Q64中文手冊(cè)
    發(fā)表于 10-16 15:25 ?714次下載
    <b class='flag-5'>w25Q64</b>中文手冊(cè)

    w25Q64的中文手冊(cè)

    w25Q64的中文手冊(cè)
    發(fā)表于 10-19 08:59 ?338次下載
    <b class='flag-5'>w25Q64</b>的中文手冊(cè)

    STM32Cube-18】使用硬件QSPI讀寫SPI FlashW25Q64

    本篇詳細(xì)的記錄了如何使用STM32CubeMX配置STM32L431RCT6的硬件QSPI外設(shè)與 SPI Flash 通信(W25Q64)。
    發(fā)表于 12-01 21:06 ?14次下載
    【<b class='flag-5'>STM32</b>Cube-18】使用硬件QSPI讀寫SPI <b class='flag-5'>Flash</b>(<b class='flag-5'>W25Q64</b>)

    STM32單片機(jī)基礎(chǔ)18——使用硬件QSPI讀寫SPI FlashW25Q64

    本篇詳細(xì)的記錄了如何使用STM32CubeMX配置STM32L431RCT6的硬件QSPI外設(shè)與 SPI Flash 通信(W25Q64)。1. 準(zhǔn)備工作硬件準(zhǔn)備開(kāi)發(fā)板首先需要準(zhǔn)備一個(gè)
    發(fā)表于 12-02 10:21 ?19次下載
    <b class='flag-5'>STM32</b>單片機(jī)基礎(chǔ)18——使用硬件QSPI讀寫SPI <b class='flag-5'>Flash</b>(<b class='flag-5'>W25Q64</b>)

    剖析STM32F103讀寫W25Q64

    可說(shuō)的。關(guān)于FATFS的移植下一篇文章介紹。本篇文章主要介紹W25Q64驅(qū)動(dòng)函數(shù)。W25Q64容量是64Mbit的flash,
    發(fā)表于 12-02 11:21 ?37次下載
    剖析<b class='flag-5'>STM32</b>F103讀寫<b class='flag-5'>W25Q64</b>

    W25Q64中文數(shù)據(jù)手冊(cè)

    W25Q64中文
    發(fā)表于 06-28 11:09 ?120次下載

    Linux驅(qū)動(dòng)開(kāi)發(fā)-編寫W25Q64(Flash)驅(qū)動(dòng)

    本篇文章就介紹如何在Linux系統(tǒng)下編寫W25Q64芯片的驅(qū)動(dòng),完成數(shù)據(jù)存儲(chǔ),W25Q64支持標(biāo)準(zhǔn)SPI總線,當(dāng)前驅(qū)動(dòng)程序底層的代碼寫了兩種方式,一種是采用內(nèi)核提供的SPI子系統(tǒng)框架,
    的頭像 發(fā)表于 09-17 15:09 ?3392次閱讀
    Linux<b class='flag-5'>驅(qū)動(dòng)</b>開(kāi)發(fā)-編寫<b class='flag-5'>W25Q64</b>(<b class='flag-5'>Flash</b>)<b class='flag-5'>驅(qū)動(dòng)</b>

    STM32驅(qū)動(dòng)W25Q64讀寫數(shù)據(jù)資料

    STM32驅(qū)動(dòng)W25Q64讀寫數(shù)據(jù)資料
    發(fā)表于 04-12 14:28 ?30次下載

    STM32 SPI讀寫W25Q64(二)

    W25Q64 將 8M 的容量分為 128 個(gè)塊(Block),每個(gè)塊大小為 64K 字節(jié),每個(gè)塊又分為 16個(gè)扇區(qū)(Sector),每個(gè)扇區(qū) 4K 個(gè)字節(jié)。
    發(fā)表于 07-22 11:09 ?6832次閱讀
    <b class='flag-5'>STM32</b> SPI讀寫<b class='flag-5'>W25Q64</b>(二)

    STM32 SPI讀寫W25Q64(三)

    GPIO口模擬SPI讀寫W25Q64的基本內(nèi)容已經(jīng)跟大家介紹完了,今天跟大家介紹下如何通過(guò)串口接收文件并保存到W25Q64中。
    發(fā)表于 07-22 11:11 ?1638次閱讀
    <b class='flag-5'>STM32</b> SPI讀寫<b class='flag-5'>W25Q64</b>(三)

    Arduino下W25Q64驅(qū)動(dòng)程序源碼

    本上傳資料中包含W25Q64驅(qū)動(dòng)源碼,以及在Arduino下配合SPI設(shè)備的測(cè)試工程。測(cè)試工程使用的是合宙Air001開(kāi)發(fā)板。你可以改變?yōu)槠渌蠸PI設(shè)備的Arduino開(kāi)發(fā)板,經(jīng)過(guò)適當(dāng)改造
    發(fā)表于 08-28 16:05 ?5次下載
    RM新时代网站-首页