精华内容
下载资源
问答
  • IIC协议总结

    万次阅读 多人点赞 2018-12-17 16:56:02
    这篇总结IIC协议 简介 IIC,Inter-Integrated Circuit,集成电路总线,需要2根线连接拓扑,是半双工,适用于"字节型"设备。 特点 拓扑如下: SDA — 串行数据线 SCL — 串行时钟线 通讯速率标准模式...
    这篇总结下IIC协议
    简介
    • IIC,Inter-Integrated Circuit,集成电路总线,需要2根线连接拓扑,是半双工,适用于"字节型"设备。
    特点
    • 拓扑如下:
      在这里插入图片描述
      SDA — 串行数据线
      SCL — 串行时钟线
    • 通讯速率标准模式下100kb/s,快速模式下400kb/s
    • 连接到总线的IC最大负载电容400pf
    • 需要上拉电阻
      原因:
      - 总线空闲时要求是高电平
      • IIC的数据线SDA是开漏的,无法输出高电平,只能输出低电平
      • 起到保护作用,如果某个器件拉低,并且不接上拉电阻就电源-地短路了
      • 对于不明确负载,IC不能很大的保证输出功率,接上拉电阻则负载所需功率由电源提供,保护IC
    • 上拉电阻选取见下面这篇文章关于IIC的上拉电阻
    时序
    • 开始信号、结束信号
      在SCL为高电平时,SDA由高跳变到低时开始信号
      在SCL为高电平时,SDA由低跳变到高时开始信号
    • 有效数据
      传输有效数据时SDA只能在SCL为低时发生变化,SCL为高时要保持不变,否则就成的开始结束信号
    • 应答、非应答
      主机每发生一个字节数据,主机总是需要等待从机给主机反馈一个应答或者非应答信号,确保数据是否接收。在SCL第9个脉冲时之前把SDA设置为输入,检测SDA,为低是应答信号,为高则是非应答信号。
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      下面是用IO模拟的iic
    #include "myiic.h"
    
    uint16_t SlaveAddr;   //设备地址
    uint8_t  SlaveAddrLen=1;//设备地址字节数
    uint16_t SubAddr;     //片内地址
    uint8_t  SubAddrLen=2;  //片内地址字节数
    uint8_t IICReadBuf[IIC_SIZE]={0}; //从IIC读到IICLen个数据缓存
    uint8_t IICWriteBuf[IIC_SIZE]={0};//待写入IICLen个数据缓存
    uint16_t IICLen; //IIC操作长度
    
    //IO方向设置  
    void SDA_IN(void) 
    {	
    	GPIO_InitTypeDef        GPIO_InitStructure;
    	GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    	GPIO_Init(IIC_GPIO, &GPIO_InitStructure);
    }
    
    void SDA_OUT(void)
    {	
    	GPIO_InitTypeDef        GPIO_InitStructure;
    	GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    	GPIO_Init(IIC_GPIO, &GPIO_InitStructure);
    }
    
    //初始化IIC 
    //PA9-->IIC_SCL PA10-->IIC_SDA  
    void IIC_Init(void)
    {				     
    	GPIO_InitTypeDef        GPIO_InitStructure;
    	
      RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
    	
      /* Configure PA9 and PA10 in output pushpull mode */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
      GPIO_Init(IIC_GPIO, &GPIO_InitStructure);	
    	
    	IIC_SCL_H;
    	IIC_SDA_H;
    }
    
    void IIC_close(void)
    {				     
    	GPIO_InitTypeDef        GPIO_InitStructure;
    	
      RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
    	
      /* Configure PA9 and PA10 in output pushpull mode */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
      GPIO_Init(IIC_GPIO, &GPIO_InitStructure);	
    	
    	IIC_SCL_H;
    	IIC_SDA_H;
    }
    
    //产生IIC起始信号
    uint8_t IIC_Start(void)
    {
    	SDA_OUT();     //sda线输出
    	IIC_SDA_H;	  	  
    	IIC_SCL_H;
    	delay_us(5);
    	if(!READ_SDA) return 1; //SDA线为低电平则总线忙,退出
     	IIC_SDA_L;//START:when CLK is high,DATA change form high to low 
    	delay_us(5);
    	if(READ_SDA) return 1; //SDA线为高电平则总线出错,退出
    	IIC_SCL_L;//钳住I2C总线,准备发送或接收数据 
    	return 0;
    }	  
    //产生IIC停止信号
    void IIC_Stop(void)
    {
    	SDA_OUT();//sda线输出
    	IIC_SCL_L;
    	IIC_SDA_L;//STOP:when CLK is high DATA change form low to high
     	delay_us(5);
    	IIC_SCL_H; 
    	delay_us(5);			
    	IIC_SDA_H;//发送I2C总线结束信号
    	delay_us(5);							   	
    }
    //等待应答信号到来
    //返回值:1,接收应答失败
    //        0,接收应答成功
    uint8_t IIC_Wait_Ack(void)
    {
    	uint8_t ucErrTime=0;
    	SDA_IN();      //SDA设置为输入  
    	IIC_SDA_H;delay_us(1);	   
    	IIC_SCL_H;delay_us(1);	 
    	while(READ_SDA)
    	{
    		ucErrTime++;
    				delay_us(1);
    		if(ucErrTime>250)
    		{
    			IIC_Stop();
    			return 1;
    		}
    	}
    	IIC_SCL_L;//时钟输出0 	   
    	return 0;  
    } 
    
    //产生ACK应答
    void IIC_Ack(void)
    {
    	IIC_SCL_L;
    	SDA_OUT();
    	delay_us(3);
    	IIC_SDA_L;
    	delay_us(3);
    	IIC_SCL_H;
    	delay_us(3);
    	IIC_SCL_L;
    	delay_us(3);
    }
    //产生NACK应答		    
    void IIC_NAck(void)
    {
    	IIC_SCL_L;
    	SDA_OUT();
    	delay_us(3);
    	IIC_SDA_H;
    	delay_us(3);
    	IIC_SCL_H;
    	delay_us(3);
    	IIC_SCL_L;
    	delay_us(3);
    }		
    	
    //IIC发送一个字节
    //返回从机有无应答
    //1,有应答
    //0,无应答			  
    void IIC_Send_Byte(uint8_t txd)
    {                        
        uint8_t t;   
    	SDA_OUT(); 	    
        IIC_SCL_L;//拉低时钟开始数据传输
        for(t=0;t<8;t++)
        {              
            //IIC_SDA=(txd&0x80)>>7;
            if(((txd&0x80)>>7)){IIC_SDA_H;}
    			  else {IIC_SDA_L;}
            txd<<=1; 	  
    		delay_us(2);   //对TEA5767这三个延时都是必须的
    		IIC_SCL_H;
    		delay_us(4); 
    		IIC_SCL_L;	
    		delay_us(2);
        }	 
    } 	    
    //读1个字节,ack=0时,发送ACK,ack=1,发送nACK   
    uint8_t IIC_Read_Byte(unsigned char ack)
    {
    	unsigned char i,receive=0;
    	SDA_IN();//SDA设置为输入
    	IIC_SCL_L; 
      for(i=0;i<8;i++ )
    	{
            IIC_SCL_L; 
            delay_us(4);
    		IIC_SCL_H;
            receive<<=1;
            if(READ_SDA)receive++;   
    		delay_us(4); //delay_us(1); 
      }					 
        if (!ack)
            IIC_Ack();//发送ACK
        else
            IIC_NAck(); //发送NACK   
        return receive;
    }
    
    
    
    uint8_t IIC_WriteDate(uint8_t SlaveAddr,uint16_t SubAddr,uint8_t *pWriteData,uint16_t Len)
    {
    	 uint16_t i=0;
    	
    	 IIC_Start();
    	
    	 if(SlaveAddrLen==2)
    	 {
    	 IIC_Send_Byte(((SlaveAddr&0xFF00)>>8));
    	 if(IIC_Wait_Ack()==1) return 1;	
    	 delay_us(30);		 
    	 }		 
    	 IIC_Send_Byte(SlaveAddr&0x00FE);
    	 if(IIC_Wait_Ack()==1) return 1;	
    	 delay_us(30);
    	
    	
    	 if(SubAddrLen==2)
    	 {
    	  IIC_Send_Byte(((SubAddr&0xFF00)>>8));
        if(IIC_Wait_Ack()==1) return 1;	
        delay_us(30);
    	 }	 
    	 IIC_Send_Byte((SubAddr&0x00FF));
       if(IIC_Wait_Ack()==1) return 1;	
    	 delay_us(30);
    	 
    	 
    	 for(i=0;i<Len;i++)
    	 {
    		IIC_Send_Byte((pWriteData[i]));
    		if(IIC_Wait_Ack()==1) return 1;	
    		  delay_us(30);
    	 }
    	 IIC_Stop();
    	 return 0;		  
    }
    
    uint8_t IIC_ReadDate(uint8_t SlaveAddr,uint16_t SubAddr,uint8_t *pReadData,uint16_t Len)
    {
    	   uint8_t i=0;
    	  
    	   if(IIC_Start()==1)  return 1;    //Start
    	
    		 if(SlaveAddrLen==2)
    		 {
    		 IIC_Send_Byte(((SlaveAddr&0xFF00)>>8));
    		 if(IIC_Wait_Ack()==1) return 1;	
    		 delay_us(30);		 //30us
    		 }		 
    		 IIC_Send_Byte(SlaveAddr&0x00FE);
    		 if(IIC_Wait_Ack()==1) return 1;	
    		 delay_us(30);
    	
    	  if(SubAddrLen==2)
    	  {
    	    IIC_Send_Byte(((SubAddr&0xFF00)>>8));
          if(IIC_Wait_Ack()==1) return 1;		
    			delay_us(30);
    	  }		
    	  IIC_Send_Byte((SubAddr&0x00FF));
        if(IIC_Wait_Ack()==1) return 1;	
    		delay_us(30);
    		
    		IIC_Start();
    		
    		if(SlaveAddrLen==2)
    		{
    		IIC_Send_Byte(((SlaveAddr&0xFF00)>>8));
    		if(IIC_Wait_Ack()==1) return 1;	
    		delay_us(30);		 
    		}		 
    		IIC_Send_Byte(((SlaveAddr&0x00FE)|0x01));
    		if(IIC_Wait_Ack()==1) return 1;	
    		delay_us(30);
    		
    		for(i=0;i<(Len-1);i++)
    		{
    		   pReadData[i]=IIC_Read_Byte(0);
    			 delay_us(30);
    		}
    		pReadData[Len-1]=IIC_Read_Byte(1);
    		delay_us(30);
    		IIC_Stop();
    	  return 0;				
    }
    
    uint8_t IIC_StateCheck(uint8_t SlaveAddr)
    {
    	  if(IIC_Start()==1){IIC_Stop();return 1;}
    	
    		if(SlaveAddrLen==2)
    		{
    		IIC_Send_Byte(((SlaveAddr&0xFF00)>>8));
    		if(IIC_Wait_Ack()==1) {IIC_Stop(); return 1;}	
    		delay_us(30);		 
    		}		 
    		IIC_Send_Byte(SlaveAddr&0x00FE);
    		if(IIC_Wait_Ack()==1) {IIC_Stop(); return 1;}	
    		delay_us(30); 
    
        IIC_Stop();
    	  return 0;	
    }
    
    #ifndef __MYIIC_H
    #define __MYIIC_H
    
    #include "stm32f0xx.h"
    #include "delay.h"
    
    //PA9-->IIC_SCL PA10-->IIC_SDA  
    #define IIC_GPIO GPIOA
    #define IIC_SCL_PIN GPIO_Pin_9
    #define IIC_SDA_PIN GPIO_Pin_10
    #define IIC_SIZE 128
    
    extern uint16_t SlaveAddr;   //设备地址
    extern uint8_t  SlaveAddrLen;//设备地址字节数
    extern uint16_t SubAddr;     //片内地址
    extern uint8_t  SubAddrLen;  //片内地址字节数
    
    extern uint8_t IICReadBuf[IIC_SIZE]; //从IIC读到IICLen个数据缓存
    extern uint8_t IICWriteBuf[IIC_SIZE];//待写入IICLen个数据缓存
    extern uint16_t IICLen; //IIC操作长度
    
    //IO操作函数	 IIC_SCL_H
    #define IIC_SCL_L  GPIO_WriteBit(IIC_GPIO,IIC_SCL_PIN,(BitAction)0) //SCL
    #define IIC_SCL_H  GPIO_WriteBit(IIC_GPIO,IIC_SCL_PIN,(BitAction)1)
    #define IIC_SDA_L  GPIO_WriteBit(IIC_GPIO,IIC_SDA_PIN,(BitAction)0) //SDA	
    #define IIC_SDA_H  GPIO_WriteBit(IIC_GPIO,IIC_SDA_PIN,(BitAction)1)
    #define READ_SDA   GPIO_ReadInputDataBit(IIC_GPIO, IIC_SDA_PIN)  //输入SDA 
    #define READ_SCL   GPIO_ReadInputDataBit(IIC_GPIO, IIC_SCL_PIN)) //输入SCL
    
    //IIC所有操作函数
    
    void IIC_Init(void);                           //初始化IIC的IO口				 
    uint8_t IIC_Start(void);				         //发送IIC开始信号
    void IIC_Stop(void);	  			             //发送IIC停止信号
    void IIC_Send_Byte(uint8_t txd);			     //IIC发送一个字节
    uint8_t IIC_Read_Byte(unsigned char ack);      //IIC读取一个字节
    uint8_t IIC_Wait_Ack(void); 				     //IIC等待ACK信号
    void IIC_Ack(void);					         //IIC发送ACK信号
    void IIC_NAck(void);				             //IIC不发送ACK信号
    uint8_t IIC_StateCheck(uint8_t SlaveAddr);
    
     
    uint8_t IIC_WriteDate(uint8_t SlaveAddr,uint16_t SubAddr,uint8_t *pWriteData,uint16_t Len);
    uint8_t IIC_ReadDate(uint8_t SlaveAddr,uint16_t SubAddr,uint8_t *pReadData,uint16_t Len);
    
    #endif
    
    
    展开全文
  • IIC通信协议总结

    2020-04-23 14:02:40
    IIC通信协议总结 处理器和芯片间的通信可以形象的比喻成两个人讲话: 1、你说的别人得能听懂:双方约定信号的协议。 2、你的语速别人得能接受:双方满足时序要求。 看IIC协议先:两条线可以挂多个设备。IIC设备...

    IIC通信协议总结


    处理器和芯片间的通信可以形象的比喻成两个人讲话:
    1、你说的别人得能听懂:双方约定信号的协议。
    2、你的语速别人得能接受:双方满足时序要求。
    看IIC协议先:两条线可以挂多个设备。IIC设备(稍微有点智能的)里有个固化的地址。只有在两条线上传输的值等于我(IIC设备)的地址时,我才作出响应。
    IIC时序图
    开始信号:处理器让SCL时钟保持高电平,然后让SDA数据信号由高变低就表示一个开始信号。同时IIC总线上的设备检测到这个开始信号它就知道处理器要发送数据了。
    停止信号:处理器让SCL时钟保持高电平,然后让SDA数据信号由低变高就表示一个停止信号。同时IIC总线上的设备检测到这个停止信号它就知道处理器已经结束了数据传输,我们就可以各忙各个的了,如休眠等。

    IIC数据传送时序
    再看数据怎么传:SDA上传输的数据必须在SCL为高电平期间保持稳定:因为外接IIC设备在SCL为高电平的期间采集数据方知SDA是高或低电平。SDA上的数据只能在SCL为低电平期间翻转变化。
    响应信号(ACK):处理器把数据发给外接IIC设备,如何知道IIC设备数据已经收到呢?就需要外接IIC设备回应一个信号给处理器。处理器发完8bit数据后就不再驱动总线了(SDA引脚变输入),而SDA和SCL硬件设计时都有上拉电阻,所以这时候SDA变成高电平。那么在第8个数据位,如果外接IIC设备能收到信号的话接着在第9个周期把SDA拉低,那么处理器检测到SDA拉低就能知道外接IIC设备数据已经收到。
    IIC数据从最高位开始传输。
    再进一步说:IIC总线是允许挂载多个设备的,如何访问其中一个设备而不影响其他设备呢?

    在这里插入图片描述
    用7bit表示从地址,那么可以挂载的从设备数是2的7次方128个。处理器想写的话:先发送起始位,再发一个8bit数据:前7bit表示从地址,第8bit表示读或者写。0write是处理器往IIC从设备发,1read是IIC从设备往处理器发。第9个时钟周期回复响应信号。
    下面就以AT24Cxx为例详细说明一下:

    在这里插入图片描述
    首先发出一个start信号,从设备地址,R/W(0,写),回应ACK表示有这个从设备存在。这时候是处理器从指定的从设备读数据的从设备里8bit存储地址的指定。所以这里R/W是0为写。ACK回应有这个设备的话,处理器把要访问的从设备里的8bit存储地址写好。ACK对方回应。继续一个start信号+从设备地址,最低位是高电平表示读数据,回应ACK表示有这个从设备存在。在读数据的时候,每发出一个时钟,处理器会SDA上的数据存起来。那么发出8个时钟后处理器就能得到8位的数据。这时候若想连续读就不断回应ACK信号否则就发出停止信号。
    读的过程:start信号,从设备地址,写,待读取存储地址,再一个start信号,从设备地址,读,8个时钟,从设备就把对应的数据反馈给处理器。

    在这里插入图片描述
    start信号,哪一个设备地址,写,紧跟连续两个字节的数据:要写的地址,对方收到8bit地址后回应ACK,再8bit数据发给从设备,对方收到8bit数据后回应ACK,处理器写完后发送停止信号。

    展开全文
  • IIC总线协议总结

    千次阅读 2016-03-22 15:05:18
    IIC

    I2C(INTER IC BUS)

    前言:

    IIC 是多主设备的总线(同一时刻只有一个主设备,多主设备竞争仲裁),IIC只使用两条信号线,从机拥有唯一确定的地址(7位地址,后拓展支持10位地址)。

    主要总结了IIC的基本用法,对于多主竞争和高速模式,有兴趣可以自己研究,具体参考周立功的IIC 文档,非常详细。

     

    一.IIC构成

    1 物理层面

    只有2线(没算上地线),SDA数据线和SCL时钟线。

    速率:协议传输速率有三种,分别是:标准100kbps、快速400kbps、高速3.4Mbps。

    另一些变种实现了低速模式(10 kbps)和快速+模式(1 Mbps)。(不同的速率主要取决于芯片支持)。

     

    2 硬件电路

    上拉电阻连接到VCC,一般取值10K。上拉电阻是必须的,因IIC协议规定空闲时刻为高电平。上拉电阻取值大小主要考虑两个因素,一个是功耗和速度,上拉电阻与总线的电容形成了RC,因为总线拉高时有个充电时间以及高电平的阀值,如果还没有充电到足以保证从器件可以识别的高电平的阀值时主器件就以为完成了一个总线动作的话,那么通讯肯定是不能进行的。同样因RC电容充电时间,导致高速率瓶颈。

     

    3 IIC原则

    传输数据时,在SCL线为高电平时,主机或从机获取采样SDA的电平作为数据逻辑值,因此SCL高电平时候,SDA数据线必须保持稳定。在SCL=0(低电平)时,SDA数据线更改电平,从而传输不同的逻辑电平。在SCL线为高电平时,SDA变化会被判定为起始或者结束传输。

    SCl时钟线是由主设备控制,但允许SDA强行拉低SCL线以迫使主设备等待。


     

    二. 基本工作原理:

    1起始和停止

    IIC通信以START信号为每次传输的起始,STOP为传输结束释放总线。但是如果主机仍希望在总线上通讯,它可以重复产生起始条件和寻址另一个从机而不是首先产生一个停止条件,在这种传输中可能有不同的读写格式结合。

     


    2数据格式

    发送到SDA 线上以字节为单位,每个字节后必须跟一个响应位,每次传输可以发送的字节数量不受限制。首先传输的是数据的最高位MSB。如果从机要完成一些其他功能后(例如一个内部中断服务程序),才能接收或发送下一个完整的数据字节,可以使时钟线SCL保持低电平迫使主机进入等待状态,当从机准备好接收下一个数据字节,释放时钟线SCL后数据传输继续。

    数据传输必须带响应,每个字节后应该由对方回送一个应答信号ACK做为对方在线的标志。

     

    3传输过程:start -> addr -> datas -> stop/restart

    主机发送起始信号后,紧接着发送一个地址Byte,包括7位从机地址和以为读写位,第8位是数据方向位R/W,0表示发送写,1表示请求数据读

     


    三. 总线信号时序分析

    1 总线空闲状态

    SDA和SCL两条信号线都处于高电平,即总线上所有的器件都释放总线,两条信号线各自的上拉电阻把电平拉高。在物理实现上,SCL线和SDA线都是漏极开路(open-drain),通过上拉电阻外加一个电压源。当把线路接地时,线路为逻辑0,当释放线路,线路空闲时,线路为逻辑1。基于这些特性,IIC设备对总线的操作仅有“把线路接地”——输出逻辑0。基于这个特性,IIC可以做到时钟拉伸。

    2 7位地址

    I2C 总线的寻址过程是在起始条件后的第一个字节决定了主机选择哪一个从机。例外的情况是可以寻址所有器件的广播呼叫地址。使用这个地址时理论上所有器件都会发出一个响应,但是也可以使器件忽略这个地址。

    第一个字节的头7 位组成了从机地址。最低位LSB 是第8 位它决定了报文的方向。第一个字节的最低位是0 表示主机会写信息到被选中的从机,1 表示主机会向从机读信息。


    I2C 总线委员会协调I2C 地址的分配。见下表,可以看到如何拓展10位地址。11110xx,第8位依然是数据传输方向,其中xx是10位地址的最高位。

     

    3应答信号ACK
    I2C总线的数据都是以字节(8位)的方式传送的,发送器件每发送一个字节之后,在时钟的第9个脉冲期间释放数据总线,由接收器发送一个ACK(把数据总线的电平拉低)来表示数据成功接收。

    4无应答信号NACK

    在时钟的第9个脉冲期间发送器释放数据总线,接收器不拉低数据总线表示一个NACK,NACK有两种用途:
    a. 一般表示接收器未成功接收数据字节;
    b. 当接收器是主控器时,它收到最后一个字节后,应发送一个NACK信号,以通知被控发送器结束数据发送,并释放总线,以便主控接收器发送一个停止信号STOP。

    展开全文
  • IIC协议总线——总结

    2019-10-29 16:18:56
    IIC采用主从(Master-Slave)通信,适用于短距离,中低速设备通信,每次都是主机发起通信,和结束通信;从机不能主动发起通信。 空闲时:SDA和SCL保持为高,此时从机要完全释放总线。这个阶段SDA控制权在主机 ...

     

    IIC采用主从(Master-Slave)通信,适用于短距离,中低速设备通信,每次都是主机发起通信,和结束通信;从机不能主动发起通信。

     

    空闲时:SDA和SCL保持为高,此时从机要完全释放总线。这个阶段SDA控制权在主机

     

    总线空闲状态时,通信开始时的start信号产生:SDA由高变低。这个阶段SDA控制权在主机

     

    地址发送:在上阶段的基础上,接下来主机发送clk信号,主机也会在clk翻转过程中,将7bit 的IIC地址和控制位由高到低从SDA管脚发送,发送时。SDA在SCL为高电平时保持稳定,在SCL为低时变化。这个阶段SDA控制权在主机

    数据发送和接收:根据IIC协议,当通信一旦建立,主机就可以进行读或写,以下假设要读写n(n > 1)个字节的第一个字节,分别介绍:

    (1)主机放送数据:在上个阶段基础上,从机如果检测到IIC地址与之匹配,就会与主机建立通信,主机按照上一步规则发送8个bit数据,与此同时,从机接收8bt数据,由从机回ACK信号(在第9个clk时,拉低SDA,使SDA为低)。这个阶段前8个clk,SDA控制权在主机,第9个clk控制权在从机

    (2)主机接收数据:从机按照规则发送8个bit数据,与此同时,主机接收8bt数据,由主机回ACK信号(在第9个clk时,拉低SDA,使SDA为低)。这个阶段前8个clk,SDA控制权在从机,第9个clk控制权在主机

    通信结束时,stop信号的产生:SCL保持为高,SDA由低变高。这个阶段SDA控制权在主机

    随后IIC总线进入空闲状态。

     

    1. ACK/NAK信号到底是谁产生?

    答:由数据的接收方产生,不管主机和从机,都可以产生ACK/NAK信号。

    2.NAK信号什么情况下产生?

    答:地址不匹配;数据出错;最后一个字节传输完成,之后没有数据时;异常情况。

    3.SCL占空比有何影响?

    答:主要体现在数据的保持时间和建立时间的影响,中低速情况影响不大,当高速通信时,例如大于350K,留意IIC的建立和保持时间。

    4.IIC总线速度怎么理解?

    答:IIC总线速度有50K/100K/200K/250K/300K/400K/500K等规格,SCL每个周期可以发送1个bit,所以,如果SCL频率200KHz,可以理解成200Kbit/s,另外,速度快慢主要看主机如何配置。

    5. IIC第一个或前几个字节数据异常,怎么解决?

    答:出现数据异常有很多情况。

    例如,第一种,有可能软件IIC中断处理过多,耽误时间太长,数据还没放到buf就被总线采集。400K速度下,每个byte时间为9个clk,25us左右。如果软件处理需要>20us,就要检查软件中断处理;

    第二种出错可能是没有将数据提前放到buf中。当主机启动读命令时,就要提前将数据放到buf中,每次发送中断需要将下次发送的数据提前放到buf,否则,就会出现第一个字节出错。

    第三种:没有正确回应ACK/NAK信号;举个例子,有些场合下,主机来读2次数据,正常应该每次读完主机回应NAK,如果第一次读数据通信结束时,主机回应ACK,没有回NAK,从机就会以为主机还要读数据,所以拉住SDA总线,从机如果也没防范措施,就会持续拉死总线,那么,第2次读数据就会出错。

    第四种:器件特殊要求,有些芯片例如24C02一类,写操作最后要延时,数据手册称这段时间write cycle time 一般为5ms~10ms.如果没有延时直接操作进行下次操作就会NAK.

    6. IIC地址总是NAK?

    答:第一种:地址出错,检查配置的IIC地址;第二种:硬件原因:电压不匹配,SDA与SCL短路断路,上拉电阻不对等等。

    7.主机读数据有哪些?

    答:标准IIC中,读数据有2种方式:start+addr+w+reg+stop,start_addr+r+data+stop以及start+addr+w+reg+restart +addr+r_data+stop。细看这两种情况,第一种启动2次通信读寄存器,第二种,只发起1次通信就完成读寄存器

    展开全文
  • IIC协议博客记录

    2019-02-28 10:57:05
    比较详细的IIC协议博客记录: IIC通信协议总结 IIC协议
  • IIC协议

    2017-03-22 18:43:15
    三轴陀螺仪的芯片MPU-6050芯片驱动是采用IIC总线协议和处理器进行通信。...看IIC协议先:两条线可以挂多个设备。IIC设备(稍微有点智能的)里有个固化的地址。只有在两条线上传输的值等于我(IIC设备)的地址时
  • 总结IIC通信协议

    2013-06-02 18:01:48
    总结IIC通信协议,很好地学习资料,你值得一看!
  • 关于MPU6050学习的一些总结之二IIC协议前言一、IIC总线 前言 在查阅并了解了MPU6050的芯片手册后,已经对MPU6050有了大致的了解。那么接下来如何使MPU6050工作并且读取内部寄存器的数据呢?由于MPU6050是一个IIC元件...
  • I2C (Inter-IC)总线是一种简单、低带宽、短距离的协议。它通常出现在具有间歇访问的外围设备的系统中。这也是一个常见的通信解决方案,在一个封闭的系统,其中最小的痕迹是板上所希望的。许多半导体供应商在嵌入式...
  • IIC协议的知识总结与积累

    千次阅读 2015-12-11 15:01:09
    1.I2C协议 2条双向串行线,一条数据线SDA,一条时钟线SCL。 SDA传输数据是大端传输,每次传输8bit,即一字节。 支持多主控(multimastering),任何时间点只能有一个主控。 总线上每个设备都有自己的一个addr,共7个...
  • IIC协议应用实例

    2020-12-30 18:16:40
    这是一篇关于IIC协议的学习资料,感兴趣的话就关注我吧 文章目录前言一、IIC是什么?二、时序图三、代码1.IIC代码(理论)2.IIC实战1.MPU6050总结 前言 IIC协议是目前来说比较方便的一种协议,很多地方都可以用到...
  • IIC入门总结

    多人点赞 2021-02-19 21:53:21
    IIC(Inter-Integrated Circuit,是IICBus的简称,中文:集成电路总线),它是一种符合IIC协议的串行通信总线。一般两根线,一根是双向的数据线SDA,另一根也是双向的时钟线SCL,它们都通过一个电流源或上拉电阻连接...
  • IIC通信协议原理总结

    2019-07-09 14:50:42
    1.位传输:由于连接到 IIC 总线的器件有不同种类的工艺 (CMOS NMOS 双极性) 逻辑‘ 0 ’(低) 和 ‘1’(高 )的电平不是固定的 它由 VDD 的相关电平决定;每传输一个数据位就产生一个时钟脉冲 2.数据有效性:...
  • iic总线总结

    2021-03-05 10:42:12
    iic总线 物理概念 1、iic是一种半双工串行通信总线,由两根信号线组成一根双向数据线scl和一根时钟线clk组成。 2、iic传输速率有标准模式100...协议概念 1、为了保证数据的有效性,在时钟信号的高电平期间,数据信号
  • 案例采用明德扬设计思想...该篇博文主要讲如何使用verilog来描述IIC协议,以读写EEPROM为例带领大家了解下明德扬四段式状态机规范和优势,另外还有一些自己在设计过程中总结的经验技巧。  IIC协议时序格式以Data...
  • IIC协议是常用的嵌入式器件协议之一,它简单高效,便于应用. 本博客主要为个人学习总结,如有错误,请大家指出 主要的IIC通信有两种方式 1.软件GPIO模拟 2.IIC控制器 GPIO模拟的方式比较通用可移植性好,IIC控制器取决...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 157
精华内容 62
关键字:

iic协议总结