單芯片解決方案,開啟全新體驗——W55MH32 高性能以太網單片機
W55MH32是WIZnet重磅推出的高性能以太網單片機,它為用戶帶來前所未有的集成化體驗。這顆芯片將強大的組件集于一身,具體來說,一顆W55MH32內置高性能Arm? Cortex-M3核心,其主頻最高可達216MHz;配備1024KB FLASH與96KB SRAM,滿足存儲與數據處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協議棧、內置MAC以及PHY,擁有獨立的32KB以太網收發緩存,可供8個獨立硬件socket使用。如此配置,真正實現了All-in-One解決方案,為開發者提供極大便利。
在封裝規格上,W55MH32 提供了兩種選擇:QFN100和QFN68。
W55MH32L采用QFN100封裝版本,尺寸為12x12mm,其資源豐富,專為各種復雜工控場景設計。它擁有66個GPIO、3個ADC、12通道DMA、17個定時器、2個I2C、5個串口、2個SPI接口(其中1個帶I2S接口復用)、1個CAN、1個USB2.0以及1個SDIO接口。如此豐富的外設資源,能夠輕松應對工業控制中多樣化的連接需求,無論是與各類傳感器、執行器的通信,還是對復雜工業協議的支持,都能游刃有余,成為復雜工控領域的理想選擇。 同系列還有QFN68封裝的W55MH32Q版本,該版本體積更小,僅為8x8mm,成本低,適合集成度高的網關模組等場景,軟件使用方法一致。更多信息和資料請進入網站或者私信獲取。
此外,本W55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應用,涵蓋TCP SSL、HTTP SSL以及 MQTT SSL等,為網絡通信安全再添保障。
為助力開發者快速上手與深入開發,基于W55MH32L這顆芯片,WIZnet精心打造了配套開發板。開發板集成WIZ-Link芯片,借助一根USB C口數據線,就能輕松實現調試、下載以及串口打印日志等功能。開發板將所有外設全部引出,拓展功能也大幅提升,便于開發者全面評估芯片性能。
若您想獲取芯片和開發板的更多詳細信息,包括產品特性、技術參數以及價格等,歡迎訪問官方網頁,我們期待與您共同探索W55MH32的無限可能。

第二十九章 讀寫內部FLASH
1 W55MH32的內部FLASH簡介
在W55MH32芯片內部有一個FLASH存儲器,它主要用于存儲代碼,我們在電腦上編寫好應用程序后,使用下載器把編譯后的代碼文件燒錄到該內部FLASH中, 由于FLASH存儲器的內容在掉電后不會丟失,芯片重新上電復位后,內核可從內部FLASH中加載代碼并運行, 見下圖,W55MH32的內部框架圖:

