模拟IIC.docx

上传人:b****5 文档编号:6502645 上传时间:2023-01-07 格式:DOCX 页数:16 大小:149.59KB
下载 相关 举报
模拟IIC.docx_第1页
第1页 / 共16页
模拟IIC.docx_第2页
第2页 / 共16页
模拟IIC.docx_第3页
第3页 / 共16页
模拟IIC.docx_第4页
第4页 / 共16页
模拟IIC.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

模拟IIC.docx

《模拟IIC.docx》由会员分享,可在线阅读,更多相关《模拟IIC.docx(16页珍藏版)》请在冰豆网上搜索。

模拟IIC.docx

模拟IIC

IIC总线

1、IIC总线简介

IIC总线是Philips推出的一种串行总线方式,它的全称是IntelIntegrateCircuitBus,它通过SDA(串行数据线)和SCL(串行时钟线)两根线在连到总线上的器件之间传送信息,并通过软件寻址识别每个器件,而不需要片选线(结合图1说明)。

IIC总线接口均为开漏或开集电极输出,因此需要为总线增加上拉电阻Rp。

总线速率越高,总线上拉电阻就越小,对于100Kbit/s总线速率,通常使用5.1K欧姆的上拉电阻。

IIC总线上的通信通常发生在两个器件之间,其中一个是主机另一个是从机,从机和主机均能读和写,ads1110只能作为从机。

2、数据方式

IIC总线有三种数据速率工作方式:

标准方式:

允许最高100KHz的时钟频率;

快速方式:

允许最高400KHz的时钟频率;

高速方式:

允许最高3.4MHz的时钟频率。

3、数据传送

一条IIC总线有两条线路构成:

SDA线和SCL线,SDA线传送数据,SCL提供时钟,所用数据以8位为一组在总线上传送。

在数据传送过程中,必须确认数据传送的开始和结束,这通过起始和结束信号识别,开始信号的条件是当时钟为高电平时,数据线从高到低的跳变;结束信号的条件是当时钟为高电平时,数据线从低到高的跳变。

(结合图2说明)

IIC的完整时序图,具体可参考ads1110的datasheet

发送起始信号后传送的第一字节数据具有特别的意义,其中前七位为从机地址,最后一位为读写方向位(0表示写,1表示读)。

IIC总线数据传送时,每传送一个字节数据后都必须有应答信号(A)。

主控器接收数据时,如果要结束通信时,将在停止位之前发送非应答信号(!

A)。

IIC总线是双向的:

SDA用来发送数据和接收数据,当主机从从机中读取数据时,从机驱动数据线,当主机向从机发送数据时,主机驱动数据线,主机总是驱动时钟线。

具有IIC接口的器件在通信中可以配置为主控器也可以作为被控器,那么它就具有4种操作模式:

主发送模式、主接收模式、从发送模式和从接收模式。

(结合图3说明)

 

多数时候总线是空闲的,不发生通信,两条线上均是高电平。

只有主机才能发起一次通信。

为了开始通信,主机必须发起一个开始信号,通常在SCL为低的时候数据才允许改变,否则在SCL线为高电平的时候数据线改变了状态,则形成一个开始条件或结束条件。

4对于没有IIC接口的器件,比如MCS-51单片机,若想使用IIC进行串行通信,硬件上可以外扩IIC接口芯片,软件上可以模拟IIC总线时序进行通讯,在此我们采用第二种方法,这就需要软件模拟IIC的读、写时序,模拟在作为接收器时的应答信号和非应答信号。

5、IIC程序构成及代码

IIC程序一共分成7个子程序块:

开始条件,结束条件,应答信号,发送连续读信号,发送不连续读信号,发送一个字节,接收一个字节。

5.1开始条件

当时钟信号SCL处于高电平期间数据线SDA有个由高到低的跳变则表示进入IIC通信。

代码段:

voidstart(void)//开始

{

SDA=1;

_nop_();

SCL=1;

_nop_();

SDA=0;

_nop_();

SCL=0;

_nop_();

}

5.2结束条件

当时钟信号SCL处于高电平期间数据信号SDA有个由低到高的跳变表示IIC通信结束。

代码段:

voidstop(void)//结束

{

SDA=0;

_nop_();;

SCL=1;

_nop_();

SDA=1;

_nop_();

SCL=0;

_nop_();

}

