IIC通信---EEPROM24C02---STMF4

IIC通信协议

IIC是同步半双工通信,一个数据线SDA和一个时钟SCL线,可以接受和发送数据。在CPU与被控IC之间、IC与IC之间进行双向传送。

空闲状态

IIC总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。

起始信号

当SCL为高期间,SDA由高到低的跳转

在这里插入图片描述
代码实现为:

//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出模式
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}	  
停止信号

当SCL为高期间,SDA由低到高的跳转
在这里插入图片描述
代码实现:

//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1; 
	delay_us(4);			
	IIC_SDA=1;//发送I2C总线结束信号				   	
}
应答信号

发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位,表示接收器已经成功接收到了该字节。应答信号为高电平时,规定为非应答位,一般表示接收器接收该字节没有成功。
对于反馈有效应答位ACK的要求是,接收器第9个时钟脉冲之前的低电平将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电压。
在这里插入图片描述
代码实现为:

//产生ACK应答
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}

//不产生ACK应答		    
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}	
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;//时钟输出0 	   
	return 0;  
} 
数据的有效性

IIC总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平才允许变化。即数据在SCL的上升沿到来之前就需要准备好,并且在下降沿到来之前必须保持稳定。
在这里插入图片描述

数据的传送

在IIC总线上传送的每一位数据都有一个时钟脉冲相对应(同步控制),即在SCL串行时钟的配合下,在SDA上逐位串行传送每一位数据,数据位的传输是边沿触发。

发送一字节代码实现为:

//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
} 

数据传输之前IIC_SCL必须等于0,即时信号为低电平,然后准备一位数据,准备好之后,IIC_SCL=1,即时钟信号为高电平,数据就传输过去了
对于下面的代码:

IIC_SDA=(txd&0x80)>>7;
txd<<=1;

无符号类型左移丢弃最高位,低位补0,无符号类型右移丢弃最低位,低位补0,txd&0x80让txd第8位数据不变,其他为变成0(txd的值不受影响),左移7位,将最高位的数据赋值给IIC_SDA,当IIC_SCL=1时,第八位数据就传输过去了,txd<<=1让第7位数据变成第8位数据,下次循环就传输原来第7位数据了。循环8次将一字节数据传输完毕。

读取数据代码实现:

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0; 
        delay_us(2);
		IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

对于下面的代码:

 receive<<=1;
 if(READ_SDA)receive++;   

READ_SDA是获取SDA线上的电压,高电压说明说明传送过来的数据是1,receive++,下一次的时候, receive<<=1,receive先右移一位,然后接受数据,这样循环8次,就能保证接受的数据在原来的位置上了。

与EEPROM通信
硬件连接

在这里插入图片描述
EEPROM是一种掉电后数据不丢失的存储芯片,可以在电脑上或专用设备上擦除已有信息,重新编程。
24C02的总容量是256个字节,接口是IIC
在这里插入图片描述

模式选择

硬件连接中,A2=A1=A0=0(接地),所以,我们读数据时,只需写入0xA1,表示读模式,写数据时,只需写入0xA0,表示写模式
在这里插入图片描述

写时序

下面是写入一个字节数据的过程
在这里插入图片描述

  1. 一个IIC_START信号
  2. 写入模式,写入0xA0
  3. 等待一个ACK
  4. 发送写入数据的地址(0~255)
  5. 等待一个ACK
  6. 发送一个字节
  7. 等待一个ACK
  8. 一个STOP信号
    具体代码如下
//在AT24CXX指定地址写入一个数据
//WriteAddr  :写入数据的目的地址    
//DataToWrite:要写入的数据
void AT24CXX_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{				   	  	    																 
    IIC_Start();  
	if(EE_TYPE>AT24C16)
	{
		IIC_Send_Byte(0XA0);	    //发送写命令
		IIC_Wait_Ack();
		IIC_Send_Byte(WriteAddr>>8);//发送高地址	  
	}else IIC_Send_Byte(0XA0+((WriteAddr/256)<<1));   //发送器件地址0XA0,写数据 	 
	IIC_Wait_Ack();	   
    IIC_Send_Byte(WriteAddr%256);   //发送低地址
	IIC_Wait_Ack(); 	 										  		   
	IIC_Send_Byte(DataToWrite);     //发送字节							   
	IIC_Wait_Ack();  		    	   
    IIC_Stop();//产生一个停止条件 
	delay_ms(10);	 
}
读数据

下面是读一个字节数据的过程
在这里插入图片描述

  1. 产生一个START信号
  2. 写入0xA0,表示是写模式
  3. 等待一个ACK
  4. 写入读数据的地址
  5. 等待一个ACK
  6. 产生一个START信号
  7. 写入0xA1,表示是读模式
  8. 等待一个ACK
  9. 读取数据
    实现代码如下:
//在AT24CXX指定地址读出一个数据
//ReadAddr:开始读数的地址  
//返回值  :读到的数据
u8 AT24CXX_ReadOneByte(u16 ReadAddr)
{				  
	u8 temp=0;		  	    																 
    IIC_Start();  
	if(EE_TYPE>AT24C16)
	{
		IIC_Send_Byte(0XA0);	   //发送写命令
		IIC_Wait_Ack();
		IIC_Send_Byte(ReadAddr>>8);//发送高地址	    
	}else IIC_Send_Byte(0XA0+((ReadAddr/256)<<1));   //发送器件地址0XA0,写数据 	   
	IIC_Wait_Ack(); 
    IIC_Send_Byte(ReadAddr%256);   //发送低地址
	IIC_Wait_Ack();	    
	IIC_Start();  	 	   
	IIC_Send_Byte(0XA1);           //进入接收模式			   
	IIC_Wait_Ack();	 
    temp=IIC_Read_Byte(0);		   
    IIC_Stop();//产生一个停止条件	    
	return temp;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值