除了使用外部的工具(如下載器)讀寫內部FLASH外,W55MH32芯片在運行的時候,也能對自身的內部FLASH進行讀寫,因此, 若內部FLASH存儲了應用程序后還有剩余的空間,我們可以把它像外部SPI-FLASH那樣利用起來,存儲一些程序運行時產生的需要掉電保存的數據。
由于訪問內部FLASH的速度要比外部的SPI-FLASH快得多,所以在緊急狀態下常常會使用內部FLASH存儲關鍵記錄;為了防止應用程序被抄襲, 有的應用會禁止讀寫內部FLASH中的內容,或者在第一次運行時計算加密信息并記錄到某些區域,然后刪除自身的部分加密代碼,這些應用都涉及到內部FLASH的操作。
1.1 內部FLASH的構成
W55MH32的內部FLASH包含主存儲器、系統存儲器以及選項字節區域, 它們的地址分布及大小見下表,W55MH32大容量產品內部FLASH的構成:
| 模塊 | 名稱 | 地址 | 大小 |
| 主存儲塊 | 頁 0 | 0x0800 0000 - 0x0800 07FF | 2K |
| 頁 1 | 0x0800 0800 - 0x0800 0FFF | 2K | |
| 頁 2 | 0x0800 1000 - 0x0800 17FF | 2K | |
| 頁 3 | 0x0800 1800 - 0x0800 1FFF | 2K | |
| … | … | … | |
| 頁 255 | 0x0807 F800 - 0x0807 FFFF | 2K | |
| 信息塊 | 系統存儲器 | 0x1FFF F000 - 0x1FFF F7FF | 2K |
| 選擇字節 | 0x1FFF F000 - 0x1FFF F7FF | 16 | |
| 閃存存儲器接口寄存器 | FLASH_ACR | 0x4002 2000 - 0x4002 2003 | 4 |
| FALSH_KEYR | 0x4002 2004 - 0x4002 2007 | 4 | |
| FLASH_OPTKEYR | 0x4002 2008 - 0x4002 200B | 4 | |
| FLASH_SR | 0x4002 200C - 0x4002 200F | 4 | |
| FLASH_CR | 0x4002 2010 - 0x4002 2013 | 4 | |
| FLASH_AR | 0x4002 2014 - 0x4002 2017 | 4 | |
| 保留 | 0x4002 2018 - 0x4002 201F | 4 | |
| FLASH_OBR | 0x4002 201C - 0x4002 201F | 4 | |
| FLASH_WRPR | 0x4002 2020 - 0x4002 2023 | 4 |
主存儲
| 型號 | W55MH32L | W55MH32Q |
| Flash (KB) | 1024 | 1024 |
| SRAM (KB) | 96 | 96 |
| 定時器 | ||
| 高級 | 2 | 2 |
| 通用 | 10 | 10 |
| 基本 | 2 | 2 |
| 通信接口 | ||
| SPI | 2 | 2 |
| I2C | 2 | 2 |
| USART/UART | 5 | 3 |
| USB | 1 | 1 |
| CAN | 1 | 1 |
| SDIO | 1 | - |
| Ethernet | 1 | 1 |
| GPIO 端口 | 66 | 36 |
| 12 位 ADC (通道數) | 3(12 個通道) | 3(12 個通道) |
| 12 位 DAC (通道數) | 2(2 個通道) | 2(2 個通道) |
| 隨機數模塊 | 支持 | 支持 |
| 硬件加密算法單元 | 支持 | 支持 |
| 頁大小 (K 字節) | 4 | 4 |
| CPU 頻率 | 216M | 216M |
| 工作電壓 | 2.0-3.6V | 2.0-3.6V |
| 工作溫度 | -40-+85℃ | -40-+85℃ |
系統存儲區
系統存儲區是用戶不能訪問的區域,它在芯片出廠時已經固化了啟動代碼,它負責實現串口、USB以及CAN等ISP燒錄功能。
選項字節
選項字節用于配置FLASH的讀寫保護、待機/停機復位、軟件/硬件看門狗等功能,這部分共16字節。可以通過修改FLASH的選項控制寄存器修改。
2 對內部FLASH的寫入過程
2.1 解鎖
由于內部FLASH空間主要存儲的是應用程序,是非常關鍵的數據,為了防止誤操作修改了這些內容,芯片復位后默認會給控制寄存器FLASH_CR上鎖, 這個時候不允許設置FLASH的控制寄存器,從而不能修改FLASH中的內容。
2.2 頁擦除
在寫入新的數據前,需要先擦除存儲區域,W55MH32提供了頁(扇區)擦除指令和整個FLASH擦除(批量擦除)的指令,批量擦除指令僅針對主存儲區。
頁擦除的過程如下:
檢查 FLASH_SR 寄存器中的“忙碌寄存器位 BSY”,以確認當前未執行任何 Flash 操作;
在 FLASH_CR 寄存器中,將“激活頁擦除寄存器位PER ”置 1;
用FLASH_AR寄存器選擇要擦除的頁;
將 FLASH_CR 寄存器中的“開始擦除寄存器位 STRT ”置 1,開始擦除;
等待 BSY 位被清零時,表示擦除完成。
2.3 寫入數據
擦除完畢后即可寫入數據,寫入數據的過程并不是僅僅使用指針向地址賦值,賦值前還還需要配置一系列的寄存器,步驟如下:
檢查 FLASH_SR 中的 BSY 位,以確認當前未執行任何其它的內部 Flash 操作;
將 FLASH_CR 寄存器中的 “激活編程寄存器位PG” 置 1;
向指定的FLASH存儲器地址執行數據寫入操作,每次只能以16位的方式寫入;
等待 BSY 位被清零時,表示寫入完成。
3 查看工程的空間分布
由于內部FLASH本身存儲有程序數據,若不是有意刪除某段程序代碼,一般不應修改程序空間的內容, 所以在使用內部FLASH存儲其它數據前需要了解哪一些空間已經寫入了程序代碼,存儲了程序代碼的扇區都不應作任何修改。 通過查詢應用程序編譯時產生的“*.map”后綴文件,可以了解程序存儲到了哪些區域, 它在工程中的打開方式見下圖,打開工程的map文件 , 也可以到工程目錄中的“Listing”文件夾中找到,關于map文件的詳細說明可參考《MDK的編譯過程及文件類型》章節。

