单片机:EEPROM(IIC总线)

I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。

在这里插入图片描述
I2C总线通过上拉电阻接正电源。当总线空闲时,两根线均为高电平。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。
2.png
在这里插入图片描述
每个接到I2C总线上的器件都有唯一的地址。主机与其它器件间的数据传送可以是由主机发送数据到其它器件,这时主机即为发送器。由总线上接收数据的器件则为接收器。
起始和终止信号
SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。
起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态。
接收器件收到一个完整的数据字节后,有可能需要完成一些其它工作,如处理内部中断服务等,可能无法立刻接收下一个字节,这时接收器件可以将SCL线拉成低电平,从而使主机处于等待状态。直到接收器件准备好接收下一个字节时,再释放SCL线使之为高电平,从而使数据传送可以继续进行。
3.png
在这里插入图片描述在这里插入图片描述
4.png

AT24CXX存储器工作原理

  • 与400KHz I2C总线兼容
  • 1.8到6.0伏工作电压范围
  • 低功耗CMOS技术
  • 写保护功能当WP为高电平时进入写保护状态
  • 页写缓冲器
  • 自定时擦写周期
  • 100万次编程/擦除周期
  • 可保存数据100年
  • 8脚DIP SOIC或TSSOP封装
  • 温度范围商业级和工业级

5.png
在这里插入图片描述
6.png
在这里插入图片描述
总线时序
7.png
在这里插入图片描述
8.png
在这里插入图片描述
9.png

在这里插入图片描述

代码:

实现:
k1:数码管数据存储到at24c01中
k2:显示at24c01中存储数据
k3:数码管数据加一
k4:数码管显示数据清零

main.c

#include "reg52.h"
#include "i2c.h"

typedef unsigned char u8;
typedef unsigned int u16;

sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

u8 code smgduan[]={
	0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71
};
u8 num=0,disp[4];
void delayus(u16 i)
{
		while(i--);
}
void keyPros()
{
	if(k1==0)
	{
		delayus(1000);
		if(k1==0)
		{
			at24c02Write(1,num);  //写入地址1
		}
		while(!k1);
	}
	if(k2==0)
	{
		delayus(1000);
		if(k2==0)
		{
			num=at24c02Read(1); 
		}
		while(!k2);
	}
	if(k3==0)
	{
		delayus(1000);
		if(k3==0)
		{
			num++;
			if (num >255) num=0;
		}
		while(!k3);
	}
	if(k4==0)
	{
		delayus(1000);
		if(k4==0)
		{
			num=0;
		}
		while(!k4);
	}
}
void dataPros()
{
	disp[0]=smgduan[num/1000];
	disp[1]=smgduan[num%1000/100];
	disp[2]=smgduan[num%100/10];
	disp[3]=smgduan[num%10];
}
void smgDisplay()
{
	u8 i;
	for(i=0;i<4;i++)
	{
		switch(i)
		{
			case(0): LSC=0;LSB=0;LSA=0;break;
			case(1): LSC=0;LSB=0;LSA=1;break;
			case(2): LSC=0;LSB=1;LSA=0;break;	
			case(3): LSC=0;LSB=1;LSA=1;break;	
		}
		P0=disp[3-i];
		delayus(100);
		P0=0x00;
	}
}

void main()
{
	
	while(1)
	{
		keyPros();
		dataPros();
		smgDisplay();
	}
}


i2c.c

#include "i2c.h"

void delay10us(void)   //误差 0us
{
    unsigned char a,b;
    for(b=1;b>0;b--)
        for(a=2;a>0;a--);
}

void i2cStart()
{
	SDA=1;
	delay10us();
	SCL=1;
	delay10us();
	SDA=0;
	delay10us();
	SCL=0;
	delay10us();
}

void i2cStop()
{
	SDA=0;
	delay10us();
	SCL=1;
	delay10us();
	SDA=1;
	delay10us();
}

unsigned char i2cSendByte(unsigned char dat)
{
	unsigned char a=0,b;
	for(a=0;a<8;a++)
	{
		SDA=dat>>7;
		dat=dat<<1;
		delay10us();
		SCL=1; //保持高电平
		delay10us();
		SCL=0;
		delay10us();
	}
	SDA=1;
	delay10us();
	SCL=1;
	while(SDA)
	{
		b++;
		if(b>200)
		{
			SCL=0;
			delay10us();
			return 0;
		}
	}
	SCL=0;
	delay10us();
	return 1;
}

unsigned char i2cReadByte()
{
	unsigned char a=0,dat=0;
	SDA=1;  //使SDA保持空闲状态
	delay10us();
	for(a=0;a<8;a++)
	{
		SCL=1;
		delay10us();
		dat<<=1;
		dat |=SDA;
		delay10us();
		SCL=0;
		delay10us();
	}
	return dat;
}

void at24c02Write(unsigned char addr,unsigned char dat)
{
	i2cStart();
	i2cSendByte(0xa0);
	i2cSendByte(addr);
	i2cSendByte(dat);
	i2cStop();
}

unsigned char at24c02Read(unsigned char addr)
{
	unsigned char num;
	i2cStart();
	i2cSendByte(0xa0);
	i2cSendByte(addr);
	i2cStart();
	i2cSendByte(0xa1);
	num=i2cReadByte();
	i2cStop();
	return num;
}

i2c.h

#ifndef _I2C_H
#define _I2C_H

#include "reg52.h"
sbit SCL=P2^1;
sbit SDA=P2^0;

void at24c02Write(unsigned char addr,unsigned char dat);
unsigned char at24c02Read(unsigned char addr);

#endif
发布了97 篇原创文章 · 获赞 120 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/acktomas/article/details/104259078