5.3应答信号

一个时钟周期内如果数据信号为低则产生一个应答信号,数据为高则没有应答。

程序最后有返回值。

注意:

在检查应答信号之前一定要先释放SDA的控制权:

SDA=1;否则程序会出错。

代码段:

unsignedcharcheck_ack(void)//检查应答信号

{

SDA=1;//检测从机应答信号之前应释放对SDA线的控制权

SCL=0;

SCL=1;

_nop_();

if(SDA)

{

ACK=1;

}

else

{

ACK=0;

}

SCL=0;

return(ACK);

}

5.4发送连续读信号,即主机工作在主接收方式下,接收完一个字节数据后发送应答信号

在读周期中,字节是8位为一组在总线上传送的,这就涉及到连续数据的传输。

注意:

主机发送完应答信号后要释放SDA。

代码段:

voidwrite_ack(void)//发送连续读信号

{

SCL=0;

SDA=0;

SCL=1;

_nop_();;

SCL=0;

SDA=1;//主发送机发送完应答信号后应释放SDA总线,否则

//只能读出第一个字节

}

5.5发送非应答信号(也可作为不连续读信号),在要结束IIC通信时可发一个非应答信号

在一个时钟周期内,数据线SDA始终为高,表示发送非应答信号。

代码段:

voidwrite_nack(void)//发送不连续读信号

{

SCL=0;

SDA=1;

SCL=1;

_nop_();

SCL=0;

}

5.6发送一个字节

以8位一个字节为一组进行发送。

代码段:

voidwrite_byte(unsignedchardate)//发送一个字节

{

unsignedchari=8;//发送8位

do

{

SCL=0;

if((date&0x80)==0x80)

{

SDA=1;//写1

}

else

{

SDA=0;//写0

}

SCL=1;

_nop_();

SCL=0;

date=date<<1;

}while(--i);

SDA=1;//发送完一个字节数据后应在接收器发送应答信号前释放总线

}

5.7接收一个字节:

有返回值。

代码段:

unsignedcharread_byte(void)//接收一个字节

{

unsignedchardate=0;

unsignedchari=8;

do

{

SCL=0;

SCL=1;

_nop_();

if(SDA)//读1

{

date=date|0x01;

}

SCL=0;

if(i-1)

{

date=date<<1;

}

}while(--i);

return(date);

}

6、典型应用

我们以16位A/D转换芯片ADS1110为例,说明其具体操作过程。

ADS1110的写操作是对配置寄存器进行的,首先要对ADS1110寻址,然后写入一个字节。

这个字节是写入配置寄存器。

输出寄存器不能被写入。

ADS1110的读操作首先也要对ADS1110寻址,然后从器件中读取三个字节,前两个是输出寄存器内容,第三个为配置寄存器内容。

ADS1110允许读少于三个的字节,但是多于三个字节是无效的。

从第四个以后所有的字节均为FF。

16位的输出寄存器包含了上次转换的结果,8位的配置寄存器是用来控制ADS1110的工作方式,数据速率和PGA的设置。

默认设置为8C。

具体信息参考datasheet中寄存器的说明部分。

写操作过程:

开始条件,对器件寻址,检查主机应答信号,有应答则继续。

写入一个字节到配置寄存器,检查应答信号,有应答则继续,最后结束IIC的写操作。

程序:

start();//开始一次通信

write_byte(0x90);//写器件地址(写)

if(check_ack())//检测应答信号

{

return(0);

}

write_byte(8c);//写配置字,8c为ads1110工作时的设置

if(check_ack())//检测应答信号

{

return(0);

}

stop();

读操作过程:

(ads1110是16位ad,转换结果分两次读出)

开始条件,读器件地址,检查主机应答信号,有应答则继续。

读高8位数据,主机发送连续读信号,读低8位数据,主机发送连续读信号,读配置寄存器状态,主机发送不连续读信号,结束IIC的读操作。

程序:

start();

write_byte(0x91);//写器件地址(读)

if(check_ack())//检测应答信号

{

return(0);

}

temp=read_byte();//读高8位

write_ack();//连续读

tempL=read_byte();//读低8位

write_ack();//连续读

config_s=read_byte();//读配置寄存器的状态