3.1 程序ROM的加載與執行空間
上述說明中有兩段分別以“Load Region LR_ROM1”及“Execution Region ER_IROM1”開頭的內容, 它們分別描述程序的加載及執行空間。 在芯片剛上電運行時,會加載程序及數據,例如它會從程序的存儲區域加載到程序的執行區域,還把一些已初始化的全局變量從ROM復制到RAM空間, 以便程序運行時可以修改變量的內容。加載完成后,程序開始從執行區域開始執行。
在上面map文件的描述中,我們了解到加載及執行空間的基地址(Base)都是0x08000000,它正好是W55MH32內部FLASH的首地址, 即W55MH32的程序存儲空間就直接是執行空間;它們的大小(Size)分別為0x000017a8及0x0000177c, 執行空間的ROM比較小的原因就是因為部分RW-data類型的變量被拷貝到RAM空間了; 它們的最大空間(Max)均為0x00080000,即512K字節,它指的是內部FLASH的最大空間。
計算程序占用的空間時,需要使用加載區域的大小進行計算,本例子中應用程序使用的內部FLASH是從0x08000000至(0x08000000+0x000017a8)地址的空間區域。
3.2 ROM空間分布表
在加載及執行空間總體描述之后,緊接著一個ROM詳細地址分布表,它列出了工程中的各個段(如函數、常量數據)所在的地址BaseAddr及占用的空間Size, 列表中的Type說明了該段的類型,CODE表示代碼,DATA表示數據,而PAD表示段之間的填充區域,它是無效的內容, PAD區域往往是為了解決地址對齊的問題。
觀察表中的最后一項,它的基地址是0x0800175c,大小為0x00000020,可知它占用的最高的地址空間為0x0800177c,跟執行區域的最高地址0x0000177c一樣, 但它們比加載區域說明中的最高地址0x80017a8要小,所以我們以加載區域的大小為準。 對比表 W55MH32大容量產品內部FLASH的構成 的內部FLASH頁地址分布表, 可知僅使用頁0至頁2就可以完全存儲本應用程序,所以從頁3(地址0x08001800)后的存儲空間都可以作其它用途,使用這些存儲空間時不會篡改應用程序空間的數據。
4 操作內部FLASH的庫函數
為簡化編程,W55MH32標準庫提供了一些庫函數,它們封裝了對內部FLASH寫入數據操作寄存器的過程。
4.1 FLASH解鎖、上鎖函數
對內部FLASH解鎖、上鎖的函數見代碼清單:FLASH-2:
代碼清單:FLASH-2 FLASH解鎖、上鎖
#define FLASH_KEY1 ((uint32_t)0x45670123)
#define FLASH_KEY2 ((uint32_t)0xCDEF89AB)
/**
* @brief 對FLASH控制寄存器解鎖,使能訪問
* @param None
* @retval None
*/
void FLASH_Unlock(void)
{
if ((FLASH->CR & FLASH_CR_LOCK) != RESET) {
/* 寫入確認驗證碼 */
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
}
/**
* @brief 對FLASH控制寄存器上鎖,禁止訪問
* @param None
* @retval None
*/
void FLASH_Lock(void)
{
/* 設置FLASH寄存器的LOCK位 */
FLASH->CR |= FLASH_CR_LOCK;
}
解鎖的時候,它對FLASH_KEYR寄存器寫入兩個解鎖參數,上鎖的時候,對FLASH_CR寄存器的FLASH_CR_LOCK位置1。
4.2 設置操作位數及頁擦除
解鎖后擦除扇區時可調用FLASH_EraseSector完成,見代碼清單:FLASH-3:
代碼清單:FLASH-3 擦除扇區
/**
* @brief 擦除指定的頁
* @param Page_Address: 要擦除的頁地址.
* @retval FLASH Status:
可能的返回值: FLASH_BUSY, FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
{
FLASH_Status status = FLASH_COMPLETE;
/* 檢查參數 */
assert_param(IS_FLASH_ADDRESS(Page_Address));
/*...此處省略XL超大容量芯片的控制部分*/
/* 等待上一次操作完成 */
status = FLASH_WaitForLastOperation(EraseTimeout);
if (status == FLASH_COMPLETE) {
/* 若上次操作完成,則開始頁擦除 */
FLASH->CR|= CR_PER_Set;
FLASH->AR = Page_Address;
FLASH->CR|= CR_STRT_Set;
/* 等待操作完成 */
status = FLASH_WaitForLastOperation(EraseTimeout);
/* 復位 PER 位 */
FLASH->CR &= CR_PER_Reset;
}
/* 返回擦除結果 */
return status;
}
本函數包含一個輸入參數用于設置要擦除的頁地址,即目標頁的在內部FALSH的首地址,函數獲取地址后,根據前面的流程檢查狀態位、 向控制寄存器FLASH_CR及地址寄存器FLASH_AR寫入參數,配置開始擦除后,需要等待一段時間,函數中使用使用FLASH_WaitForLastOperation()等待, 擦除完成的時候才會退出FLASH_EraseSector()函數。
4.3 寫入數據
對內部FLASH寫入數據不像對SDRAM操作那樣直接指針操作就完成了,還要設置一系列的寄存器, 利用FLASH_ProgramWord()和FLASH_ProgramHalfWord()函數可按字、半字的單位單位寫入數據, 見代碼清單:FLASH-4:
代碼清單:FLASH-4 寫入數據
/**
* @brief 向指定的地址寫入一個字的數據(32位)
* @param Address: 要寫入的地址
* @param Data: 要寫入的數據
* @retval FLASH Status:
可能的返回值: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data)
{
FLASH_Status status = FLASH_COMPLETE;
__IO uint32_t tmp = 0;
/* 檢查參數 */
assert_param(IS_FLASH_ADDRESS(Address));
/*...此處省略XL超大容量芯片的控制部分*/
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if (status == FLASH_COMPLETE) {
/* 若上次操作完成,則開始頁入低16位的數據(輸入參數的第1部分) */
FLASH->CR |= CR_PG_Set;
*(__IO uint16_t*)Address = (uint16_t)Data;
/* 等待上一次操作完成 */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if (status == FLASH_COMPLETE) {
/* 若上次操作完成,則開始頁入高16位的數據(輸入參數的第2部分) */
tmp = Address + 2;
*(__IO uint16_t*) tmp = Data >> 16;
/* 等待操作完成 */
status = FLASH_WaitForLastOperation(ProgramTimeout);
/* 復位 PG 位 */
FLASH->CR &= CR_PG_Reset;
} else {
/* 復位 PG 位 */
FLASH->CR &= CR_PG_Reset;
}
}
/* 返回寫入結果 */
return status;
}
從函數代碼可了解到,它設置FLASH->CR 寄存器的PG位允許寫入后,使用16位的指針往指定的地址寫入數據,由于每次只能按16位寫入, 所以這個按字寫入的過程使用了兩次指針賦值,分別寫入指定數據的低16位和高16位,每次賦值操作后,調用FLASH_WaitForLastOperation()函數等待寫操作完畢。 標準庫里還提供了FLASH_ProgramHalfWord()函數用于每次寫入半個字,即16位,該函數內部的執行過程類似。
5 讀寫內部FLASH
5.1 代碼分析
1.宏定義
#define FLASH_TEST_ADDR (0x0800F400) // 測試用Flash地址(32KB處)
地址選擇:需確保該地址未被程序代碼占用,且屬于可擦寫區域。
2.主函數邏輯
int main(void)
{
// 初始化系統時鐘、串口等
delay_init();
UART_Configuration(115200);
printf("系統時鐘信息...");
while (1)
{
FLASH_EraseProgram(number++); // 執行擦除編程測試
if (number == 0xFFFFFFFF) // 防止溢出,結束測試
{
printf("Test Endn");
while (1);
}
}
}
無限循環:持續測試,直到number溢出。
3.FLASH 擦除與編程函數
void FLASH_EraseProgram(uint32_t number)
{
// 1. 擦除頁測試
SYSTICK_Reset();
FLASH_ErasePage(FLASH_TEST_ADDR);
if (擦除成功)
printf("擦除時間:%d msn", 計算時間);
else
進入死循環;
// 2. 編程半字測試
SYSTICK_Reset();
for (i = 0; i < 512; i++)
FLASH_ProgramHalfWord(地址+i*2, 0x5A5A);
if (編程成功)
printf("編程時間:%d msn", 計算時間);
else
進入死循環;
}
擦除操作:使用FLASH_ErasePage擦除整頁(通常為 2KB)。
編程操作:逐個半字寫入0x5A5A,驗證寫入正確性。
4.時間測量函數
void SYSTICK_Reset(void)
{
SysTick->CTRL = 0; // 停止定時器
SysTick->LOAD = 0xFFFFFF; // 最大計數值
SysTick->VAL = 0; // 清零當前值
SysTick->CTRL = 0x05; // 使能定時器,選擇HCLK時鐘
}
時間計算:通過0xFFFFFF - SysTick->VAL得到操作耗時(單位:時鐘周期)。
5. 串口配置函數
void UART_Configuration(uint32_t bound)
{
// 使能USART1和GPIOA時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// 配置TX引腳(PA9)為復用推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 初始化USART1參數(波特率、數據位等)
USART_Init(USART_TEST, &USART_InitStructure);
USART_Cmd(USART_TEST, ENABLE);
}
功能:配置 USART1 為 115200 波特率,用于調試輸出。
5.2 下載驗證

