0 摘要
M24256 是一個256k的存盤芯片,本文將主要講解如何采用模擬IIC實作對M24256的讀寫驅動操作,并且使用Proteus進行仿真驗證,處理器采用STM32F103,使用STM32CubeMX和Keil5進行聯合開發,
1 所使用的軟體
- Proteus 8.9 SP2
鏈接:https://pan.baidu.com/s/1Mnc5M0A5rOIQ2xrPT96ugw
提取碼:dfct
- Keil5
鏈接:https://pan.baidu.com/s/1Aavx3TkvBSLrLxlFOZ7xPw
提取碼:uagc
- STM32CubeMX
https://www.st.com/en/development-tools/stm32cubemx.html
2 M24256介紹
M24256是ST公司的一款256k EEPROM存盤芯片,其具有以下特點,
- M24256具有256kbit EEPROM內容,每頁可寫入的內容為64bytes(Page Size = 64 bytes)
- Single supply voltage and high speed
- Write:
- – Byte Write within 5 ms
- – Page Write within 5 ms
- Random and sequential Read modes
- Write protect of the whole memory array 所有記憶體整列均可以進行寫保護
- Enhanced ESD/Latch-Up protection
- More than 4 million Write cycles
- More than 200-years data retention
M24256引腳介面如表2-1所示:
表2-1 芯片引腳定義
Signal name | Function | Direction |
E2、E1、E0 | Chip Enable | Input |
SDA | Serial Data | I/O |
SCL | Serial Clock | Input |
WC(低電平有效) | Write Control | Input |
VCC | Supply voltage |
|
VSS | Ground |
|
通過控制E2、E1、E0的電平關系來修改芯片的地址,也就是說每一個IIC總線上最多可以掛接8個M24256存盤芯片,
Write Control引腳用于保護寫操作,可以用來保護存盤器的整個內容免受意外寫操作,將寫控制(WC)驅動為高電平時,將禁止對整個存盤器陣列進行寫操作, 當寫控制(WC)被驅動為低電平或懸空時,使能寫操作, 將寫控制(WC)驅動為高電平時,確認器件選擇和地址位元組,不確認資料位元組,
3 M24256設備地址
表3-1 芯片地址(設備選擇代碼)
通過硬體電路定義E2、E1、E0的電平來定義設備的地址,其中最低位為讀寫標志位,當bit0=1時處于Read模式,反之處于Write模式,而高八位為固定地址,通常使用的是Memory array情況,所以高八位為A
如果在設備選擇代碼上發生匹配,則相應的設備會在第9位時間內給出串行資料(SDA)的確認, 如果設備與設備選擇代碼不匹配,則會從總線上取消選擇自身,并進入待機模式,
4 M24256寫操作
當芯片處于非寫保護狀態,即WC為0時對應的時序圖如圖4-1所示,
表4-1 M24256寫時序(WC為低電平)
由圖可以看出,M24256支持兩種形式的寫操作,分別是按位元組寫入和按頁寫入,接下來將針對其時序圖逐一進行分析,
4.1 Byte Write Mode
按位元組寫入的時序圖如圖4-2所示,
圖4-2 Byte Write Mode 時序圖
由圖可知,該模式下,設備僅向指定地址中寫入一個位元組的資料,其包含的時序程序如下:
Start | 發送設備地址 1010 E2E1E0 0 | ACK | 待寫入的設備地址高8位 Byte addr | ACK | 待寫入的設備地址低8位 Byte addr | ACK | 待寫入的八位資料 Data in | ACK | Stop |
對應的寫入代碼如下:
uint8_t W24256_Byte_Write(uint8_t WriteData,uint16_t address) { uint16_t usAddr; usAddr = address; /* 第1步:發起I2C總線啟動信號 */ IIC_Start(); /* 第2步:發起控制字節,高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */ IIC_Send_Byte(EEPROM_DEV_ADDR | I2C_WR); /* 此處是寫指令 */ /*第3步:等待ACK信號*/ if (IIC_Wait_Ack() != 0) { goto cmd_fail; /* EEPROM器件無應答 */ } /* 第4步:發送字節地址,發送地址直接高八位*/ IIC_Send_Byte((uint8_t)(usAddr>> 8)); /*第5步:等待ACK信號*/ if (IIC_Wait_Ack() != 0) { goto cmd_fail; /* EEPROM器件無應答 */ } /* 第6步:發送字節地址,發送地址直接低八位*/ IIC_Send_Byte((uint8_t)(usAddr&0x00ff)); /*第7步:等待ACK信號*/ if (IIC_Wait_Ack() != 0) { goto cmd_fail; /* EEPROM器件無應答 */ } /* 第8步:開始寫入數據 */ IIC_Send_Byte(WriteData); /*第7步:等待ACK信號*/ if (IIC_Wait_Ack() != 0) { goto cmd_fail; /* EEPROM器件無應答 */ } IIC_Stop(); return 1; cmd_fail: /* 命令執行失敗后,切記發送停止信號,避免影響I2C總線上其他設備 */ /* 發送I2C總線停止信號 */ IIC_Stop(); return 0; } |
4.2 Page Write Mode
按頁寫入的時序圖如圖4-3所示,
圖4-3 Page Write Mode
由圖可知,該模式下,設備可以向指定頁中寫入指定位元組的資料,可寫入的位元組數小于等于64byte,其包含的時序程序如下:
Start | 發送設備地址 1010 E2E1E0 0 | ACK | 待寫入的設備地址高8位 Byte addr | ACK | 待寫入的設備地址低8位 Byte addr | ACK | 待寫入的八位資料 Data in | 如果繼續寫入,則ACK 停止寫入,則NACK | STOP |
對應的按頁寫入代碼如下:
uint8_t W24256_Page_Write(uint8_t *WriteBuf, uint16_t Page, uint16_t Size) { uint16_t i,m; uint16_t usAddr;
/* * 寫串行EEPROM不像讀操作可以連續讀取很多字節,每次寫操作只能在同一個page, * 對于24xx02,page size = 8 * 簡單的處理方法為:按字節寫操作模式,沒寫1個字節,都發送地址 * 為了提高連續寫的效率: 本函數采用page wirte操作, */
usAddr = Page * 0x0040; for (i = 0; i < Size; i++) { /* 當發送第1個字節或是頁面首地址時,需要重新發起啟動信號和地址 */ if ((i == 0) || (usAddr & (EEPROM_PAGE_SIZE - 1)) == 0) { // /* 第0步:發停止信號,啟動內部寫操作 */ // IIC_Stop();
/* 通過檢查器件應答的方式,判斷內部寫操作是否完成, 一般小于 10ms CLK頻率為200KHz時,查詢次數為30次左右 */ for (m = 0; m < 1000; m++) { /* 第1步:發起I2C總線啟動信號 */ IIC_Start();
/* 第2步:發起控制字節,高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */ IIC_Send_Byte(EEPROM_DEV_ADDR | I2C_WR); /* 此處是寫指令 */
/* 第3步:發送一個時鐘,判斷器件是否正確應答 */ if (IIC_Wait_Ack() == 0) { break; } } if (m == 1000) { goto cmd_fail; /* EEPROM器件寫超時 */ }
/* 第4步:發送字節地址,發送地址直接高八位*/ IIC_Send_Byte((uint8_t)(usAddr>> 8)); /*第五步:等待ACK信號*/ if (IIC_Wait_Ack() != 0) { goto cmd_fail; /* EEPROM器件無應答 */ } /* 第6步:發送字節地址,發送地址直接低八位*/ IIC_Send_Byte((uint8_t)(usAddr&0x00ff)); /* 第5步:等待ACK */ if (IIC_Wait_Ack() != 0) { goto cmd_fail; /* EEPROM器件無應答 */ } }
/* 第6步:開始寫入數據 */ IIC_Send_Byte(WriteBuf[i]);
/* 第7步:發送ACK */ if (IIC_Wait_Ack() != 0) { goto cmd_fail; /* EEPROM器件無應答 */ }
usAddr++; /* 地址增1 */ }
/* 命令執行成功,發送I2C總線停止信號 */ IIC_Stop(); return 1;
cmd_fail: /* 命令執行失敗后,切記發送停止信號,避免影響I2C總線上其他設備 */ /* 發送I2C總線停止信號 */ IIC_Stop(); return 0; } |
注:M24256有256kbit空間,每一頁的大小Page Size =64,所以計算可得頁的取值范圍為:256*1024/8/64 = 512 頁,
5 M24256讀操作
WC引腳的電平狀態對讀操作無效,所以其對應的時序圖入圖5-1所示,
圖5-1 Read mode sequences
由圖5-1可知,M24256共有三種模式的讀操作,包括隨機地址讀取(Random Address Read)、當前地址(Current Address Read)、順序讀取(Sequential Read)
下面主要針對隨機地址讀取和順序讀取兩種模式進行分析,其余分析類似,
5.1 Random Address Read
圖5-2 Random Address Read 時序圖
由圖可知,該模式下,僅從設備的指定地址中讀取一個位元組的資料,其包括的時序如下:
Start | 設備地址和控制字 1010 E2E1E0 0 | ACK | 待寫入的設備地址高8位 Byte addr | ACK | 待寫入的設備地址低8位 Byte addr | ACK | Start 重啟IIC總線 | 設備地址和控制字 1010 E2E1E0 1 | ACK | 讀出的資料 Data out | NACK | Stop |
對應的代碼如下:
uint8_t W24256_Byte_Read( uint16_t Address) { uint16_t uAddress; uint8_t ReadData; uAddress = Address; /* 第1步:發起I2C總線啟動信號 */ IIC_Start();
/* 第2步:發起控制字節,高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */ IIC_Send_Byte(EEPROM_DEV_ADDR | I2C_WR); /* 此處是寫指令 */
/* 第3步:等待ACK */ if (IIC_Wait_Ack() != 0) { IIC_Stop(); /* EEPROM器件無應答 */ }
/* 第4步:發送字節地址高8位 */ IIC_Send_Byte((uint8_t)(uAddress>>8));
/* 第5步:等待ACK */ if (IIC_Wait_Ack() != 0) { IIC_Stop(); /* EEPROM器件無應答 */ } /* 第6步:發送字節地址低八位 */ IIC_Send_Byte((uint8_t)uAddress&0xff);
/* 第7步:等待ACK */ if (IIC_Wait_Ack() != 0) { IIC_Stop(); /* EEPROM器件無應答 */ } /* 第8步:重新啟動I2C總線,前面的代碼的目的向EEPROM傳送地址,下面開始讀取數據 */ IIC_Start();
/* 第9步:發起控制字節,高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */ IIC_Send_Byte(EEPROM_DEV_ADDR | I2C_RD); /* 此處是讀指令 */
/* 第10步:發送ACK */ if (IIC_Wait_Ack() != 0) { IIC_Stop(); /* EEPROM器件無應答 */ }
/* 第11步:讀取數據并保存*/ ReadData = https://www.cnblogs.com/Mr-Wangblogs/p/IIC_Read_Byte(); /* 讀1個字節 */ /*第12步:發送NACK命令*/ IIC_NAck(); /* 最后1個字節讀完后,CPU產生NACK信號(驅動SDA = 1) */
/*第13步:發送I2C總線停止信號 */ IIC_Stop(); return ReadData; /* 執行成功 */ } |
5.2 Sequention Random Read
圖5-3 Sequention Random Read 時序圖
由圖可知,該模式下,可以向指定地址中讀取指定數目的資料,其包括的時序如下:
Start | 設備地址和控制字 1010 E2E1E0 0 | ACK | 待寫入的設備地址高8位 Byte addr | ACK | 待寫入的設備地址低8位 Byte addr | ACK | Start 重啟IIC總線 | 設備地址和控制字 1010 E2E1E0 1 | ACK | 讀出的資料 Data out | 如果到達要讀取資料個數,發送NACK,反之發送ACK | Stop |
其對應的代碼如下:
/** * 函數功能: 從串行EEPROM指定地址處開始讀取若干數據 * 輸入引數: ReadBuf : 存放讀到的數據的緩沖區指針 * Address : 起始地址 * Size : 數據長度,單位為字節 * 返 回 值: 0 表示失敗,1表示成功 * 說 明:無 */ uint8_t W24256_Page_Read(uint8_t *ReadBuf, uint16_t Page, uint16_t Size) { uint16_t i; uint16_t uAddress; /* 采用串行EEPROM隨即讀取指令序列,連續讀取若干字節 */ uAddress = Page * 0x0040; /* 第1步:發起I2C總線啟動信號 */ IIC_Start();
/* 第2步:發起控制字節,高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */ IIC_Send_Byte(EEPROM_DEV_ADDR_Page | I2C_WR); /* 此處是寫指令 */
/* 第3步:等待ACK */ if (IIC_Wait_Ack() != 0) { goto cmd_fail; /* EEPROM器件無應答 */ }
/* 第4步:發送字節地址高8位 */ IIC_Send_Byte((uint8_t)(uAddress>>8));
/* 第5步:等待ACK */ if (IIC_Wait_Ack() != 0) { goto cmd_fail; /* EEPROM器件無應答 */ } /* 第6步:發送字節地址低八位 */ IIC_Send_Byte((uint8_t)uAddress&0xff);
/* 第7步:等待ACK */ if (IIC_Wait_Ack() != 0) { goto cmd_fail; /* EEPROM器件無應答 */ } /* 第8步:重新啟動I2C總線,前面的代碼的目的向EEPROM傳送地址,下面開始讀取數據 */ IIC_Start();
/* 第7步:發起控制字節,高7bit是地址,bit0是讀寫控制位,0表示寫,1表示讀 */ IIC_Send_Byte(EEPROM_DEV_ADDR_Page | I2C_RD); /* 此處是讀指令 */
/* 第8步:發送ACK */ if (IIC_Wait_Ack() != 0) { goto cmd_fail; /* EEPROM器件無應答 */ }
/* 第9步:循環讀取數據 */ for (i = 0; i < Size; i++) { ReadBuf[i] = IIC_Read_Byte(); /* 讀1個字節 */
/* 每讀完1個字節后,需要發送Ack, 最后一個字節不需要Ack,發Nack */ if (i != Size - 1) { IIC_Ack(); /* 中間字節讀完后,CPU產生ACK信號(驅動SDA = 0) */ } else { IIC_NAck(); /* 最后1個字節讀完后,CPU產生NACK信號(驅動SDA = 1) */ } } /* 發送I2C總線停止信號 */ IIC_Stop(); return 1; /* 執行成功 */
cmd_fail: /* 命令執行失敗后,切記發送停止信號,避免影響I2C總線上其他設備 */ /* 發送I2C總線停止信號 */ IIC_Stop(); return 0; } |
6 M24256讀寫測驗
使用Proteus 和Stm32CubeMX keil 聯合開發,對M24256的讀寫測驗進行仿真分析,
圖6-1 仿真搭建
6.1 按位元組讀寫測驗結果
代碼如下
W24256_Byte_Write(0x01,0x0000); HAL_Delay(100); W24256_Byte_Read(0x0000); HAL_Delay(500); |
圖6-2 仿真結果
第一行 | S | A0 | A | 00 | A | 00 | A | 01 | A | P | 向1101 000x設備的0x0000地址寫入0x01資料 |
第二行 | S | A0 | A | 00 | A | 00 | A | Sr | A1 | A | 01 | N | P | 從1101 000x設備的0x0000地址讀出資料,讀出的資料為0x01 |
6.2 按頁讀寫測驗結果
uint8_t Data[3]={0x01,0x05,0xff}; uint8_t DataRead[3]={0x00,0x00,0x00}; W24256_Page_Write(Data,10,3); HAL_Delay(100); W24256_Page_Read(DataRead,10,3); HAL_Delay(500); |
圖6-3 仿真結果
第一行 | S | A0 | A | 02 | A | 80 | A | 01 | A | 05 | A | FF | A | P | 向1101 000x設備的第10頁(0X0280)寫入0x01、0X05、0XFF三個位元組資料 |
第二行 | S | A0 | A | 02 | A | 80 | A | Sr | A1 | A | 01 | A | 05 | A | FF | N | P | 從1101 000x 設備的第10頁(0x0280)讀取3個位元組資料,讀出的資料為 0x01、0x05、0xff |
6.3 按位元組讀寫多個位元組測驗
uint8_t Data[3]={0x01,0x05,0xff}; uint8_t DataRead[3]={0x00,0x00,0x00}; W24256_Write(0x0000,Data,3); HAL_Delay(100); W24256_Read(0x0000,DataRead,3); HAL_Delay(500); |
圖6-4 仿真結果
第一行 | S | A0 | A | 00 | A | 00 | A | 01 | A | P | 向1010 000x設備的0x0000地址寫入0x01資料 |
第二行 | S | A0 | A | 00 | A | 01 | A | 05 | A | P | 向1010 000x設備的0x0001地址寫入0x05資料 |
第三行 | S | A0 | A | 00 | A | 02 | A | FF | A | P | 向1010 000x設備的0x0002地址寫入0xFF資料 |
第四行 | S | A0 | A | 00 | A | 00 | A | Sr | A1 | A | 01 | N | P | 從1010 000x設備的0x0000地址讀取資料,結果為0x01 |
第五行 | S | A0 | A | 00 | A | 01 | A | Sr | A1 | A | 05 | N | P | 從1010 000x設備的0x0001地址讀取資料,結果為0x05 |
第六行 | S | A0 | A | 00 | A | 02 | A | Sr | A1 | A | FF | N | P | 從1010 000x設備的0x0002地址讀取資料,結果為0xFF |
制作不易,如有錯誤或者不好理解的地方請留言
如果需要仿真源檔案,請聯系EMAIL:[email protected]
并添加QQ:975107705
請注明M24256 讀寫測驗
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/20760.html
標籤:C++
上一篇:未來世界
