快捷搜索:  汽车  科技

IIC通信详解(IIC通信详解)

IIC通信详解(IIC通信详解)IIC分为软件IIC和硬件IIC  二者都可以传输数据,但是从设备不能发起传输,且传输是受到主设备控制的。  IIC总线通过上拉电阻接正电源。当总线空闲时,两根线均为高电平(SDL=1;SCL=1)。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。 2、主设备与从设备  系统中的所有外围器件都具有一个7位的\从器件专用地址码\,其中高4位为器件类型,由生产厂家制定,低3位为器件引脚定义地址,由使用者定义。主控器件通过地址码建立多机通信的机制,因此I2C总线省去了外围器件的片选线,这样无论总线上挂接多少个器件,其系统仍然为简约的二线结构。终端挂载在总线上,有主端和从端之分,主端必须是带有CPU的逻辑模块,在同一总线上同一时刻使能有一个主端,可以有多个从端,从端的数量受地址空间和总线的最大电容 400pF的限制。

IIC概述

IIC:两线式串行总线,它是由数据线SDA时钟线SCL构成的串行总线,可发送和接收数据。

在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbs以上。

时钟线SCL:在通信过程起到控制作用。
数据线SDA:用来一位一位的传送数据。

SDA:双向数据线,为OD门,与其它任意数量的OD与OC门成\线与\关系。

  IIC总线通过上拉电阻接正电源。当总线空闲时,两根线均为高电平(SDL=1;SCL=1)。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。


2、主设备与从设备

  系统中的所有外围器件都具有一个7位的\从器件专用地址码\,其中高4位为器件类型,由生产厂家制定,低3位为器件引脚定义地址,由使用者定义。主控器件通过地址码建立多机通信的机制,因此I2C总线省去了外围器件的片选线,这样无论总线上挂接多少个器件,其系统仍然为简约的二线结构。终端挂载在总线上,有主端和从端之分,主端必须是带有CPU的逻辑模块,在同一总线上同一时刻使能有一个主端,可以有多个从端,从端的数量受地址空间和总线的最大电容 400pF的限制。

  二者都可以传输数据,但是从设备不能发起传输,且传输是受到主设备控制的

IIC分为软件IIC和硬件IIC

软件IIC:软件IIC通信指的是用单片机的两个I/O端口模拟出来的IIC,用软件控制管脚状态以模拟I2C通信波 形,软件模拟寄存器的工作方式。 硬件IIC:一块硬件电路,硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专 用的,硬件(固件)I2C是直接调用内部寄存器进行配置。

补充

1.硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。 2.IIC是半双工通信方式IIC通信协议

IIC通信过程由开始、结束、发送、响应、接收五个部分构成。

1、(在发送、接收数据的时候)当SCL为高电平时,SDA线不允许变化;当SCL线为低电平时,SDA线可以任意0、1变化。 2、(在任意时候)只有当SCL为高电平时,IIC电路才对SDA线上的电平(0或者1)进行记录,当SCL线为低电平时,无论SDA是高还是低,IIC电路都不对SDA进行采样。空闲状态

在介绍上面五个部分前,我们首先说说空闲状态,什么是空闲状态,就是没有通信时的状态初始状态

//产生IIC起始信号 //1.设置SDA输出 //2.先拉高SDA,再拉高SCL,空闲状态 //3.拉低SDA //4.准备接收数据 void IIC_Start(void) { SDA_OUT(); //sda线输出 IIC_SDA=1; IIC_SCL=1; delay_us(4); IIC_SDA=0;//START:when CLK is high DATA change form high to low delay_us(4); IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 } 开始信号与停止信号

开始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平。 停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。

IIC通信详解(IIC通信详解)(1)

图1

开始信号程序

//产生IIC起始信号 //1.设置SDA输出 //2.先拉高SDA,再拉高SCL,空闲状态 //3.拉低SDA //4.准备接收数据 void IIC_Start(void) { SDA_OUT(); //sda线输出 IIC_SDA=1; IIC_SCL=1; delay_us(4); IIC_SDA=0;//START:when CLK is high DATA change form high to low delay_us(4); IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 }

停止信号程序