6 FLASH_Eeprom
6.1 代碼分析
1.主函數 main()
int main(void) {
uint8_t datatemp[SIZE], i;
delay_init();
UART_Configuration(115200);
// 打印系統時鐘信息
RCC_GetClocksFreq(&clocks);
printf("SYSCLK: %3.1fMhz...n", ...);
printf("FLASH EEPROM Tset.n");
// 循環讀寫FLASH
while (1) {
WIZFLASH_Write(FLASH_SAVE_ADDR, (u16 *)TEXT_Buffer, SIZE); // 寫入數據
WIZFLASH_Read(FLASH_SAVE_ADDR, (u16 *)datatemp, SIZE); // 讀取數據
// 打印錯誤(應逐個字符處理)
for (i = 0; i < SIZE; i++) {
printf("%sn", datatemp); }
memset(datatemp, 0x00, sizeof(datatemp)); // 清空數組
delay_ms(1000); // 延時
}
}
2.串口配置 UART_Configuration
void UART_Configuration(uint32_t bound) {
// 使能時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// 配置串口引腳
GPIO_Init(GPIOA, &GPIO_InitStructure); // PA9(發送)復用推挽,PA10(接收)浮空輸入
// 配置串口參數:115200波特率、8位數據等
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE); // 使能串口
}
配置 USART1,用于輸出調試信息。
3.串口重定向
int SER_PutChar(int ch) {
while (!USART_GetFlagStatus(USART1, USART_FLAG_TC)); // 等待發送完成
USART_SendData(USART1, (uint8_t)ch);
return ch;
}
int fputc(int c, FILE *f) {
if (c == 'n') SER_PutChar('r'); // 換行處理
return SER_PutChar(c); // 實現printf通過串口輸出
}
4. FLASH 操作
依賴eeprom.h的WIZFLASH_Write和WIZFLASH_Read,需確保其實現 FLASH 底層操作(擦除、讀寫等)。
地址:FLASH_SAVE_ADDR 0X08008000,需在可用 FLASH 空間內。
6.2 下載驗證

