一 概述
W25Q128是一種NOR Flash芯片,掉電后數(shù)據(jù)不丟失的特點。
W25Q128FV陣列被組織成65,536個可編程頁面,每個頁面256字節(jié)。每次最多可編程256字節(jié)??梢砸?6頁為一組(即一個Sector)、128頁為一組(8個Sector)、256頁為一組(16個Sector)或整個芯片(芯片擦除)進行擦除。W25Q128FV分別有4,096個可擦除扇區(qū)和256個可擦除塊。較小的4KB扇區(qū)為需要數(shù)據(jù)和參數(shù)存儲的應用程序提供了更大的靈活性。
標準SPI通信支持時鐘頻率高達104MHz,Dual SPI通信支持時鐘頻率高達208MHz,QSPI通信支持時鐘頻率高達416MHz。
注意:W25Q128一共為128M bits(16M Byte),又分為256個塊(每個塊512K bit(64K Byte)),每個塊又分為16個扇區(qū)(每個扇區(qū)32K bit(4 KByte)),每個扇區(qū)又分為16頁(每個頁2K bit(256 Byte))
二 物理特性
可以將 1 寫成 0,但是不能將 0 寫成 1,要想將 0 寫成 1,必須進行擦除操作。如果要改變數(shù)據(jù),就需要先擦除后寫數(shù)據(jù)。
如果想要修改小于扇區(qū)大小的數(shù)據(jù),需要將整個扇區(qū)的數(shù)據(jù),在內存中進行備份,然后修改內存中的數(shù)據(jù),再將數(shù)據(jù)寫回到原扇區(qū)位置。因此,驅動要達到支持自動完成這個過程,用戶可以使用驅動修改任意位置的數(shù)據(jù)。
三 存儲結構
W25Q128可以存儲16777216字節(jié),存儲一個字節(jié)占用一個地址,所以尋址范圍是0-(16777216-1),對應的16進制為0-0xFFFFFF(所以寄存器地址是24位的)

四 命令總覽

