通过I2C总线读取EEPROM内存中某地址的单字节数据并显示在1602LCD屏上

读取数据过程:

 

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

生成海报
点赞 0

横着望的猫

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

基于8051单片机实现电子时钟+数字秒表设计

概述 电子时钟是一种利用数字电路来显示秒、分、时的计时装置,与传统的机械钟相比,它具有走时准确、显 示直观、无机械传动装置等优点,因而得到广泛应用。随着人们生活环境的不断改善和美化,在许

嵌入式系统原理及应用(复习总结)

第一章 嵌入式系统概论 嵌入式系统的定义: 以应用为中心,以计算机技术为基础,软件硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。 可以从以下几个方面

51单片机通过驱动器精准控制步进电机

51单片机驱动器控制步进电机 文章简介 本文是前段时间玩步进电机精准控制的总结,关于51单片机驱动步进电机的程序(用脉冲频率控制)及接线方法。 1.驱动器简介 如图所示,以下为两相电机

51蓝牙红外循迹避障小车+代码

设计背景: 本次设计主要是为了学校的一个电子竞赛才做的这一个小项目,这也是我刚学习51单片机以来做的第一个大制作。其实这个制作的原理很简单,但实际做出来却花了一些时间,下面就简单地给大家