IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> IIC通信过程详解以及底层代码实现 -> 正文阅读

[嵌入式]IIC通信过程详解以及底层代码实现

1、概述

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

2、IIC总线寻址方式

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

3、起始信号

当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
起始信号由主机发起,当主机发起起始信号后,总线就处于占领状态;当主机发出停止信号时,总线恢复空闲状态。
起始信号时序图

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

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由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。
停止信号时序图
以下为停止信号的代码段:

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的时序图:
发送数据时序图

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

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为高电平。
时序图
以下为相关的代码段

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;
	uState = IIC_Start();
	if( BSP_OK==uState )
	{
		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、主机发送需要写的数据,发送完毕后主机发送一个停止信号给从机。
相关代码段如下:

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

	uState=IIC_Start();
	if(BSP_OK==uState)
	{
		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;	  
}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:27:28  更:2022-04-04 12:30:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:42:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码