I2C 协议 代码详解

Posted 丿轩雪灬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了I2C 协议 代码详解相关的知识,希望对你有一定的参考价值。

I2C 协议

  最后代码已上传!!!!
  一文带你了解 MQTT 协议 github 代码链接在该文章最后

I2C 简要介绍

I2C 总线(I2C bus,Inter-IC bus)是一个双向的两线连续总线,提供集成电路(ICs)之间的通信线路。I2C总线是一种串行扩展技 术,最早由 Philips 公司推出,广泛应用于电视,录像机和音频等设备。I2C总线的意思:“完成集成电路或功能单元之间信息交换的规范或协议”。Philips公司推出的 I2C 总线采用一条数据线(SDA),加一条时钟线(SCL)来完成数据的传输及外围器件的扩展;对各个节点的寻址是软寻址方式,节省了片选线,标准的寻址字节 SLAM 为7位,可以寻址127个单元。

1. 延时信号

static void i2c_Delay(void)
{
	uint8_t i;
	for (i = 0; i < 10; i++);
}

逻辑分析测试得出

​ 条件: CPU 主频 72MHZ ,MDK 编译, 1级优化

​ 循环次数 10 ,SCL 频率 = 205 KHZ

​ 循环次数 7 ,SCL 频率 = 347 KHZ, SCL 高电平时间 1.5us, SCL 低电平时间 2.87us

​ 循环次数 5 ,SCL 频率 = 421 KHZ ,SCL 高电平时间 1.25us, SCL 低电平时间 2.37us

2.起始信号

根据上方时序图可以知道

​ I2C 起始信号:当 SCL 高电平时,SDA 出现一个下跳沿表示 I2C 总线启动信号

​ 对应代码为:

void i2c_Start(void)
{
	OLED_I2C_SDA_1();			//SDA 总线置1
	OLED_I2C_SCL_1();			//SCL 总线置1
	i2c_Delay();				//延时信号
	OLED_I2C_SDA_0();			//置 0 
	i2c_Delay();
	OLED_I2C_SCL_0();			//SCL 置0
	i2c_Delay();
}

3. 停止信号

根据上方时序图可以知道

​ I2C 结束信号:当 SCL 高电平时,SDA 出现一个上跳沿表示 I2C 总线停止信号

​ 对应代码为:

void i2c_Stop(void)
{
	OLED_I2C_SDA_0();
	OLED_I2C_SCL_1();
	i2c_Delay();
	OLED_I2C_SDA_1();
}

4. 等待应答信号

根据上方时序图可以知道

​ I2C等待应答信号:当 SDA 高电平,SCL 也处在高电平,这时候 SDA 返回的数据, 1 代表无器件应答,0 代表正确应答。

​ 对应代码为:

uint8_t i2c_WaitAck(void)
{
	uint8_t re;

	OLED_I2C_SDA_1();	
	i2c_Delay();
	OLED_I2C_SCL_1();	
	i2c_Delay();
	if (OLED_I2C_SDA_READ())	//读取 SDA 口线状态
	{
		re = 1;					
	}
	else
	{
		re = 0;
	}
	OLED_I2C_SCL_0();			//拉低 SCL 总线
	i2c_Delay();
	return re;
}

5. 发送信号

根据上方时序图可以知道

​ 在SCL为高电平期间,发送数据,发送8次数据,数据为1,SDA被拉高,SDA被拉低,数据为0,SDA被拉低。

void i2c_SendByte(uint8_t _ucByte)
{
	uint8_t i; 							//先传输高位 bit7
	for (i = 0; i < 8; i++)
	{		
		if (_ucByte & 0x80)   			//判断 高位
		{
			OLED_I2C_SDA_1();			//设置 SDA 传输数据 
		}
		else
		{
			OLED_I2C_SDA_0();			
		}
		i2c_Delay();
		OLED_I2C_SCL_1();				//拉高 SCL ,发送数据
		i2c_Delay();	
		OLED_I2C_SCL_0();				//拉低 SCL ,改变 SDA 数据,左移 _ucByte ,再次判断 高位 bit6 等等
		if (i == 7)
		{
			 OLED_I2C_SDA_1(); 			//退出传输, SDA 置 1
		}
		_ucByte <<= 1;	
		i2c_Delay();
	}
}

6. 读取信号

uint8_t i2c_ReadByte(void)
{
	uint8_t i;
	uint8_t value;
	value = 0;          
	for (i = 0; i < 8; i++)
	{
		value <<= 1;					//左移 1 位
		OLED_I2C_SCL_1();				// SCL 置 1 
		i2c_Delay();
		if (OLED_I2C_SDA_READ())		//读取 SDA 口数据
		{
			value++;                    //每次都左移一位,value++,就等于 |          
		}
		OLED_I2C_SCL_0();				//SCL 置 0 ,改变 SDA 数据
		i2c_Delay();
	}
	return value;						//返回读取到的数据
}

SCL 置 1,SDA数据稳定,SCL 置 0,可以改变 SDA数据

最后

 第一次尝试编写博客,若是有什么建议,欢迎批评指出。

后续会逐步分块更新,并会在最后一篇文章上传源代码。

  最后一篇文章已更新,代码在该篇文章最后

  一文带你了解 MQTT 协议 代码在该文章最后

 若是该文章对你有作用或是觉得文章写得还行,帮忙点点赞,三连!

以上是关于I2C 协议 代码详解的主要内容,如果未能解决你的问题,请参考以下文章

I2C 总线协议详解

I2C总线协议详解

I2C协议详解

I2C总线协议详解

RK3399平台开发系列讲解(I2C子系统)4.40I2C协议详解

linux内核I2C子系统详解——看这一篇就够了