IIC通信过程详解以及底层代码实现

这篇具有很好参考价值的文章主要介绍了IIC通信过程详解以及底层代码实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、概述

I2C总线是PHLIPS公司推出的一种串行总线,是具备多主机系统所需的包括总线裁决和高低速器件同步功能的高性能串行总线。此通信方式为半双工。
I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。
I2C总线通过上拉电阻接正电源。当总线空闲时,两根线均为高电平。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。
IIC通信过程详解以及底层代码实现

2、IIC总线寻址方式

主机在发送起始信号后必须发送一个字节的数据,该数据的高7位为从机地址,最低位表示后续字节的传送方向,‘0’表示主机发送数据,‘1’表示主机接收数据;总线上所有的从机接收到该字节数据后都将这7位地址与自己的地址进行比较,如果相同,则认为自己被主机寻址,然后再根据第8位将自己定位发送器或接收器。

3、起始信号

当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
起始信号由主机发起,当主机发起起始信号后,总线就处于占领状态;当主机发出停止信号时,总线恢复空闲状态。
IIC通信过程详解以及底层代码实现

以下为起始信号的代码段:

void IIC_Start( void)
{
	IIC_SCL_H();         //拉高SCL
	BSP_IIC_Delay( );
	
	IIC_SDA_H( );    //SDA拉高
	BSP_IIC_Delay( );
	BSP_IIC_Delay( );
	
	IIC_SDA_L( );  //SDA拉低
	BSP_IIC_Delay( );	
	IIC_SCL_L( );    //SCL复位
}

4、停止信号

当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
IIC通信过程详解以及底层代码实现
以下为停止信号的代码段:

void IIC_Stop(void)
{
	IIC_SCL_H( );	
	BSP_IIC_Delay( );
	IIC_SDA_L( );
	
	BSP_IIC_Delay( );
	BSP_IIC_Delay( );
	IIC_SDA_H();
	
	BSP_IIC_Delay( );	
	IIC_SCL_L( );    //SCL复位
}

5、有效数据

当主机发起起始信号后,需要向从机进行寻址,发送相应的从机地址给从机进行响应。
SCL为时钟线,SDA为数据线。IIC总线进行数据传送时,SCL信号为高电平时,SDA电平必须保持稳定,即此时作为接收器接收数据。当SCL为低电平时,SDA的高低电平状态才允许变化,此时即为发送器发送数据。
SCL作为连接在收发双方上时钟线就解决了不同步的问题。

IIC总线通信时每个字节为8位长度,数据传送时,先传送最高位,后传送低位,当8位发送完后,从机将SDA拉低,表示应答。如还是高电平,表示非应答,即可能没有接收到。所以发送一个完整的字节,SCL会产生9个时钟信号。
下面为发送0xA0的时序图:
IIC通信过程详解以及底层代码实现

以下为发送字节的代码段:

uint8_t IIC_Send(  uint8_t uSendByte ) 
{ 
	uint8_t uIndex = 0;
	uint8_t uAskState = BSP_OK;
	uint16_t count = 0;

	for( uIndex = 0; uIndex < 8; uIndex ++ )
	{
		if( uSendByte & 0x80 )   
        {
            IIC_SDA_H();     
        }
        else
        {
            IIC_SDA_L();
        }
		BSP_IIC_Delay( );	//延时
		IIC_SCL_H( );	    //  SCL高电平 SDA要求稳定 接收器接收数据	  先将SDA的电平拉高,再拉高SCL的                         
		
		BSP_IIC_Delay(  );	//延时
		BSP_IIC_Delay( );	//延时
		IIC_SCL_L( );	    //  SCL低电平 SDA允许变化 发送器发送数据
		uSendByte <<= 1;
	}
	IIC_SDA_H( );					//拉高SDA和SCL 释放总线 等待从机将SDA拉低进行应答
    IIC_SCL_H(  );					
	BSP_IIC_Delay(  );
    if( 0 == IIC_SDA_READ( ) )                                                   
    { 
        uAskState = BSP_OK; 
    }
    else
    {
        uAskState = BSP_ERR;
    }
	BSP_IIC_Delay( );
	IIC_SCL_L();
	BSP_IIC_Delay( );
    return uAskState;
} 

6、应答信号和非应答信号

当主机作为接收器接收从机返回的数据时,接收完一个字节主机需要发起一个应答信号告诉从机,该字节接收完成。当主机接收完所有的数据后需要发起一个非应答信号给从机,方便从机准备接收停止信号,停止此次的通信。
以下为应答信号和非应答信号的时序图,SCL信号一致,都是维持在高电平,应答信号SDA为低电平,非应答信号SDA为高电平。
IIC通信过程详解以及底层代码实现
以下为相关的代码段

