C51(I2C)

该博客详细介绍了如何使用I2C通信协议与AT24C02进行数据交互。通过I2C的开始和停止时序、发送和接收字节、应答机制,实现了向AT24C02写入和读取数据的功能。同时,展示了如何在实际应用中结合独立按键和LCD1602显示模块,实现数值的存储与读取操作。
摘要由CSDN通过智能技术生成

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

请添加图片描述
请添加图片描述

在这里插入图片描述
请添加图片描述
下面是I2C的六组时序图:
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

请添加图片描述

所以我们主要实现的I2C功能:
请添加图片描述
请添加图片描述
I2C: 带数据应答

SCL:同步时钟线
SDA: 只有一根线,负责来回,发送和接受信息 ,所以是半双工
SDA的变化:是根据数据输入的信号来决定的
(图上的两根线)在读取数据的时候,前面的数据变化,可能是高电平
也可能是低电平;,所以变化可能会从低->高,也可能 高->低;
也可能高不变,低不变,一共四种状态;

初始化的时候 A6-A3固定标志位AT24c02的标志,先发送7位地址位+读写标志位,一共八位
RA : 0 ;收一个字节 ,接收应答;
SA :0 ; 收一个字节,发出一个应答;
0是应答标志,1是非应答;
接收应答的时候,先初始化,让从机接收应答 RA: 0 ,把话语权交给从机

在这里插入代码片:
#include <REGX52.H>
#include "Delay.h"

/**
  * @brief  获取独立按键键码
  * @param  无
  * @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
  */
unsigned char Key()
{
	unsigned char KeyNumber=0;
	
	if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
	if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
	if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
	if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
	
	return KeyNumber;
}

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调用I2C模块:

在这里插入代码片:
#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 KeyNum;
unsigned int Num;

void main()
{
	LCD_Init();
	LCD_ShowNum(1,1,Num,5);
	while(1)
	{
		KeyNum=Key();
		if(KeyNum==1)	//K1按键,Num自增
		{
			Num++;
			LCD_ShowNum(1,1,Num,5);
		}
		if(KeyNum==2)	//K2按键,Num自减
		{
			Num--;
			LCD_ShowNum(1,1,Num,5);
		}
		if(KeyNum==3)	//K3按键,向AT24C02写入数据
		{
			AT24C02_WriteByte(0,Num%256);
			Delay(5);  //使周期结束
			AT24C02_WriteByte(1,Num/256);//写入多少个数据,这个数据的值
			Delay(5);
			LCD_ShowString(2,1,"Write OK");
			Delay(1000);
			LCD_ShowString(2,1,"        ");
		}
		if(KeyNum==4)	//K4按键,从AT24C02读取数据
		{
			Num=AT24C02_ReadByte(0);
			Num|=AT24C02_ReadByte(1)<<8;
			LCD_ShowNum(1,1,Num,5);
			LCD_ShowString(2,1,"Read OK ");
			Delay(1000);
			LCD_ShowString(2,1,"        ");
		}
	}
}

### C51单片机与I2C通讯协议 #### 使用C51单片机实现I2C通信的关键概念 通过学习可以掌握使用C51编译器开发微控制器项目的必要技能,并为后续章节中更复杂的应用和协议的深入研究打下坚实的基础[^1]。对于I2C通信协议的理解有助于进一步提升这些能力。 IIC(也称为I&sup2;C),全称Inter-Integrated Circuit,是一种由PHILIPS公司于80年代开发的两线式串行总线,主要用于连接微控制器及其外围设备。这种总线的特点在于其简单性和有效性,采用半双工同步通信方式[^4]。 为了减轻单片机的工作负担,在实际应用中通常会利用中断机制来处理数据接收过程中的事件响应,而不是持续不断地查询是否有新消息到来[^3]。 以下是基于C51单片机的一个简单的I2C读写操作示例: ```c #include <reg52.h> sbit SDA = P1^7; // 定义SDA引脚 sbit SCL = P1^6; // 定义SCL引脚 void I2C_Start(void); void I2C_Stop(void); void I2C_Write_Byte(unsigned char dat); unsigned char I2C_Read_Byte(void); // 初始化函数 void Init_I2C() { SDA = 1; SCL = 1; } // 开始条件 void I2C_Start() { SDA = 1; SCL = 1; _nop_(); SDA = 0; SCL = 0; } // 停止条件 void I2C_Stop() { SDA = 0; SCL = 1; _nop_(); SDA = 1; } // 发送一字节数据 void I2C_Write_Byte(unsigned char dat) { unsigned char i; for (i=0;i<8;i++) { SCL = 0; if(dat & 0x80){ SDA = 1; }else{ SDA = 0; } dat <<= 1; SCL = 1; } SCL = 0; SDA = 1; SCL = 1; while(SDA==0); } // 接收一字节数据 unsigned char I2C_Read_Byte() { unsigned char i,dat=0; SDA = 1; for(i=0;i<8;i++){ SCL = 0; _nop_(); SCL = 1; dat<<=1; if(SDA) dat++; } SCL = 0; return dat; } ``` 此代码片段展示了如何初始化I2C接口并执行基本的数据传输功能。需要注意的是,这只是一个基础框架;针对特定硬件平台可能还需要调整配置参数或增加额外的功能支持。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

The endeavor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值