一、前言
1.1 功能介紹
在嵌入式系統(tǒng)設計中,數(shù)據(jù)的存儲與讀取是至關(guān)重要的一環(huán)。隨著技術(shù)的不斷發(fā)展,對存儲設備的性能、容量和可靠性要求也越來越高。EEPROM(電可擦除可編程只讀存儲器)作為一種非易失性存儲介質(zhì),以其數(shù)據(jù)存儲可靠、功耗低、讀取速度快等特點,廣泛應用于各種嵌入式系統(tǒng)中。本項目在利用STC90C51單片機和EEPROM-AT24C02存儲器芯片實現(xiàn)高效的數(shù)據(jù)讀寫存儲功能,以滿足現(xiàn)代嵌入式系統(tǒng)對數(shù)據(jù)存儲的需求。
本項目的主要目標是通過STC90C51單片機與EEPROM-AT24C02存儲器芯片的配合使用,實現(xiàn)以下功能:
- 數(shù)據(jù)寫入:通過STC90C51單片機向EEPROM-AT24C02存儲器芯片中寫入數(shù)據(jù),實現(xiàn)數(shù)據(jù)的非易失性存儲。EEPROM-AT24C02存儲容量為2Kbit(即256字節(jié)),足夠滿足大多數(shù)嵌入式系統(tǒng)對數(shù)據(jù)存儲的需求。
- 數(shù)據(jù)讀取:STC90C51單片機能夠從EEPROM-AT24C02存儲器芯片中讀取已存儲的數(shù)據(jù),并在需要時進行處理或使用。由于EEPROM-AT24C02的讀取速度快,能夠保證數(shù)據(jù)訪問的高效性。
1.2 AT24C02介紹
AT24C02是一款串行EEPROM(電可擦除可編程只讀存儲器)芯片,由CATALYST公司(或Atmel公司,因品牌收購關(guān)系)生產(chǎn),廣泛應用于各種電子設備中,特別是那些需要數(shù)據(jù)存儲和參數(shù)保存的場景。
以下是關(guān)于AT24C02的詳細介紹:
主要技術(shù)參數(shù)
- 存儲容量:2Kbit(256個8位字節(jié)),適合存儲少量但重要的數(shù)據(jù)。
- 工作電壓范圍:1.8V至5.5V,寬電壓范圍使得AT24C02能夠適應不同的電源供電情況。
- 通信接口:I2C串行總線接口,通過兩根總線(串行數(shù)據(jù)線SDA和串行時鐘線SCL)與微處理器或其他設備進行通信。
- 存儲速率:可達400KHz,提供較快的數(shù)據(jù)傳輸速度。
- 可擦寫次數(shù):高達100萬次,確保長期使用的可靠性。
- 存儲器保持時間:至少10年,保證數(shù)據(jù)長時間存儲的穩(wěn)定性。
- 工作溫度范圍:雖然不同資料給出的溫度范圍略有差異,但一般可認為是-40℃至+85℃或-55℃至+125℃,適應各種工作環(huán)境。
主要特點
- 低功耗:采用先進的CMOS技術(shù),功耗極低,適用于電池供電等低功耗應用場景。
- 高可靠性:內(nèi)部具有校驗和功能,可以檢測和糾正數(shù)據(jù)傳輸中的錯誤,提高數(shù)據(jù)傳輸?shù)目煽啃浴?/li>
- 多種封裝形式:提供DIP、SOP、TSSOP等多種封裝形式,方便用戶根據(jù)實際需求選擇。
- 易于使用:通過I2C總線接口與微處理器進行通信,簡化了與主機的連接和數(shù)據(jù)傳輸過程。
應用領(lǐng)域
AT24C02廣泛應用于各種需要數(shù)據(jù)存儲和參數(shù)保存的領(lǐng)域:
- 工業(yè)控制:用于存儲和讀取PLC程序、傳感器數(shù)據(jù)等。
- 儀器儀表:用于存儲電子秤、溫度計、壓力計等設備的校準參數(shù)。
- 網(wǎng)絡通信:用于存儲MAC地址、序列號等數(shù)據(jù)。
- 汽車電子:用于存儲汽車門鎖控制、氣囊控制等信息。
二、代碼實現(xiàn)
2.1 main.c
#include <reg51.h>
#include "delay.h"
#include "key.h"
#include "type.h"
#include "led.h"
#include "uart.h"
#include "timer.h"
#include "exti.h"
#include "infrared.h"
#include "ds18b20.h"
#include "at24c02.h"
//u8 at24c02_w[8]="1234567";
//u8 at24c02_r[8];
int main()
{
u8 dat;
UART_Init(); //初始化串口波特率為4800
while(1)
{
//單個字節(jié)讀寫測試
AT24C02_WriteOneByte(5,0xAA);
dat=AT24C02_ReadOneByte(5);
printf("dat=%drn",(int)dat);
//多個字節(jié)讀寫測試
// AT24C02_WriteByte(0,8,at24c02_w);
// AT24C02_ReadByte(0,8,at24c02_r);
// printf("at24c02_r=%srn",at24c02_r);
DelayMs(1000);
}
}
2.2 AT24C02.c
#include "at24c02.h"
#include "iic.h"
/*
函數(shù)功能: 寫一個字節(jié)
函數(shù)參數(shù):
u8 addr 數(shù)據(jù)的位置(0~255)
u8 dat 數(shù)據(jù)范圍(0~255)
*/
void AT24C02_WriteOneByte(u16 addr,u8 dat)
{
IIC_SendStart();//起始信號
IIC_SendOneByte(AT24C02_WRITE_ADDR);//發(fā)送設備地址
IIC_GetAck();//獲取應答
IIC_SendOneByte(addr); //數(shù)據(jù)存放的地址
IIC_GetAck();//獲取應答
IIC_SendOneByte(dat); //發(fā)送將要存放的數(shù)據(jù)
IIC_GetAck();//獲取應答
IIC_SendStop(); //停止信號
DelayMs(10); //等待寫
}
/*
函數(shù)功能: 讀一個字節(jié)
函數(shù)參數(shù):
u8 addr 數(shù)據(jù)的位置(0~255)
返回值: 讀到的數(shù)據(jù)
*/
u8 AT24C02_ReadOneByte(u16 addr)
{
u8 dat=0;
IIC_SendStart();//起始信號
IIC_SendOneByte(AT24C02_WRITE_ADDR);//發(fā)送設備地址
IIC_GetAck();//獲取應答
IIC_SendOneByte(addr); //將要讀取數(shù)據(jù)的地址
IIC_GetAck();//獲取應答
IIC_SendStart();//起始信號
IIC_SendOneByte(AT24C02_READ_ADDR);//發(fā)送設備地址
IIC_GetAck();//獲取應答
dat=IIC_RecvOneByte();//讀取數(shù)據(jù)
IIC_SendAck(1); //發(fā)送非應答
IIC_SendStop(); //停止信號
return dat;
}
/*
函數(shù)功能: 從指定位置讀取指定長度的數(shù)據(jù)
函數(shù)參數(shù):
u16 addr 數(shù)據(jù)的位置(0~255)
u16 len 讀取的長度
u8 *buffer 存放讀取的數(shù)據(jù)
返回值: 讀到的數(shù)據(jù)
*/
void AT24C02_ReadByte(u16 addr,u16 len,u8 *buffer)
{
u16 i=0;
IIC_SendStart();//起始信號
IIC_SendOneByte(AT24C02_WRITE_ADDR);//發(fā)送設備地址
IIC_GetAck();//獲取應答
IIC_SendOneByte(addr); //將要讀取數(shù)據(jù)的地址
IIC_GetAck();//獲取應答
IIC_SendStart();//起始信號
IIC_SendOneByte(AT24C02_READ_ADDR);//發(fā)送設備地址
IIC_GetAck();//獲取應答
for(i=0;i<len;i++)
{
buffer[i]=IIC_RecvOneByte();//讀取數(shù)據(jù)
if(i<len-1)IIC_SendAck(0); //發(fā)送應答
else IIC_SendAck(1); //發(fā)送非應答
}
IIC_SendStop(); //停止信號
}
/*
函數(shù)功能: AT24C02頁寫函數(shù)
函數(shù)參數(shù):
u16 addr 寫入的位置(0~1023)
u8 len 寫入的長度(每頁16字節(jié))
u8 *buffer 存放讀取的數(shù)據(jù)
*/
void AT24C02_PageWrite(u16 addr,u16 len,u8 *buffer)
{
u16 i=0;
IIC_SendStart();//起始信號
IIC_SendOneByte(AT24C02_WRITE_ADDR);//發(fā)送設備地址
IIC_GetAck();//獲取應答
IIC_SendOneByte(addr); //數(shù)據(jù)存放的地址
IIC_GetAck();//獲取應答
for(i=0;i<len;i++)
{
IIC_SendOneByte(buffer[i]); //發(fā)送將要存放的數(shù)據(jù)
IIC_GetAck();//獲取應答
}
IIC_SendStop(); //停止信號
DelayMs(10); //等待寫
}
/*
函數(shù)功能: 從指定位置寫入指定長度的數(shù)據(jù)
函數(shù)參數(shù):
u16 addr 數(shù)據(jù)的位置(0~255)
u16 len 寫入的長度
u8 *buffer 存放即將寫入的數(shù)據(jù)
返回值: 讀到的數(shù)據(jù)
*/
void AT24C02_WriteByte(u16 addr,u16 len,u8 *buffer)
{
u8 page_byte=8-addr%8; //得到當前頁剩余的字節(jié)數(shù)量
if(page_byte>len) //判斷當前頁剩余的字節(jié)空間是否夠?qū)?
{
page_byte=len; //表示一次性可以寫完
}
while(1)
{
AT24C02_PageWrite(addr,page_byte,buffer); //寫一頁
if(page_byte==len)break; //寫完了
buffer+=page_byte; //指針偏移
addr+=page_byte;//地址偏移
len-=page_byte;//得到剩余沒有寫完的長度
if(len>8)page_byte=8;
else page_byte=len; //一次可以寫完
}
}
2.3 AT24C02.h
#ifndef _AT24C02_H_
#define _AT24C02_H_
#include <reg51.h>
#include "delay.h"
#include "type.h"
//地址
#define AT24C02_WRITE_ADDR 0xA0
#define AT24C02_READ_ADDR 0xA1
//函數(shù)聲明
void AT24C02_WriteOneByte(u16 addr,u8 dat);
u8 AT24C02_ReadOneByte(u16 addr);
void AT24C02_WriteByte(u16 addr,u16 len,u8 *buffer);
void AT24C02_PageWrite(u16 addr,u16 len,u8 *buffer);
void AT24C02_ReadByte(u16 addr,u16 len,u8 *buffer);
#endif