---
title: Flash 記憶體的原理與應用—PART9
description: "### **作者：Bird** 上一回[【Maker電子學】Flash 記憶體的…"
url: "https://makerpro.cc/docs/flash-memory-principle-and-application-part9/"
updated: "2025-03-26"
category: Flash記憶體
---

# Flash 記憶體的原理與應用—PART9

### **作者：Bird**

上一回[【Maker電子學】Flash 記憶體的原理與應用—PART8（I^2C EEPROM）](https://makerpro.cc/2024/07/flash-memory-principle-and-application-part8/)中，我們說明了如何利用 I^2C 上的通訊來讀取和寫入 24LC64 這顆 I^2C EEPROM 的內容。EEPROM 的讀取速度很快，跟得上 I^2C bus 的存取速度，但是寫入的速度很慢，因此在寫入時，需要一些特別的等待處理。

這一回我們就來看看這個等待要怎麼做。

### **寫入有多慢？**

我們來看一下 24LC64 的 datasheet 中，關於時間特性的描述。下面這個表是 24LC64 的 AC characteristics，它說明了 24LC64 的各種訊號所需要的時序要求。

 ![](https://makerpro.cc/wp-content/uploads/2024/08/Screenshot-2024-08-19-224835.png)

（圖片來源：Bird 提供）

比方說，output valid from clock，就是告訴我們，在 I^2C bus 的 SCL 變為 low 後，SDA 最長還會維持多久不變化。根據 I^2C bus 的規格，SDA 在 SCK 為 high 的時候不能變化，而在 SCL 為 low 的時候可以變化到下一個狀態，但實務上兩者不會同時變動，也就說 SDA 並不會在 SDL 變成 low 的瞬間就一起變化。

在數位訊號的世界裡，沒有真正的「同時」這種事，只要你把觀察的尺度放得夠大，都看得到時間差異，因此為了保證 SCL 為 high 的時候 SDA 絕對不會變化，一般在設計晶片內部 I^2C 的電路時，都會確定 SCL 變為 low 之後，SDA 才開始變化，因此 SDA 會在 SCL 變為 low 之後再稍微等待一小段時間，才開始變化，這個時間就是 datasheet 上的 output valid from clock。

從 datasheet 上可以看出來，很多的時序都會隨著供電電壓的變化而不同。當 24LC64 的供電電壓在 1.7 V-2.5 V 時，它切換邏輯訊號的速度會比較慢，因此只能跑到 100 KHz 的 standard-mode；如果要跑 400 KHz 的 fast-mode，就要用 2.5 V 以上的電壓供電，至於如果要跑 1 MHz 的 fast-mode plus，則需要使用高速版本的晶片 24 FC64。

這整張表裡面大部分的數字都是以 ns 為單位，唯獨有一個特性的單位是 ms，就是 write cycle time。

Write cycle time 就是 24LC64 寫入資料所需要的時間，根據 datasheet 上的說明，不管是寫入一個 byte 還是寫入一個 page，最長都可能會需要 5ms。

5 ms 對現在的 MCU 來說是一個很長的時間。以很常用的 STM32F030 來說，它的 Cortex-M0 核心大部分是 single-cycle 的指令，也就是說每一個 clock 可以執行一個指令；STM32F030 可以輕輕鬆鬆跑到 48 MHz，也就說它一秒鐘可以跑 48,000,000 個 single-cycle 指令，換算一下 5 ms 可以跑：

48000000 * 0.005 = 240,000

24 萬個 single-cycle 指令！

為什麼需要這麼長的時間呢？這跟 24LC64 內部的結構還有 EEPROM 的原理有關。

### **EEPROM 的寫入方式**

雖然我們都說 EEPROM 可以逐個 byte 去抹除、寫入，但是實務上在設計晶片時，抹除的電路不會涉及到 byte 這麼小的單位。在 24LC64 內部，抹除和寫入都是以「page」為單位在進行，而一個 page 是 32 bytes。

當我們要寫入某一個特定位址的 byte 時，24LC64 會利用一個 buffer 暫存整個 page 的資料，抹除整個 page 之後，再把整個 page 連同新的資料一起寫進去，因此在 24LC64 的 datasheet 上有這麼一句耐人尋味的說明：

 ![](https://makerpro.cc/wp-content/uploads/2024/08/Screenshot-2024-08-19-224847.png)

（圖片來源：Bird 提供）

它告訴你，不管你寫 1 個 byte 2 個 byte 還是 32 個 byte，整個 page 都會被寫一次，因此它的寫入壽命計算方式是以 page 為單位來計算，而不是用 byte 的寫入次數。

比方說，我對 0x0000 這個位址下了一次寫入，這時整個 0x0000 - 0x001F 的 page 都會被抹除、寫入一次，這樣就用掉了一次寫入的壽命，而且要等 5 ms；如果接著又對 0x0001 這個位址又下一次寫入，這時整個 0x0000-0x001F 的 page 又會承受一次抹除、寫入，再度用掉一次寫入壽命，也要再度等待 5 ms，總共要花 10 ms。

比較好的作法，就是利用我們上一回說明過的連續寫入功能，在同一次 I^2C 的寫入指令中，連續寫入 0x0000 和 0x0001 這兩個位址的值，然後用 STOP condition 結束這一回合的 I^2C 寫入指令。24LC64 會在收到 STOP condition 後，開始執行整個 page 的暫存、抹除、寫入，因此總共只需要等待一次寫入的週期，也就是 5ms，就可以完成 0x0000 和 0x0001 這兩個 byte 的寫入，也只消耗掉一次寫入的壽命。

因為這種以 page 為單位的寫入結構，在使用 page write 指令時還有一件事要注意：page write 不可以跨過 page 的邊界。

在 24LC64 的 datasheet 中也有這麼一段常常被人忽略的說明：

 ![](https://makerpro.cc/wp-content/uploads/2024/08/Screenshot-2024-08-19-224854.png)

（圖片來源：Bird 提供）

它就是告訴你，用 page write 時，要注意 pysical page 的邊界。一個 page 32 byte，從 0 開始，0 - 31 是一個 page，32 - 63 是一個 page，64 - 95 是一個 page… 如果你從位址 20 開始下 page write 指令，最多只能送 12 個 bytes 的 page write，不能超過；如果超過，寫入的資料會繞回那個 page 的頭，覆蓋掉同一個 page 前面的資料。舉例來說，如果我們從位址 20 開始下 page write，如果送了不只 12 個 bytes，第 13 個 byte 就會被寫到位址 0，第 14 個 byte 就會被寫到位址 1，因此在使用 page write 的時候，要特別注意這個特性，不然就會有一些奇奇怪怪的問題發生。

### **寫完了沒**

我們已經知道 EEPROM 寫入需要花相對來說很長的時間，那我們要怎麼知道它寫完了沒呢？最懶的方式就是每次下完 write 指令後，等 5 ms，再繼續對 24LC64
 下指令。

但 datasheet 中描述的 5 ms 只是最大值，實務上每次寫入所需要的時間隨著電壓、溫度、半導體壽命等因素會有不同，統一等待 5 ms 往往會浪費不必要的時間，因此 24LC64 提供了一個很簡單的方法讓我們知道它寫完了沒：它在寫入週期進行中的時候，不會回應 I^2C 的 ACK。

因此，在 write 指令的 STOP condition 結束後，24LC64 開始努力工作，此時它不會回應 I^2C 的 ACK，只要試著對他發起 START 接著 control byte，看看在第 9 個 clock 的時候 24LC64 會不會去把 SDA 拉下來，就知道它是不是還在忙了。

如果在第 9 個 SCL 週期時，SDA 沒有被拉 low，就代表 24LC64 還在忙，還沒辦法回應 I^2C 指令；如果在第 9 個 SCL 週期時 SDA 被拉 low 了，就代表 24LC64 忙完了，可以繼續下一個 I^2C 指令了；因此只要持續的對 24LC64 發起 I^2C 指令，並檢查它有沒有 ACK，就可以知道它忙完了沒，利用這個方法可以將寫入的效率推到極限。

### **小結**

關於 I^2C EEPROM 的介紹，我們大概就說明到這邊。事實上 I^2C EEPROM 的讀寫架構也是大部分以 I^2C 介面控制的 IC 所利用的基礎，透過 I^2C 介面讀寫 IC 內部的暫存器，就像是在讀寫 EEPROM 一樣，因此熟悉這個 protocol 對於操作其它 IC 來說會很有幫助。

下一回我們會開始介紹另一個完全不一樣的世界：SPI 介面的 flash memory。

（責任編輯：賴佩萱）