//产生IIC停止信号 //1.设置SDA输出 //2.先拉低SDA,再拉低SCL //3.拉高SCL //4.拉高SDA //5.停止接收数据 void IIC_Stop(void) { SDA_OUT();//sda线输出 IIC_SCL=0; IIC_SDA=0;//STOP:when CLK is high DATA change form low to high delay_us(4); IIC_SCL=1; IIC_SDA=1;//发送I2C总线结束信号 delay_us(4); }应答信号

发送器每发送一个字节,就在时钟脉冲9期间释放数据先,由接收器反馈一个应答信号。应答信号为低电平 时,规定为有效应答位(ACK简称应答位),表示接收器已经成功接收了该字节;应答信号为高电平时,规定 为非应答位(NACK) 一般表示接收器接收该字节没有成功。对于反馈有效应答位ACK的要求是,接收器在第9 个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间位稳定的低电平。如果接收器 是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放 SDA线,以便主控接收器发送一个停止信号P

每当主机向从机发送完一个字节的数据,主机总是需要等待从机给出一个应答信号,以确认从机是否成功接收到了数据,从机应答主机所需要的时钟仍是主机提供的,应答出现在每一次主机完成8个数据位传输后紧跟着的时钟周期,低电平0表示应答,1表示非应答:

IIC通信详解(IIC通信详解)(2)

图2

应答信号程序

//产生ACK应答 //这里就很清楚了,产生应答:SCL在SDA一直为低电平期间完成低高电平转换 void IIC_Ack(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=0; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; } //不产生ACK应答 //这里就很清楚了,不产生应答:SCL在SDA一直为高电平期间完成低高电平转换 void IIC_NAck(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=1; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; } 发送数据

在I2C总线上传送的每位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,SDA逐 位地串行传送每一位数据。数据位的传输是边沿触发。

//IIC发送一个字节 //返回从机有无应答 //1,有应答 //0,无应答 //IIC_SCL=0; //在SCL上升沿时准备好数据,进行传送数据时,拉高拉低SDA,因为传输一个字节,一个SCL脉冲里传输一个位。 //数据传输过程中,数据传输保持稳定(在SCL高电平期间,SDA一直保持稳定,没有跳变) //只有当SCL被拉低后,SDA才能被改变 //总结:在SCL为高电平期间,发送数据,发送8次数据,数据为1 SDA被拉高,数据为0,SDA被拉低。 //传输期间保持传输稳定,所以数据线仅可以在时钟SCL为低电平时改变。 void IIC_Send_Byte(u8 txd) { u8 t; SDA_OUT(); IIC_SCL=0;//拉低时钟开始数据传输 for(t=0;t<8;t ) { //IIC_SDA=(txd&0x80)>>7; //获取数据的最高位,然后左移7位 //如果某位为1,则SDA为1,否则相反 if((txd&0x80)>>7) IIC_SDA=1; else IIC_SDA=0; txd<<=1; delay_us(2); //对TEA5767这三个延时都是必须的 IIC_SCL=1; delay_us(2); IIC_SCL=0; delay_us(2); } }

单片机发送完一个字节后面必须跟一个等外应答函数:

思路:先让SDA=1,再判断在一定时间内SDA是否变为0,从而识别出外设有没有发送应答信号。

//等待应答信号到来 //返回值:1,接收应答失败 // 0,接收应答成功 //1.设置SDA为输入 //2.拉高SDA //3.拉高SCL //4.等待接收器返回应答信号,如果数据线SDA一直为高,就一直等待,并返回1(无效应答),如果数据线SDA为低,返回0(有效应答) u8 IIC_Wait_Ack(void) { u8 ucErrTime=0; SDA_IN(); //SDA设置为输入 IIC_SDA=1;delay_us(1); IIC_SCL=1;delay_us(1); while(READ_SDA) { ucErrTime ; if(ucErrTime>250) { IIC_Stop(); return 1; } } IIC_SCL=0;//时钟输出0 return 0; } 接收数据

发送数据是一位一位发送,接收数据也是一位一位接收进来,最后返回应答信号:

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK //先拉低SCL,延时后拉高 //读取数据 //是否发送应答 u8 IIC_Read_Byte(unsigned char ack) { unsigned char i receive=0; SDA_IN();//SDA设置为输入 for(i=0;i<8;i ) { IIC_SCL=0; delay_us(2); IIC_SCL=1; receive<<=1; if(READ_SDA)receive ; delay_us(1); } if (!ack) IIC_NAck();//发送nACK else IIC_Ack(); //发送ACK return receive; }

猜您喜欢: