一、EEPROM芯片
ROM | RAM |
断电后数据保留 | 断电后数据消失 |
因此,如果在断电后希望数据继续保留的话,就需要存储在EEPROM芯片中。
二、EEPROM芯片原理图
- A0~A2与芯片地址相关连接到GND,为0
- GND 接地,VCC 正电源
- WP——write protect写保护,连接到地,意味着可以被自由写入(连接到高电平无法被写入)
- scl,sda说明采用iic协议进行通信
前七位固定不变,最后一位是0或1,write是0,read是1
所以写入地址是:0xA0 读取地址是:0xA1
因为地址不同,所以都采用iic协议也不会有冲突。
三、写入读取方式
1.写入方式
- start 开始信号
- DEVICE ADDRESS 地址
- R/W 低电平是写,高电平是读
- ACK 应答位
- WORD ADDRESS 写入的位置
- ACK 应答位
- DATA写入相关数据
- ACK 应答位
- STOP 终止
2.读取方式
- start 开始信号
- DEVICE ADDRESS 设备地址
- R/W 低电平是写,高电平是读
- ACK 应答位
- WORD ADDRESS 读取的位置
- ACK 应答位
- start 再次发送开始信号
- DEVICE ADDRESS 设备地址
- READ 进入读模式
- ACK 应答位
- DATA将指定地址上的数据返回回来
- NO ACK没有应答
- STOP 终止
四、开发板位置
五、模块代码
#include "iic.h"
#define DELAY_TIME 5
//
static void I2C_Delay(unsigned char n)
{
do
{
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();
}
while(n--);
}
//
void I2CStart(void)
{
sda = 1;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 0;
I2C_Delay(DELAY_TIME);
scl = 0;
}
//
void I2CStop(void)
{
sda = 0;
scl = 1;
I2C_Delay(DELAY_TIME);
sda = 1;
I2C_Delay(DELAY_TIME);
}
//
void I2CSendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++){
scl = 0;
I2C_Delay(DELAY_TIME);
if(byt & 0x80){
sda = 1;
}
else{
sda = 0;
}
I2C_Delay(DELAY_TIME);
scl = 1;
byt <<= 1;
I2C_Delay(DELAY_TIME);
}
scl = 0;
}
//
unsigned char I2CReceiveByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++){
scl = 1;
I2C_Delay(DELAY_TIME);
da <<= 1;
if(sda)
da |= 0x01;
scl = 0;
I2C_Delay(DELAY_TIME);
}
return da;
}
//
unsigned char I2CWaitAck(void)
{
unsigned char ackbit;
scl = 1;
I2C_Delay(DELAY_TIME);
ackbit = sda;
scl = 0;
I2C_Delay(DELAY_TIME);
return ackbit;
}
//
void I2CSendAck(unsigned char ackbit)
{
scl = 0;
sda = ackbit;
I2C_Delay(DELAY_TIME);
scl = 1;
I2C_Delay(DELAY_TIME);
scl = 0;
sda = 1;
I2C_Delay(DELAY_TIME);
}
unsigned char PCF8591_ADC(void)
{
unsigned char temp;
/**********************写入**********************/
I2CStart();//开始
I2CSendByte(0x90);//发送写地址
I2CWaitAck();//等待应答
I2CSendByte(0x43);//发送光敏电阻控制位
I2CWaitAck();//等待应答
/**********************读取**********************/
I2CStart();//开始
I2CSendByte(0x91);//发送读地址
I2CWaitAck();//等待应答
temp=I2CReceiveByte();//接收
I2CSendAck(1);//发送应答
I2CStop();//终止通信
return temp;
}
void PCF8591_DAC(unsigned char dat)
{
I2CStart();//开始
I2CSendByte(0x90);//发送写地址
I2CWaitAck();//等待应答
I2CSendByte(0x41);//发送光敏电阻控制位
I2CWaitAck();//等待应答
I2CSendByte(dat);//发送光敏电阻控制位
I2CWaitAck();//等待应答
I2CStop();
}
void EEPROM_Read(unsigned char *pucRuf,unsigned char addr,unsigned char num)
{
I2CStart();
I2CSendByte(0xA0);//发送设备地址
I2CWaitAck();//等待应答
I2CSendByte(addr);//发送写入位置
I2CWaitAck();
I2CStart();
I2CSendByte(0xA1);//发送读取地址
I2CWaitAck();
while(num--)
{
*pucRuf++= I2CReceiveByte();
if(num)
I2CSendAck(0);
else
I2CSendAck(1);
}
I2CStop();//终止通信
}
void EEPROM_Write(unsigned char *pucRuf,unsigned char addr,unsigned char num)
{
I2CStart();
I2CSendByte(0xA0);//发送设备地址
I2CWaitAck();//等待应答
I2CSendByte(addr);//发送读取位置
I2CWaitAck();
while(num--)
{
I2CSendByte(*pucRuf++);
I2CWaitAck();
I2C_Delay(200);//加入延时,不至于导致总线过于繁忙,有助于总线稳定性
}
I2CStop();//终止通信
}