读取数据过程:
1.发送一个起始信号
2.发送EEPROM器件地址
3.发送EEPROM片内地址(告诉EEPROM要读取的数据的地址)
4.重新发送起始信号和器件地址,并在方向位选择“读”操作
5.读取数据
6.发送结束信号
写数据时应答信号由从机给出,表示从机是否正确接收了数据;读数据时应答信号则由主机给出,表示是否继续读下去。
主机在读取数据时发送非应答信号表示不需要再读取,发送应答信号表示继续读取,这里我们只读取单字节数据,所以读取后发送非应答信号。
LCD1602代码:
#include<reg52.h>
#define LCD1602_DB P0
sbit LCD1602_RS=P1^0;
sbit LCD1602_RW=P1^1;
sbit LCD1602_E=P1^5;
void LcdReady()
{
unsigned char sta;
LCD1602_RS=0;
LCD1602_RW=1;
LCD1602_DB=0xFF;
do
{
LCD1602_E=1;
sta=LCD1602_DB;
LCD1602_E=0;
}while(sta & 0x80);
}
void LcdWriteCMD(unsigned char cmd)
{
LCD1602_RS=0;
LCD1602_RW=0;
LCD1602_DB=cmd;
LCD1602_E=1;
LCD1602_E=0;
}
void LcdWriteDAT(unsigned char dat)
{
LCD1602_RS=1;
LCD1602_RW=0;
LCD1602_DB=dat;
LCD1602_E=1;
LCD1602_E=0;
}
void LcdSetRAM(unsigned char x,unsigned char y)
{
unsigned char addr;
if(y==0)
{
addr=0x00+x;
}
else
{
addr=0x40+x;
}
LcdWriteCMD(addr | 0x80);
}
void LcdShow(unsigned char x,unsigned char y,unsigned char *str)
{
LcdSetRAM(x,y);
while(*str!='\0')
{
LcdWriteDAT(*str++);
}
}
void InitLcd1602()
{
LcdWriteCMD(0x38);
LcdWriteCMD(0x0C);
LcdWriteCMD(0x01);
LcdWriteCMD(0x06);
}
I2C总线代码:
#include<reg52.h>
#include<intrins.h>
#define I2CDelay() {_nop_();_nop_();_nop_();_nop_();} //延时函数
sbit I2C_SCL=P1^7;
sbit I2C_SDA=P1^6;
void I2CStart() //起始信号
{
I2C_SCL=1;
I2C_SDA=1;
I2CDelay();
I2C_SDA=0;
I2CDelay();
I2C_SCL=0;
}
void I2CStop() //结束信号
{
I2C_SDA=0;
I2C_SCL=0;
I2CDelay();
I2C_SCL=1;
I2CDelay();
I2C_SDA=1;
I2CDelay();
}
bit I2CWrite(unsigned char dat) //写入数据并接受应答信号
{
bit ack;
unsigned char mask;
for(mask=0x80;mask!=0;mask>>=1)
{
if((mask&dat)==0)
I2C_SDA=0;
else
I2C_SDA=1;
I2CDelay();
I2C_SCL=1;
I2CDelay();
I2C_SCL=0;
}
I2C_SDA=1;
I2CDelay();
I2C_SCL=1;
ack=I2C_SDA;
I2CDelay();
I2C_SCL=0;
return (~ack);
}
unsigned char I2CReadNAK() //读取数据并返回非应答信号
{
unsigned char dat;
unsigned char mask;
I2C_SDA=1;
for(mask=0x80;mask!=0;mask>>=1)
{
I2CDelay();
I2C_SCL=1;
if(I2C_SDA==0)
dat &=~mask;
else
dat |=mask;
I2CDelay();
I2C_SCL=0;
}
I2C_SDA=1;
I2CDelay();
I2C_SCL=1;
I2CDelay();
I2C_SCL=0;
return dat;
}
主函数代码:
#include<reg52.h>
extern void InitLcd1602();
extern void LcdShow(unsigned char x,unsigned char y,unsigned char *str);
extern void I2CStart();
extern void I2CStop();
extern bit I2CWrite(unsigned char dat);
extern unsigned char I2CReadNAK();
extern unsigned char I2CReadACK();
unsigned char E2ReadByte(unsigned char addr); //读取数据
void main()
{
unsigned char dat;
unsigned char str[10];
InitLcd1602(); //初始化屏幕
dat = E2ReadByte(0x02); //将0x02地址的数据读取出来
str[0] = (dat/100) + '0';
str[1] = (dat/10%10) + '0';
str[2] = (dat%10) + '0';
str[3] = '\0';
LcdShow(0, 0, str); //显示在屏幕上
while (1);
}
unsigned char E2ReadByte(unsigned char addr)
{
unsigned char dat;
I2CStart();
I2CWrite(0x50<<1); //读取地址为0x50的器件
I2CWrite(addr);
I2CStart();
I2CWrite((0x50<<1) | 0x01); //再次发送器件地址并选择“读”操作
dat=I2CReadNAK();
I2CStop();
return dat;
}
以上是全部代码,还可拓展为写入或读取多字节数据,只需修改接受数据时返回的非应答信号改为应答信号即可
版权声明:本文为CSDN博主「横着望的猫」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_65029021/article/details/122581363
暂无评论