E_Bool IIC_AskOrNo( uint8_t ask_or_no )
{
	/* 每发送完一个数据字节后,发送器释放SDA,接收器拉高SDA(接收时BMS为接收器),
	在SCL处于高电平期间保持稳定的高电平接收器产生一个有效的否应答信号 */ 	
	//应答和非应答的时候SCL时序一样,只是SDA维持的电平不一样,低电平是应答信号,高电平是非应答信号
	
	IIC_SCL_L( );
	BSP_IIC_Delay( );
	//if( ask_or_no)   //应答
	( ask_or_no==1) ?(IIC_SDA_L( )):(IIC_SDA_H( ));
	BSP_IIC_Delay();
	
	IIC_SCL_H( );
	BSP_IIC_Delay( );
	
	IIC_SCL_L();
	BSP_IIC_Delay();
	return True; 
}

7、接收数据

当主机向从机发送读地址后,从机开始向主机回复相关数据 。相关代码段如下:

uint8_t IIC_Recv_Byte( )  
{ 
    /* 接收数据,高位在前 */
	uint16_t count = 0;
    uint8_t uBitIndex    = 0; 
    uint8_t uReceiveByte = 0; 
	
	IIC_SDA_H(  );
	IIC_SCL_L();
	BSP_IIC_Delay();
	for( uBitIndex = 0; uBitIndex < 8; uBitIndex ++)
	{ 
		uReceiveByte <<= 1; 
		IIC_SCL_H();
		/*count = 0;    等待SCL电平变化  可以屏蔽
		do{
			__nop();
			if( count ++ > WAIT_CLK_TIMES )
			{
				IIC_Stop( uIIC_ID );
				break;
			}
		}while( 0 == IIC_SCL_READ( uIIC_ID ) );*/
		BSP_IIC_Delay();
		if( IIC_SDA_READ() ) 
		{ 
			uReceiveByte |= 0X01; 
		} 
		BSP_IIC_Delay( );
		IIC_SCL_L();
		BSP_IIC_Delay();				
	}
    return uReceiveByte;		
}

8、IIC通信流程

8.1读数据

1、主机发送一个起始信号
2、主机发送从机写地址
3、主机发送要写寄存器的地址
4、主机发送从机读地址
5、主机开始收取数据,每收取完一个字节,主机发送一个应答信号给从机。当全部的字节都收取完了以后,主机发送一个非应答信号给从机。
6、主机发送一个停止信号给从机
相关代码段如下:
从机写地址为:0xA0 读地址为:0xA1

uint8_t ReadReg( uint8_t uRegAdr, uint8_t uRegNum, uint8_t *pData )
{
	uint8_t  uIndex  = 0;
	uint8_t uState  = BSP_ERR;
	E_Bool eAsk = False;
	IIC_Start();
	uState = IIC_Send( 0xA0 );
	if(BSP_OK==uState)
	{
	  ///写寄存器地址
		uState = IIC_Send( uRegAdr );
	    if(BSP_OK==uState)
		{
			uState = IIC_Send( 0xA1 );
			if(BSP_OK==uState)
			{
				for( uIndex = 0 ; uIndex < uRegNum; uIndex ++ )
				{
					pData[uIndex] = Recv_Byte(); //读寄存器数据
					if(uIndex < (uRegNum - 1) )
					{
						eAsk =IIC_AskOrNo(1); 
						if(False==eAsk)
						{
							uState = BSP_ERR;
							break;
						}
					}
				}
				if(uIndex==uRegNum)
				{
					IIC_AskOrNo(0);    //收完最后一个字节发送一个非应答位
				}
			}
		}
	}	
	IIC_Stop();
	return uState;	 
}

8.2写数据

写数据相对于读数据来说较为简单。前三个步骤和读数据一样。
1、主机发送一个起始信号
2、主机发送从机写地址
3、主机发送要写寄存器的地址
4、主机发送需要写的数据,发送完毕后主机发送一个停止信号给从机。
相关代码段如下:文章来源地址https://www.toymoban.com/news/detail-429714.html

uint8_t WriteReg( uint8_t uRegAdr, uint8_t uRegNum, uint8_t* pData )
{
	uint8_t uIndex  = 0;
	uint8_t uState  = BSP_ERR;

	IIC_Start();
	uState = IIC_Send( 0xA0  );
	if(BSP_OK==uState)
	{
		uState = IIC_Send( uRegAdr );
		if(BSP_OK==uState)
		{
			for(uIndex=0; uIndex<uRegNum; uIndex++)
			{
				uState = IIC_Send( pData[uIndex] );
				if(uState != BSP_OK)
				{
					break;
				}
			}
		}
	}
	IIC_Stop();
	return uState;	  
}

