I2C总线原理与应用文档格式.docx
- 文档编号:17720538
- 上传时间:2022-12-08
- 格式:DOCX
- 页数:10
- 大小:33.07KB
I2C总线原理与应用文档格式.docx
《I2C总线原理与应用文档格式.docx》由会员分享,可在线阅读,更多相关《I2C总线原理与应用文档格式.docx(10页珍藏版)》请在冰豆网上搜索。
下面我们以ATMEL公司的AT24C02来介绍I2C的基本操作
AT24C02是美国ATMEL公司的低功耗CMOS串行EEPROM,它是内含256×
8bit存储空间,具有工作电压宽(2.5~5.5V)、擦写次数多(大于10000次)、写入速度快(小于10ms)等特点。
他在系统中始终为从动器件。
对AT24C02的操作主要有:
字节读,字节写,页面读,页面写
首先发送起始信号,如下图,起始信号后必须是控制字,
控制字格式如下,其中高四位为器件类型识别符(不同的芯片类型有不同的定义,EEPROM一般应为1010),接着三位为片选,也就是三个地址位,最后一位为读写控制位,当为1(Input)时为读操作,为0(Output)时为写操作。
控制字后就是相应的操作,读或写,一定不要结束,因为这个操作还没有完成,如果结束就等于放弃操作。
先来看写操作,写操作分为字节写和页面写两种操作,对于页面写根据芯片的一次装载的字节不同有所不同,AT24C02为8字节,每写一个字节后,地址自动加1。
关于页面写的地址、应答和数据传送的时序参见图3,字节写可以看成是只有一个字节的页面写,也就是写一个数据后停止。
注意:
写一次需要一定时间,一般为10ms,要等侍这个操作完成。
时序如下图:
说明:
对于AT24C02,在控制字后还必须写入地址,这个地址是以后读写的起始地址。
读操作有三种基本操作:
当前地址读、随机读和顺序读。
三种操作方法类似,只是读的数据个数不同,可连续读8个字节,图4给出的是顺序读的时序图,图中共读了四个数据,需要注意的是当前的地址,如果不是想要的,可以用写操作,重新写入地址。
非常重要的是,每读一个数据后,必须置低SDA,作为应答,否则,只能读一个数据,后面的数据,因为收到不应答信号,AT24C02就会认为出错,停止操作。
特别提醒的是,当SCL为低电平时,数据是可变的,因些只有SCL为高电平时,才能读数。
(相关时序,请看例程序的,读功能函数)
四.例程序(51汇编,测试单片机为AT89C51,12M晶振)
电路连接如图5,其中A0,A1,A2为地址线,本例中全部接地,因此全部为0。
由于SCL和SDA为漏极开路输出,所以在使用时,需加上拉电阻。
关于I2C总线的基本操作
软件实现I2C主模式通讯看似简单,但实际应用中最容易犯的错误就是对SCL和SDA总线上高电平的实现过程。
在硬件设计上,任意选择单片机的两个IO引脚分别指派为SCL和SDA,虽然不是必须的,但为方便软件编程一般设于同一个端口,并在其上外接上拉电阻,至于ESD保护电阻和抗干扰滤波电容则为可选件,不影响I2C总线通讯。
当器件占用总线时,需要在SCL或SDA引脚上输出低电平,软件就将PORT寄存器相关位设定为0的同时对应的TRIS寄存器位也设为0;
当释放总线即总线上变为高电平时,注意不能直接从IO引脚上输出高电平,而是应该将TRIS位设为1,使引脚变成高阻输入状态,通过外接的上拉电阻得到高电平。
很多工程师没有遵循这种操作规范,尽管在特定的应用中也可以实现I2C通讯,但留有很多隐患,不可盲目照搬。
对于PIC单片机来说,I2C总线的控制基本上可以简化到对TRIS寄存器相关位的控制。
在初始化时先将数据端口寄存器PORTx和PORTx引脚设为0。
需要总线为0,则TRISx=0或TRISx=0;
释放总线,则TRISx=1或TRISx=1。
当单片机需要从总线上读取从器件发出的数据和应答信号时,则直接读取PORTx引脚的输入电平。
由于PORTx和TRISx寄存器在不同的bank,在程序中可以利用FSR做间接寻址以减少bank切换。
MCS-51单片机模拟I2C软件包(V1.1)(c)
/********************************************************************
MCS-51单片机模拟I2C软件包(V1.1)
文件名:
VI2C_C51.C
相关文件:
VI2C_C51.H,VI2C_C51.LIB
功能说明:
本模拟I2C软件包包含了I2C操作的底层函数,如发送数据及接收
数据,应答位发送,并提供了几个直接面对器件的操作函数,它很方便的与用户程
序连接并扩展.....
注意:
函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作一定的
修改....(本软件包是1us机器周期,即晶振频率要小于12MHZ)
总线时序符合I2C标准模式,100Kbit/S。
更新时间:
2002.06.05
********************************************************************/
#include<
reg51.h>
intrins.h>
#define
ucharunsignedchar
/*宏定义*/
uint
unsignedint
_Nop()
_nop_()
/*定义空指令*/
sbitSDA=P3^4;
/*模拟I2C数据传送位*/
sbitSCL=P3^5;
/*模拟I2C时钟控制位*/
bitack;
/*应答标志位*/
/*******************************************************************
起动总线函数
函数原型:
void
Start_I2c();
功能:
启动I2C总线,即发送I2C起始条件.
voidStart_I2c()
{
SDA=1;
/*发送起始条件的数据信号*/
_Nop();
SCL=1;
/*起始条件建立时间大于4.7us,延时*/
SDA=0;
/*发送起始信号*/
/*起始条件锁定时间大于4μs*/
SCL=0;
/*钳住I2C总线,准备发送或接收数据*/
}
结束总线函数
Stop_I2c();
结束I2C总线,即发送I2C结束条件.
voidStop_I2c()
/*发送结束条件的数据信号*/
/*发送结束条件的时钟信号*/
/*结束条件建立时间大于4μs*/
/*发送I2C总线结束信号*/
字节数据发送函数
SendByte(ucharc);
将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使ack=0)
发送数据正常,ack=1;
ack=0表示被控器无应答或损坏。
void
SendByte(ucharc)
ucharBitCnt;
for(BitCnt=0;
BitCnt<
8;
BitCnt++)
/*要传送的数据长度为8位*/
{
if((c<
<
BitCnt)&
0x80)SDA=1;
/*判断发送位*/
else
/*置时钟线为高,通知被控器开始接收数据位*/
/*保证时钟高电平周期大于4μs*/
}
/*8位发送完后释放数据线,准备接收应答位*/
if(SDA==1)ack=0;
elseack=1;
/*判断是否接收到应答信号*/
字节数据接收函数
uchar
RcvByte();
用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数应答从机。
********************************************************************/
uchar
RcvByte()
ucharretc;
ucharBitCnt;
retc=0;
/*置数据线为输入方式*/
for(BitCnt=0;
BitCnt++)
/*置时钟线为低,准备接收数据位*/
/*时钟低电平周期大于4.7μs*/
/*置时钟线为高使数据线上数据有效*/
retc=retc<
1;
if(SDA==1)retc=retc+1;
/*读数据位,接收的数据位放入retc中*/
return(retc);
应答子函数
voidAck_I2c(bita);
主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
voidAck_I2c(bita)
if(a==0)SDA=0;
/*在此发出应答或非应答信号*/
elseSDA=1;
/*时钟低电平周期大于4μs*/
/*清时钟线,钳住I2C总线以便继续接收*/
用户接口函数
*******************************************************************/
向无子地址器件发送字节数据函数
bit
ISendByte(ucharsla,ucahrc);
从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
如果返回1表示操作成功,否则操作有误。
使用前必须已结束总线。
bitISendByte(ucharsla,ucharc)
/*启动总线*/
SendByte(sla);
/*发送器件地址*/
if(ack==0)return(0);
SendByte(c);
/*发送数据*/
/*结束总线*/
return
(1);
向有子地址器件发送多字节数据函数
ISendStr(ucharsla,ucharsuba,ucahr*s,ucharno);
从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
bitISendStr(ucharsla,ucharsuba,uchar*s,ucharno)
uchari;
SendByte(suba);
/*发送器件子地址*/
for(i=0;
i<
no;
i++)
{
SendByte(*s);
s++;
}
向无子地址器件发送多字节数据函数
ISendStr(ucharsla,ucahr*s,ucharno);
地址sla,发送内容是s指向的内容,发送no个字节。
bitISendStrExt(ucharsla,uchar*s,ucharno)
向无子地址器件读字节数据函数
IRcvByte(ucharsla,ucahr*c);
从启动总线到发送地址,读数据,结束总线的全过程,从器件地
址sla,返回值在c.
bitIRcvByte(ucharsla,uchar*c)
SendByte(sla+1);
*c=RcvByte();
/*读取数据*/
Ack_I2c
(1);
/*发送非就答位*/
向有子地址器件读取多字节数据函数
从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
*********************************
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- I2C 总线 原理 应用
![提示](https://static.bdocx.com/images/bang_tan.gif)