write_nack();

stop();//结束读

temp=(temp<<8)+tempL;//对两次读取的结果进行处理

整个过程:

开始--->>写从机地址(写操作)--->>检测应答信号(若有应答信号)--->>写配置字,设定从机工作方式--->>检测应答信号(若有应答信号)--->>写操作结束;

开始--->>写从机地址(读操作)--->>检测应答信号(若有应答信号)--->>读高8位转换数据--->>发送应答信号即连续读信号--->>读低8位转换数据--->>发送应答信号即连续读信号--->>读配置寄存器(可选)--->>发送非应答信号信号准备结束IIC通信--->>结束读操作,可对读到的两个8位数据联接成一个16位的数据;

一次读取转换数据结束。

注意:

在以下三个地方单片机要释放对SDA总线的控制权

1)单片机作为主发送机检查从机的应答信号之前要释放SDA总线

2)单片机作为主接收机发送应答信号之后要释放SDA总线

3)单片机作为主发送机发送完一个字节数据之后要释放SDA总线

他们有一个共同的特点,即在对从机进行读操作之前释放SDA总线

7、附ads1110完整程序清单如下:

//ADS1110的驱动程序,采用IIC通讯方式

sbitSDA=P1^3;//根据硬件实际连接作相应改动

sbitSCL=P1^2;

unsignedcharACK;

voidNOP()

{

_nop_();

_nop_();

}

*******************************************************************************

voidstart(void)//开始

{

SDA=1;

NOP();

SCL=1;

NOP();

SDA=0;

NOP();

SCL=0;

NOP();

}

**************************************************************************

voidstop(void)//结束

{

SDA=0;

NOP();

SCL=1;

NOP();

SDA=1;

NOP();

SCL=0;

NOP();

}

*************************************************************************

unsignedcharcheck_ack(void)//检查应答信号

{

SDA=1;//检测应答信号前应释放对SDA线的控制权

SCL=0;

SCL=1;

NOP();

if(SDA)

{

ACK=1;

}

else

{

ACK=0;

}

SCL=0;

return(ACK);

}

*********************************************************************

voidwrite_ack(void)//发送连续读信号

{

SCL=0;

SDA=0;

SCL=1;

NOP();

SCL=0;

SDA=1;//主发送机发送完应答信号后应释放SDA总线,否则只能读出第一个字节

}

***************************************************************************

voidwrite_nack(void)//发送不连续读信号

{

SCL=0;

SDA=1;

SCL=1;

NOP();

SCL=0;

}

**********************************************************************

voidwrite_byte(unsignedchardate)//发送一个字节

{

unsignedchari=8;//发送8位

do

{

SCL=0;

if((date&0x80))

{

SDA=1;//写1

}

else

{

SDA=0;//写0

}

SCL=1;

NOP();

SCL=0;

date=date<<1;

}while(--i);

SDA=1;//发送完一个字节数据后应在接收器发送应答信号前释放总线

}

******************************************************************************

unsignedcharread_byte(void)//接收一个字节

{

unsignedchardate=0;

unsignedchari=8;

do

{

SCL=0;//在时钟大于4u秒期间读数据

SCL=1;

NOP();

if(SDA)//读1

{

date=date|0x01;

}

SCL=0;

if(i-1)

{

date=date<<1;

}

}while(--i);

return(date);

}

**************************************************************

floatads1110(unsignedcharconfig)

{

unsignedintconfig_s;//配置字状态

unsignedinttemp;

unsignedinttempL;

floatadc_value;

start();

//开始写

write_byte(0x90);//写器件地址(写)

if(check_ack())//检测应答信号

{

return(0);

}

write_byte(config);//写配置字

if(check_ack())//检测应答信号

{

return(0);

}

stop();

start();

write_byte(0x91);//写器件地址(读)

if(check_ack())//检测应答信号

{

return(0);

}

temp=read_byte();//读高8位

write_ack();//连续读

tempL=read_byte();//读低8位

write_ack();//连续读

config_s=read_byte();//读配置寄存器的状态

write_nack();

stop();//结束读

temp=(temp<<8)+tempL;

x=56;

y=4;

printf("%d",temp);

adc_value=temp;

adc_value=adc_value*2.048/32768;

return(adc_value);

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1