-
單片機
+關注
關注
6076文章
45494瀏覽量
670256 -
FlaSh
+關注
關注
10文章
1748瀏覽量
155506 -
存儲器
+關注
關注
39文章
7738瀏覽量
171650 -
定時器
+關注
關注
23文章
3368瀏覽量
123579
發布評論請先 登錄
《DNK210使用指南 -CanMV版 V1.0》第二十九章 音頻錄制實驗
PCB設計規范2010最新版
眾想科技-劉洋邊講邊寫STM32視頻教程 15.RS232串口通訊實驗
《BOSCH汽車電氣與電子 》(中文第一版)(完整版)
「正點原子Linux連載」第二十九章LCD背光調節實驗
「正點原子STM32Mini板資料連載」第二十九章 無線通信實驗
「正點原子NANO STM32F103開發板資料連載」第二十九章 內存管理實驗
「ALIENTEK 探索者 STM32F407 開發板資料連載」第二十九章 IIC 實驗
模擬數字轉換器ADC編程指南
CH32V103基礎教程30-ADC(多通道DMA讀取方式)
模擬電路網絡課件 第二十九節:專用型集成電路運算放大器
蔡司亮相第二十九屆中國國際口腔設備材料展覽會,邀您共探口腔行業未來
第二十九章 W55MH32 Modbus_TCP_Server示例
第二十九章 讀寫內部FLASH
評論