五 組件的使用
1 Gitee鏈接地址
Demo位于amaziot_bloom_os_sdksample3rd2.1_W25Q128
Gitee源碼地址:https://gitee.com/ning./hongdou
Github源碼地址:https://github.com/ayumid/hongdou
編譯指令:.build.bat -l .amaziot_bloom_os_sdksample3rd2.1_W25Q128
2 組件功能介紹
實現(xiàn)軟件模擬SPI,驅動W25Q128芯片,實現(xiàn)數(shù)據(jù)存儲。
3 代碼講解
1 drv_w25q128_delay_us
功能:該函數(shù)用于,延時。
參數(shù):
| 參數(shù) | 釋義 |
| count | 死循環(huán)次數(shù) |
返回值:無
示例:
//初始化i2c總線 ret = drv_xl9535_i2c_init();
2 drv_w25q128_gpio_set
功能:該函數(shù)用于,模擬SPI設置IO輸出電平。
參數(shù):
| 參數(shù) | 釋義 |
| num | 引腳號 |
| val | 0 低電平,1 高電平 |
返回值:0 成功,-1 失敗
示例:
drv_w25q128_gpio_set(DRV_w25q128_SPI_CS, DRV_w25q128_GPIO_LOW);
3 drv_w25q128_byte_wr
功能:該函數(shù)用于,SPI寫讀一個字節(jié) mode3。
參數(shù):
| 參數(shù) | 釋義 |
| byte | 發(fā)送數(shù)據(jù) |
返回值:flash返回數(shù)據(jù)
示例:
drv_w25q128_byte_wr(DRV_w25q128_DUMMY_BYTE);
4 drv_w25q128_byte_rd
功能:該函數(shù)用于,SPI只讀一個字節(jié)。
參數(shù):無
返回值:flash返回數(shù)據(jù)
示例:
drv_w25q128_byte_rd(DRV_w25q128_DUMMY_BYTE);
5 drv_w25q128_busy_wait
功能:該函數(shù)用于,W25Q128 忙等待。
參數(shù):無
返回值:無
示例:
while(drv_w25q128_read_reg1() & BIT_BUSY);
6 drv_w25q128_read_reg
功能:該函數(shù)用于,讀reg。
參數(shù):無
返回值:無
示例:
while(drv_w25q128_read_reg() & BIT_BUSY);
7 drv_w25q128_read_jedecid
功能:該函數(shù)用于,讀 W25Q128 JEDEC_ID(制造商、類型、容量)。
參數(shù):無
返回值:無
示例:
sample_w25q128_uart_printf("identification is 0x%X, Device id is 0x%X, Manufacturer Device ID is 0x%X", drv_w25q128_read_identification(), drv_w25q128_read_device_id(), drv_w25q128_read_manufacturer_id());
8 drv_w25q128_read_manufacturer_id
功能:該函數(shù)用于,讀 W25Q128 制造商 ID。
參數(shù):無
返回值:無
示例:
sample_w25q128_uart_printf("identification is 0x%X, Device id is 0x%X, Manufacturer Device ID is 0x%X",
drv_w25q128_read_identification(), drv_w25q128_read_device_id(), drv_w25q128_read_manufacturer_id());
9 drv_w25q128_read_device_id
功能:該函數(shù)用于,讀 W25Q128 設備 ID。
參數(shù):無
返回值:無
示例:
sample_w25q128_uart_printf("identification is 0x%X, Device id is 0x%X, Manufacturer Device ID is 0x%X",
drv_w25q128_read_identification(), drv_w25q128_read_device_id(), drv_w25q128_read_manufacturer_id());
10 drv_w25q128_write_enable
功能:該函數(shù)用于,寫使能。
參數(shù):無
返回值:無
示例:
sample_w25q128_uart_printf("identification is 0x%X, Device id is 0x%X, Manufacturer Device ID is 0x%X",
drv_w25q128_read_identification(), drv_w25q128_read_device_id(), drv_w25q128_read_manufacturer_id());
11 drv_w25q128_write_disable
功能:該函數(shù)用于,寫失能。
參數(shù):無
返回值:無
示例:
無
12 drv_w25q128_write_page
功能:該函數(shù)用于,頁編程(調用本函數(shù)寫入數(shù)據(jù)前需要先擦除扇區(qū))。
參數(shù):
| 參數(shù) | 釋義 |
| pbuf | 數(shù)據(jù) |
| addr | 地址 |
| len | 長度 |
返回值:無
示例:
drv_w25q128_write_page(pbuf, addr, pageremain);
13 drv_w25q128_read
功能:該函數(shù)用于,讀閃存數(shù)據(jù)。
參數(shù):
| 參數(shù) | 釋義 |
| pbuf | 數(shù)據(jù) |
| addr | 地址 |
| len | 長度 |
返回值:無
示例:
drv_w25q128_read((UINT8*)rx_buff1, 8181, strlen(tx_buff1));
14 drv_w25q128_sector_erase
功能:該函數(shù)用于,扇區(qū)擦除。
參數(shù):
| 參數(shù) | 釋義 |
| addr | 地址 |
返回值:無
示例:
drv_w25q128_sector_erase(secpos * DRV_w25q128_SOCTOR_SIZE);
15 drv_w25q128_chip_rease
功能:該函數(shù)用于,F(xiàn)LASH整片擦除(為了安全起見,若要調用,請先調用 drv_w25q128_write_enable 函數(shù))。
參數(shù):無
返回值:無
示例:
無
16 drv_w25q128_powr_down
功能:該函數(shù)用于,掉電。
參數(shù):無
返回值:無
示例:
無
17 drv_w25q128_release_powr_down
功能:該函數(shù)用于,讀閃存數(shù)據(jù)。
參數(shù):
| 參數(shù) | 釋義 |
| pbuf | 數(shù)據(jù) |
| addr | 地址 |
| len | 長度 |
返回值:無
示例:
drv_w25q128_read((UINT8*)rx_buff1, 8181, strlen(tx_buff1));
18 drv_w25q128_write_nocheck
功能:該函數(shù)用于,寫數(shù)據(jù)。
參數(shù):
| 參數(shù) | 釋義 |
| pbuf | 數(shù)據(jù) |
| addr | 地址 |
| len | 長度 |
返回值:無
示例:
drv_w25q128_write_nocheck(w25q128_buffer, secpos * DRV_w25q128_SOCTOR_SIZE, DRV_w25q128_SOCTOR_SIZE);
19 drv_w25q128_write
功能:該函數(shù)用于,寫閃存數(shù)據(jù),可以使任意地址。
參數(shù):
| 參數(shù) | 釋義 |
| pbuf | 數(shù)據(jù) |
| addr | 地址 |
| len | 長度 |
返回值:無
示例:
drv_w25q128_write((UINT8*)tx_buff1, 8181, strlen(tx_buff1));
20 drv_w25q128_init
功能:該函數(shù)用于,寫數(shù)據(jù)。
參數(shù):無
返回值:無
示例:
drv_w25q128_init();
4 Demo實戰(zhàn)
4.1 創(chuàng)建一個Demo
復制20.1_file_xtu示例工程,到同一個文件夾下,修改文件名為3.1_SSD1315,如圖:

4.2 修改makefile
增加文件組件所在目錄頭文件路徑,和源文件路徑,如圖:

4.3 增加頭文件
使用代碼編輯器,將新建的工程文件加入代碼編輯器中,打開main.c,修改main.c,加入am.h等頭文件,如圖:

4.4 修改代碼
在Phase2Inits_exit 創(chuàng)建一個任務,如圖:

4.1 概述
上電后,按下按鍵,串口會打印出按下了哪一個按鍵
4.2 測試
測試步驟:
參考編譯教程,和文檔開頭的編譯指令,進行編譯
按照編譯教程選擇對應的選項
燒錄
4.3 宏定義介紹
sample_w25q128_uart_printf
輸出日志到DEBUG 串口,日志比較少,可以輸出到這個串口,如果日志比較多,需要輸出到usb口,以免不必要的問題出現(xiàn)
sample_w25q128_catstudio_printf
輸出日志到USB 串口,使用catstudio查看,catstudio查看日志需要更新對應版本mdb.txt文件,軟件打開filtter過濾日志,只查看用戶輸出的日志
SAMPLE_W25Q128_STACK_SIZE
棧空間宏定義
4.4 全局變量介紹
sample_w25q128_task_ref
任務指針
4.5 函數(shù)介紹
Phase1Inits_enter
底層初始化,本例空
Phase1Inits_exit
底層初始化,本例空
Phase2Inits_enter
底層初始化,本例空
Phase2Inits_exit
創(chuàng)建主任務,初始化INT 引腳
代碼片段:
void Phase2Inits_exit(void)
{
int ret;
sample_w25q128_task_stack = malloc(SAMPLE_W25Q128_STACK_SIZE);
ret = OSATaskCreate(&sample_w25q128_task_ref, sample_w25q128_task_stack, SAMPLE_W25Q128_STACK_SIZE, 88, "sample_w25q128_task", sample_w25q128_task, NULL);
ASSERT(ret == OS_SUCCESS);
}
sample_w25q128_task
主任務,代碼發(fā)分為兩部分,一部分是發(fā)送不定長數(shù)據(jù);另一部分是上電后等待其它模塊發(fā)送的數(shù)據(jù),收到后打印到串口。
代碼片段:
static void sample_w25q128_task(void *ptr)
{
int ret = 0;
uint32_t identification = 0;
// unsigned char writeBuf[30] = {0};
// unsigned char readBuf[30] = {0};
// ret = ql_spi_init(QL_SPI_PORT0, QL_SPI_MODE3, QL_SPI_CLK_812_5KHZ);
// sample_w25q128_catstudio_printf("ql_spi_init ret %d", ret);
drv_w25q128_init();
identification = drv_w25q128_read_jedecid();
sample_w25q128_uart_printf("identification is 0x%X, Device id is 0x%X, Manufacturer Device ID is 0x%X",
drv_w25q128_read_jedecid(), drv_w25q128_read_device_id(), drv_w25q128_read_manufacturer_id());
// while(1)
// {
// drv_w25q128_gpio_set(DRV_w25q128_SPI_CS, 0);
// sample_w25q128_uart_printf("low");
// OSATaskSleep(5*200);
// drv_w25q128_gpio_set(DRV_w25q128_SPI_CS, 1);
// sample_w25q128_uart_printf("high");
// OSATaskSleep(5*200);
// }
if(identification != JEDECID)
{
/* 讀取錯誤處理 */
sample_w25q128_uart_printf("SPI read-write Error, please check the connection between MCU and SPI Flashn");
}
else
{
//讀取成功處理
char tx_buff1[64] = "abcdefghigklmnopqrstuvwxyz0123456789";
char rx_buff1[64] = {0};
char tx_buff2[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ9876543210";
char rx_buff2[64] = {0};
int i = 0;
//測試跨sector寫,并且讀出數(shù)據(jù),寫兩次,第二次保留第一次部分數(shù)據(jù),證明數(shù)據(jù)擦除,寫入正常
drv_w25q128_write((UINT8*)tx_buff1, 8181, strlen(tx_buff1));//從8181地址開始寫數(shù)據(jù),需要寫第二和第三個扇區(qū)
drv_w25q128_read((UINT8*)rx_buff1, 8181, strlen(tx_buff1));
sample_w25q128_uart_printf("read flash:%s", rx_buff1);
if(!strncmp(tx_buff1, rx_buff1, strlen(tx_buff1)))
{
sample_w25q128_uart_printf("SPI read-write succeed 1");
}
//驗證驅動擦除扇區(qū)時,可以保留之前有效內容
drv_w25q128_write((UINT8*)tx_buff2, 8186, strlen(tx_buff2));//從8186地址開始寫數(shù)據(jù),需要寫第二和第三個扇區(qū),同時不能擦掉8181 - 8186的5字節(jié)數(shù)據(jù)
drv_w25q128_read((UINT8*)rx_buff2, 8181, strlen(tx_buff2) + 5);
sample_w25q128_uart_printf("read flash:%s", rx_buff2);
if(!strncmp(rx_buff2, "abcdeABCDEFGHIJKLMNOPQRSTUVWXYZ9876543210", strlen("abcdeABCDEFGHIJKLMNOPQRSTUVWXYZ9876543210")))
{
sample_w25q128_uart_printf("SPI read-write succeed 2");
}
}
// memset(writeBuf, 0x00, sizeof(writeBuf));
// memset(readBuf, 0x00, sizeof(readBuf));
// writeBuf[0] = 0x9F;
while (1)
{
// ret = ql_spi_write_read(QL_SPI_PORT0, readBuf, writeBuf, 1);
// sample_w25q128_catstudio_printf("ql_spi_write_read ret %d, readBuf %02X,%02X,%02Xn", ret, readBuf[0], readBuf[1], readBuf[2]);
// ret = ql_spi_write(QL_SPI_PORT0, writeBuf, 1);
// sample_w25q128_catstudio_printf("ql_spi_write_read ret %d, readBuf %02Xn", ret, writeBuf[0]);
// ret = ql_spi_read(QL_SPI_PORT0, readBuf, 3);
// sample_w25q128_catstudio_printf("ql_spi_write_read ret %d, readBuf %02X,%02X,%02Xn", ret, readBuf[0], readBuf[1], readBuf[2]);
OSATaskSleep(5 * 200);
}
}
4.6 固件

點擊下載 Lora Demo固件
5 生態(tài)組件鏈接
SPI NOR FLASH
本文章源自奇跡物聯(lián)開源的物聯(lián)網(wǎng)應用知識庫Cellular IoT Wiki,更多技術干貨歡迎關注收藏Wiki:Cellular IoT Wiki 知識庫(https://rckrv97mzx.feishu.cn/wiki/wikcnBvAC9WOkEYG5CLqGwm6PHf)
歡迎同學們走進AmazIOT知識庫的世界!
這里是為物聯(lián)網(wǎng)人構建的技術應用百科,以便幫助你更快更簡單的開發(fā)物聯(lián)網(wǎng)產品。
Cellular IoT Wiki初心:
在我們長期投身于蜂窩物聯(lián)網(wǎng) ODM/OEM 解決方案的實踐過程中,一直被物聯(lián)網(wǎng)技術碎片化與產業(yè)資源碎片化的問題所困擾。從產品定義、芯片選型,到軟硬件研發(fā)和測試,物聯(lián)網(wǎng)技術的碎片化以及產業(yè)資源的碎片化,始終對團隊的產品開發(fā)交付質量和效率形成制約。為了減少因物聯(lián)網(wǎng)碎片化而帶來的重復開發(fā)工作,我們著手對物聯(lián)網(wǎng)開發(fā)中高頻應用的技術知識進行沉淀管理,并基于 Bloom OS 搭建了不同平臺的 RTOS 應用生態(tài)。后來我們發(fā)現(xiàn),很多物聯(lián)網(wǎng)產品開發(fā)團隊都面臨著相似的困擾,于是,我們決定向全體物聯(lián)網(wǎng)行業(yè)開發(fā)者開放奇跡物聯(lián)內部沉淀的應用技術知識庫 Wiki,期望能為更多物聯(lián)網(wǎng)產品開發(fā)者減輕一些重復造輪子的負擔。
Cellular IoT Wiki沉淀的技術內容方向如下:

奇跡物聯(lián)的業(yè)務服務范圍:基于自研的NB-IoT、Cat1、Cat4等物聯(lián)網(wǎng)模組,為客戶物聯(lián)網(wǎng)ODM/OEM解決方案服務。我們的研發(fā)技術中心在石家莊,PCBA生產基地分布在深圳、石家莊、北京三個工廠,滿足不同區(qū)域&不同量產規(guī)模&不同產品開發(fā)階段的生產制造任務。跟傳統(tǒng)PCBA工廠最大的區(qū)別是我們只服務物聯(lián)網(wǎng)行業(yè)客戶。
連接我們,和10000+物聯(lián)網(wǎng)開發(fā)者一起 降低技術和成本門檻
讓蜂窩物聯(lián)網(wǎng)應用更簡單~~
哈哈你終于滑到最重要的模塊了,
千萬不!要!劃!走!忍住沖動!~
歡迎加入飛書“開源技術交流群”,隨時找到我們哦~
點擊鏈接如何加入奇跡物聯(lián)技術話題群(https://rckrv97mzx.feishu.cn/docx/Xskpd1cFQo7hu9x5EuicbsjTnTf)可以獲取加入技術話題群攻略
Hey 物聯(lián)網(wǎng)從業(yè)者,
你是否有了解過奇跡物聯(lián)的官方公眾號“eSIM物聯(lián)工場”呢?
這里是奇跡物聯(lián)的物聯(lián)網(wǎng)應用技術開源wiki主陣地,歡迎關注公眾號,不迷路~
及時獲得最新物聯(lián)網(wǎng)應用技術沉淀發(fā)布
注:本文部分內容來源于網(wǎng)絡,如有侵權,請及時聯(lián)系我們。
審核編輯 黃宇
-
物聯(lián)網(wǎng)
+關注
關注
2945文章
47807瀏覽量
414708 -
NOR flash
+關注
關注
2文章
103瀏覽量
23891
發(fā)布評論請先 登錄
想問問外接一個flash有什么用如外接w25q128 spi接口flash
外擴FLASH(W25Q128)如何存儲數(shù)組中的數(shù)據(jù)?。?/a>
W25Q128數(shù)據(jù)置頂
W25Q128芯片簡介
基于RT-Thread的W25Q128虛擬U盤和文件系統(tǒng)如何實現(xiàn)自由切換呢
W25Q128 閃存芯片SPI詳解
FLASH芯片(W25Q128)
stm32 cubemx usb spi flash w25q128 u盤調試筆記
STM32CUBEMX(13)--SPI,W25Q128外部Flash移植
【瑞薩FPB-RA6E2試用】W25Q128
物聯(lián)網(wǎng)行業(yè)中Nor Flash的軟件設計分享_W25Q128的軟件設計方案
評論