手把手教学51单片机第七课 | AT24C02的I²C总线数据传输

SCL(clock)时钟信号
SDA(data)数据总线

数据位的有效性规定

I²C总线进行数据传输时,时钟信号为高电平期间。数据总线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或者低电平状态才允许变化

时序图
手把手教学51单片机第七课 | AT24C02的I²C总线数据传输_第1张图片

起始信号和终止信号

当时钟信号高电平,
SDA变低电平,为起始信号,若SDA变高电平,为终止信号
手把手教学51单片机第七课 | AT24C02的I²C总线数据传输_第2张图片
起始信号产生后 ,总线处于占用状态
终止信号产生后,总线处于空闲状态

void start()//起始信号
{
     
	sda=1;
	delay();
	scl=1;
	delay();
	sda=0;
	delay();
}
void stop()//终止信号
{
     
	sda=0;
	delay();
	scl=1;
	delay();
	sda=0;
	delay();
}

数据传送格式

(1)字节传送与应答
一帧=一个字节+应答位=9位,一个字节八位,第九位是应答位
手把手教学51单片机第七课 | AT24C02的I²C总线数据传输_第3张图片
从机如果接收不了信号,就将SDA数据线置于高电平 ,中断通信;若主机要中断通信,就要发送一个终止信号,从机应答,就能终端通信。

void responds()//应答信号
{
     
	uchar i;
	scl=1;
	delay();
	while((sda==1)&&(i<250))i++;
	scl=0;
	delay();
}
(2)数据帧格式

灰色为主机 白色为从机

发送数据
在起始信号后必须传送一个从机地址(7位),第八位是数据的传送放方向位(R/T),0表示主机发送数据给从机T(transmit),1表示主机接受从机数据R(receive)
在这里插入图片描述
读数据
在这里插入图片描述
手把手教学51单片机第七课 | AT24C02的I²C总线数据传输_第4张图片

E²PROM

这里用的是AT24C02

  1. 芯片地址1010(固定的)
  2. 地址控制字格式1010 A2A1A0 R/W, A2 A1 A0接高低电平后得到三位确定的编码,和1010形成确定的7位编码,即地址码。R/W为芯片读写控制位,0表示写操作,1表示读操作。(为了便于观察最后一位0或1,我们这里的A2A1A0全都接地)
  3. 片内子地址寻址:有256个,地址码相当于大楼的地址,子地址相当于大楼内的每一个房间号,0-255,共256个
字节写入方式

手把手教学51单片机第七课 | AT24C02的I²C总线数据传输_第5张图片

void write_byte(uchar date)//写地址
{
     
	uchar i,temp;
	temp=date;
	scl=0;
	delay();
	for(i=0;i<8;i++)
	{
     
		temp=temp<<1;
		sda=CY;//最高位
		delay();
		scl=1;
		delay();
		scl=0;
		delay();
	}
	sda=1;
	delay();
}

接下来解释补充

  1. 左移:最高位向左移动,移入PSW的CY位,最低位补0;右移最低位移除,最高位保留。
temp=temp<<1;//左移一位
  1. 数据是一个一个送出来的,具体如下
    在这里插入图片描述
指定地址读操作

手把手教学51单片机第七课 | AT24C02的I²C总线数据传输_第6张图片

	start();//启动
	write_byte(0xa0);//器件地址+写
	responds();//应答
	write_byte(3);//子地址
	responds();//应答
	start();//这里要多一个应答
	write_byte(0xa1);//器件地址+读
	responds();//应答
	P1=read_byte();//赋值
	stop();//停止
	while(1);

其中read_byte 具体如下

uchar read_byte() 
{
     
	uchar i,j,k=0;
	scl=0;
	delay();
	sda=1; 
	delay();
	for(i=0;i<8;i++)
	{
     
		scl=1;
		delay();
		j=sda;
		k=(k<<1)|j;
		scl=0;
		delay(); 
	}
	return k;
}
  1. k的起始数值为0,相当于0000 0000B

  2. 或运算,有1为1,全0位0

  3. 对于 “ k=(k<<1) | j; ”解释如下 在这里插入图片描述

具体事例

#include
#define uchar unsigned char
#define uint unsigned int

sbit sda=P2^0;
sbit scl=P2^1;

void delay()
{
     
 ;;
}

void delay1(uchar z)
{
     
	uchar x,y;
	for(x=z;x>0;x--)
		for(y=100;y>0;y--);
}
void start()//ÆðʼÐźÅ
{
     
	sda=1;
	delay();
	scl=1;
	delay();
	sda=0;
	delay();
}

void stop()//ÖÕÖ¹ÐźÅ
{
     
	sda=0;
	delay();
	scl=1;
	delay();
	sda=1;
	delay();
}

void responds()//Ó¦´ðÐźÅ
{
     
	uchar i=0;
	scl=1;
	delay();
	while((sda==1)&&(i<255))
		i++;
	scl=0;
	delay();
}
void write_byte(uchar date)//дµØÖ·
{
     
	uchar i,temp;
	temp=date;
	scl=0;
	delay();
	
	for(i=0;i<8;i++)
	{
     
		temp=temp<<1;
		sda=CY;//×î¸ßλ  
		delay();
		scl=1;
		delay();
		scl=0;
		delay();
	}
	sda=1;
	delay();
}

uchar read_byte() //¶ÁÊý¾Ý
{
     
	uchar i,j,k=0;
	scl=0;
	delay();
	sda=1; 
	delay();
	for(i=0;i<8;i++)
	{
     
		scl=1;
		delay();
		j=sda;
		k=(k<<1)|j;
		scl=0;
		delay(); 
	}
	return k;
}

void init()
{
     
	scl=1;
	sda=1;
}

void write_add(uchar address, uchar date)
{
     
	start();//ÆðʼÐźÅ
	write_byte(0xa0);//Æ÷¼þµØÖ· ¸ßËÄλ¹Ì¶¨1010 0±íʾҪд device adress
	responds();
	write_byte(address);//д 0-256 word adress
	responds();
	write_byte(date);//data
	responds();
	stop();
}

uchar read_add(uchar address)
{
     
	uchar date;
	delay1(100);
	start();
	write_byte(0xa0);//µØÖ·
	responds();
	write_byte(address);
	responds();
	start();//»»·½Ïò
	write_byte(0xa1);//Æ÷¼þµØÖ· ºóÃæ±ä1 ÒòΪÊǶÁ
	responds();
	date=read_byte();
	stop();
	return date;
}

void main()
{
     
	init();//³õʼ»¯ 
	write_add(23,0xaa);
	delay1(100);
	P1=read_add(23);
	while(1);
}
	


	

你可能感兴趣的:(单片机,串口通信,单片机,嵌入式)