到了这里,关于IIC通信过程详解以及底层代码实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 标定系列二、9点标定以及5点圆心标定过程(代码详解)

            9点标定就是通过9个点计算出相机坐标系到机械手坐标系下的一个仿射变换,(实际上空间中的二维平面的仿射变换只需要3个点就足够了)。在实际应用过程中,需要获取像素下特征点的坐标和对应机械手的坐标。联立方程组求解即可得到对应仿射变换的矩阵,实际

    2024年02月04日
    浏览(33)
  • 【物联网】I2C(IIC)通信协议详解与应用

    目录 第一部分:I2C的工作原理 第二部分:I2C的特性 第三部分:I2C的应用场景 第四部分:I2C的注意事项 第五部分:I2C的通信过程 第六部分:单片机实现I2C 1. 51单片机实现I2C 2. STM32使用标准库实现I2C 3. STM32使用HAL库实现I2C 第七部分:总结 I2C是一种双线制串行通信协议,由两

    2024年02月10日
    浏览(52)
  • 基于IIC通信的显示器OLED编程详解(一篇搞懂)

    上一篇博客介绍了IIC通信,这篇我们就来玩玩oled模块。当然选用的是IIC接口,因为市面上还有一种是SPI接口的。对于oled长啥样,采用了什么材料,工艺怎么怎么样等等这里就不作任何介绍,搞得眼花缭乱的,对我们用它做开发也没任何帮助,同时节省读者阅读时间。为什么

    2024年02月09日
    浏览(53)
  • 详解UART通信协议以及FPGA实现

      从《浅谈UART,TTL,RS-232,RS-485的区别》这篇文章,我们知道了UART是一种串行、异步、全双工的通信协议,属于协议层;传输过程一般采用RS-232,RS-485电平标准,将所需传输的数据一位接一位地传输;整体传输框架如下:   串口通信由发送端和接收端构成,两根信号线

    2024年04月28日
    浏览(39)
  • IIC代码波形对照详解

    IIC(Inter-Integrated Circuit)是一个多主从的串行总线,又叫I2C,是由飞利浦公司发明的通讯总线,属于半双工同步传输类型总线。IIC总线是非常常见的数据总线,仅仅使用两条线就能完成多机通讯,一条SCL时钟线,另外一条双向数据线SDA。 (随便百度了一下,相关介绍资料较多

    2024年02月09日
    浏览(45)
  • STM32软件模拟IIC时序实现与EEPROM的通信

                       IIC简介  IIC物理层 用软件模拟IIC时序         一、空闲状态(初始化):SCL 和SDA都保持高电平         二、开始信号 :SCL为高电平期间,SDA由高电平变为低电平。         三、停止信号:SCL为高电平期间,SDA由低电平变为高电平   

    2024年02月09日
    浏览(80)
  • Benewake(北醒) 快速实现TFLuna-IIC与电脑通信的操作说明

    通过本文档的概述,能够让初次使用测试者快速了解测试 IIC 通信协议需要的工具以及查看哪些对应的 IIC 协议说明书,通过 PC 连接完成 IIC 通信协议的产品测试。 本文档适用的产品型号: TFLuna-IIC(测试前确认产品硬件版本以及固件版本) 工具 数量 PC 上位机 windows 系统 1台

    2024年02月11日
    浏览(42)
  • Spring IOC底层原理实现过程

    Spring IOC(Inversion of Control,控制反转)是 Spring 框架的核心,它的实现原理是基于反射和配置文件实现的。 在 Spring IOC 中,控制权被反转了。传统的应用程序开发中,对象的创建、管理、销毁等全部由应用程序自己来控制,这个过程称为主动管理(Active Management)。而在 Spr

    2024年02月03日
    浏览(43)
  • Benewake(北醒) 快速实现TFmini-Plus-IIC与电脑通信的操作说明

    通过本文档的概述,能够让初次使用测试者快速了解测试 IIC 通信协议需要的工具以及查看哪些对应的 IIC 协议说明书,通过 PC 连接完成 IIC 通信协议的产品测试。 本文档适用的产品型号: TFmini-Plus-IIC(测试前确认产品硬件版本以及固件版本) 工具 数量 PC 上位机 windows 系统

    2024年02月12日
    浏览(35)
  • 【运维知识进阶篇】iptables防火墙详解(iptables执行过程+表与链概述+iptables命令参数+配置filter表规则+NAT表实现共享上网、端口转发、IP映射)

    这篇文章给大家介绍下iptables防火墙,防火墙大致分三种,分别是硬件、软件和云防火墙。硬件的话部署在企业网络的入口,有三层路由的H3C、华为、Cisco(思科),还有深信服等等;软件的话一般是开源软件,写在网站内部,最常见的有iptables(写入Linux内核)和firewalld(C

    2024年02月09日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包