7 I2C总线

存储器

  • RAM:掉电丢失数据,但高速
  • ROM:掉电可保存数据,但速度没有RAM快
    ![[Pasted image 20250124140036.png]]
  • SRAM:本质上是一个D触发器,速度最快
  • DRAM:类似于电容

AT24C02

掉电不丢失
存储介质是E2PROM, 使用I2C总线为通讯接口,256字节容
![[Pasted image 20250124141714.png]]
![[Pasted image 20250124141846.png]]

I2C总线

I2C有两根通信线:SCL(Serial Clock), SDA(Serial Data)
同步,半双工,带数据应答
![[Pasted image 20250125103111.png]]
开漏输出:解决多机通信干扰问题,在对一个设备通信时,对于其他设备全输出1,没有驱动能力,相当于其他设备全断开
主机通过规定每个设备地址,通信时发送设备地址进行匹配,匹配上的设备进行通信

1. 时序结构

起始条件:SCL高电平期间,SDA从高电平切换到低电平
终止条件:SCL高电平期间,SDA从低电平切换到高电平
![[Pasted image 20250125104226.png]]
![[Pasted image 20250125104348.png]]
在SCL高电平时读取SDA电平
![[Pasted image 20250125104703.png]]
![[Pasted image 20250125105040.png]]

2. 数据帧

![[Pasted image 20250125105207.png]]
发送的数据前七位为I2C地址,最后一位为读写标志位,1是读取0是写入
且地址前四位为固定值(出厂设置)
![[Pasted image 20250125105551.png]]
![[Pasted image 20250125105735.png]]
其实就是发送之后不暂停,继续接收数据
![[Pasted image 20250125110237.png]]

读写数据

I2C代码

#include <REGX52.H>

sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;

/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void I2C_Start(void)
{
	I2C_SDA=1;
	I2C_SCL=1;
	I2C_SDA=0;
	I2C_SCL=0;
}

/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void I2C_Stop(void)
{
	I2C_SDA=0;
	I2C_SCL=1;
	I2C_SDA=1;
}

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的字节
  * @retval 无
  */
void I2C_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		I2C_SDA=Byte&(0x80>>i);
		I2C_SCL=1;
		I2C_SCL=0;
	}
}

/**
  * @brief  I2C接收一个字节
  * @param  无
  * @retval 接收到的一个字节数据
  */
unsigned char I2C_ReceiveByte(void)
{
	unsigned char i,Byte=0x00;
	I2C_SDA=1;
	for(i=0;i<8;i++)
	{
		I2C_SCL=1;
		if(I2C_SDA){Byte|=(0x80>>i);}
		I2C_SCL=0;
	}
	return Byte;
}

/**
  * @brief  I2C发送应答
  * @param  AckBit 应答位,0为应答,1为非应答
  * @retval 无
  */
void I2C_SendAck(unsigned char AckBit)
{
	I2C_SDA=AckBit;
	I2C_SCL=1;
	I2C_SCL=0;
}

/**
  * @brief  I2C接收应答位
  * @param  无
  * @retval 接收到的应答位,0为应答,1为非应答
  */
unsigned char I2C_ReceiveAck(void)
{
	unsigned char AckBit;
	I2C_SDA=1;
	I2C_SCL=1;
	AckBit=I2C_SDA;
	I2C_SCL=0;
	return AckBit;
}

AT24C02控制代码

#include <REGX52.H>
#include "I2C.h"

#define AT24C02_ADDRESS		0xA0

/**
  * @brief  AT24C02写入一个字节
  * @param  WordAddress 要写入字节的地址
  * @param  Data 要写入的数据
  * @retval 无
  */
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_SendByte(Data);
	I2C_ReceiveAck();
	I2C_Stop();
}

/**
  * @brief  AT24C02读取一个字节
  * @param  WordAddress 要读出字节的地址
  * @retval 读出的数据
  */
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
	unsigned char Data;
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS|0x01);
	I2C_ReceiveAck();
	Data=I2C_ReceiveByte();
	I2C_SendAck(1);
	I2C_Stop();
	return Data;
}

#include <REGX52.H>
#include "LCD1602.h"
#include "Key.h"
#include "AT24C02.h"
#include "Delay.h"

unsigned char reData;

void main()
{
	LCD_Init();
	AT24C02_WriteByte(1,78);
	// 存在5ms的写周期
	Delay(5);
	reData = AT24C02_ReadByte(1);
	LCD_ShowNum(1,1,reData,3);
	while(1)
	{
		
	}
}
posted @ 2025-01-25 14:35  Lain_surime  阅读(11)  评论(0)    收藏  举报