I2C总线

来源:互联网 发布:英格拉姆赛季数据 编辑:程序博客网 时间:2024/05/01 05:32
I2C的时序是比较复杂的,你如果能把I2C的时序弄清,那其他器件的时序都不成问题了。

我就按照我的理解来跟你讲吧。
直接用程序来说明吧。

NOP(),一个机器周期时间的延迟,12M晶振时为1微秒
NOPS(),4个NOP()。
sbit SDA P2^0;
sbit SCL P2^1; 定义数据线和时钟线接口
首先,I2C有2个重要的线,SDA数据线SCL时钟线,当总线上没有进行信息传送时,SDA和SCL都为高电平,我们称之为释放总线。
开始传送信息时,要有一个开始信号,
开始信号 :定义为在SCL为高电平的时候,SDA从高电平拉低。
start()
{
SDA=1;
NOP(); //同你图中 SDA/SCL上升/下降所用时间 1US
SCL=1;
NOPS(); //建立开始信号(同你图中TSU起始信号建立时间一样4US)
SDA=0; //SDA拉低
NOPS();
SCL=0; //SCL拉低, 钳住总线,准备发送或接收数据
NOP();
}
结束信号:与开始信号相反,在SCL为高电平时,SDA从低拉高
stop()
{
SDA=0;
NOP();
SCL=1;
NOPS(); //建立信号时间
SDA=1; //拉高 结束。
NOPS();
}
我晕,发现写了半天还有好多。。算了 帮人帮到底了
发送/接收一个数据:数据的发送和接收都是在SCL为低电平的时候发生,因为SCL为高电平时已给了开始和结束信号。发送数据时,当数据准备读入时,将SCL线暂时拉高(SCL为高时,SDA无法改变状搜索态),保持一段时间然后拉低(同你图中的TDH,数据输出保持时间),这时数据则发送完毕到SDA上。接收则与之大同小异。当SDA线上有数据过来时,先将SCL拉高,建立好时间,然后拉低,数据则被读入。(关于如何被发出以及如何被读入则是芯片做的事,我们不用管,只需记住SCL拉低,数据发出/读入)
用程序来讲就是:
send(uchar c) //发送一个字节
{
uint i;
for(i=0;i<8;i++) //该字节8位从高往低发送
{
if((c<<i)&0x80) SDA=1;
else SDA=0;
NOP();
SCL=1; //建立信号时间
NOPS();
SCL=0; //发送完毕
}
}
recieve()
{
uchar r;uint i;
r=0;SDA=1;
for(i=0;i<8;i++) //读取8位数据
{
NOP();
SCL=0;
NOPS();
SCL=1;
NOP();
r<<=1;
if(SDA==1) r+=1;
NOP();
}
SCL=0;
NOP();
return (r);
}
程序可能有点难懂,不过没关系,使用I2C时候,直接调用写好的程序,如我写的 start.stop.send receive 等,这些程序应该有现成的。

发送一个字节后会有一个应答函数,应答函数定义为,当发送完一个字节也就是8位的时候,如果这是SDA为低电平,则为有应答,反之则无。如果要发送多个字节,一个字节发完后需要一个应答函数才能继续发下面一个字节。程序也就大同小异。掌握好时序就行了。

I2C用的最多的就是E2PROM了。
给你举个例子
如果我想往E2PROM的0x50单元写一个‘a’,则我这样写:
start(); //开始
send(0xa0); //选择我要发送的器件。0xa0为E2PROM的器件地址
answer(); //应答
send(0x50); //选择E2PROM中的0X50地址单元
answer(); //应答
send('a'); //发送数据‘a’
stop(); //停止
0 0
原创粉丝点击