hATEmATH的网上田园

喂马 劈柴 做一个幸福的人
<2008年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011
公告
  • ◇ 欢迎来到这里的每一位朋友。

    ◇ 无需注册即可评论或留言。

    ◇ 文章无"转载(ZT)"字样均为原创。

    ◇ "随笔分类"中包含我的所有随笔

留言簿(13)

随笔分类

随笔档案

文章分类

文章档案

相册

工具网站

搜索

最新评论

阅读排行榜

评论排行榜

 
VC知识库BLOG   首页  新随笔  联系  聚合  登录 
  随笔-121 文章-20 评论-439 Trackbacks-0

 (转载请注明出处:HateMath的网上田园)

        上周用了一下24C02存储器和AD7416温度传感器.回顾起来,觉得关键之处是了解基于I2C总线传输标准的严格的时序操作.只要把I2C总线的几个信号类型搞清楚,剩下的只是按照器件的DataSheet上给出的控制时序图发送和接受数据即可.
    为此,今天特在这里用自己的语言做一下总结.需要首先说明的是,我是个水平很有限的菜鸟,无法保证文章中某些细节的绝对准确性,我所能保证的,就是让那些对基于I2C总线数据传输一窍不通的人能够在最短的时间内了解并会简单的使用它.

1. I2C总线是什么?

    I2C (Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。I2C总线产生于在80年代.
    以上是官方说法,其实说白了就是那么两条线,可以用来按照规定的格式传输数据.

2.我为什么要用I2C总线?
    传送数据的总线形式很多,为什么要用I2C总线?
    上面提到, I2C总线是一种”两线式串行总线”.这里,关键是"两线式".很显然,具有两条信号线的总线在电气连接上简洁方便,占用的空间小. 减少了电路板的空间和芯片管脚的数量,降低了互联成本。
    这两条线,就是传说中的时钟信号线(SCL)和数据信号线(SDA).

3.SCL 和 SDA
 对于使用I2C总线传输的器件来说,它可能和外界有一些连接,比如电源VCC和接地GND以及这个器件的地址线A2/A1/A0等等.这其中,最值得注意的两根线就是SCL 和 SDA,它们是器件和外界通信的接口.

    SCL(Serial CLock):  串行时钟信号线,用来给SDA上的数据传输提供时序.
    SDA(Serial DAta):    串行数据信号线,所有的数据都在这条线上传输.

    有人说,对于SCL和SDA我还是不大明白,听我打个比方你立刻就明白了.好比广播操比赛,如果每个人都是各自做各自的,那将是一团乱糟糟的景象,可是如果有人在前面喊:” 1234…2234”,那么大家的动作就很整齐,整个队形看上去也像个样子.这里,” 1234…2234”就是节拍信号SCL,大家的动作就是SDA了.
 
 相信大家一定明白了.下面让我们看一个实物图,增加一点感性认识.

图一 认识SCL和SDL
看到图中的四根红线了吗?中间两根分别就是SCL和SDA.边上的两根,自然是电源线了.

4. I2C总线中的信号.
    在了解I2C总线的工作原理之前,必须了解总线中的几种信号.就如同我们要想用英语写作,必须先学单词一样.值得庆幸的是, I2C总线的”单词”是很少的.
    I2C总线在传送数据过程中共有三种类型信号,分别是:开始信号(START)、结束信号(STOP)和应答信号(ACK)。它们的作用,有点像TCP/IP通讯中的握手信号.

    开始信号:SCL为高电平期间,SDA由高电平(H)向低电平(L)跳变,表示数据传送开始.
    结束信号:SCL为高电平期间,SDA由低电平向高电平跳变,表示数据传送结束.
    应答信号:接收数据的器件在正确接收到一系列数据(一般是8bit)后的下一个时钟脉冲期间(就是SCL为高电平期间),拉低SDA(即使SDA变为低电平),表示收到.

三种信号如下图所示:


    图二 在数据传输的任意时刻截取的I2C总线信号片断

注意:
1.SDA上有效数据(温度,指令等等)的传输只在SCL为高电平H时进行.显然,SCL为H时,SDA的数据应该保持稳定.
2.在SCL为H时,如果SDA的电平发生变化,只可能引起两种信号: 从上图中可以看出,当SDA由H变为L时,总线上出现”开始”信号,当SDA由L变为H时,总线上出现”停止”信号.
3.由2,我们可以得到一个明显但是重要推论:在传输有效数据时,SDA的电平变化只能在SCL为L的时候进行.否则,总线上将会出现开始或者停止信号,打乱器件的操作时序(基于I2C传输的器件对时序要求非常严格),使读取或写入操作失败.明白这一点对接下来的编写代码相当重要.当然,明白了这一点后,接下来的编写代码也变的相当简单.


5.总线通讯的原理
 这里所谓通讯,无非是按照时序进行数据交换罢了.比如现在想从温度传感器AD7416中读取温度值,应该怎么办呢?
 通过查AD7416的DataSheet(说明书),我们可以获得如下信息:
READING DATA FROM THE AD7416/AD7417/AD7418
……
Reading data from the temperature value, is a two-byte operation, as shown in Figure 11.


     你也许会说,这图看起来有点复杂.是的,我选了这个DataSheet中最复杂的时序图.并不是本人BT,等我把这个复杂的图讲简单后,你会发现I2C通信格式不过如此嘛.
    上图中,让我们先看看有熟悉得地方没有?有的,注意我手工标记的5个数字.其中,1 是开始信号,5是结束信号,2.3是应答信号,4么,暂时不用管它.

由上面的图我们可以看出,它的工作时序是这个样子:
1.控制器C(多半是微处理器)发出开始信号1
2.C紧接着在总线上发出寻址信号(里面包含器件D的地址),因为总线上可能有多个器件.
3.C收到D的响应,表示:你要找的器件在这.
4.D发送温度数据的高8位
5.C开始一位一位的接收D发出的温度数据,然后保存.
6.收到8位数据后,C发送一个响应信号,告诉D,收到了。
7.D发送温度数据的低8位。
8.收到并保存低8位数据后,C在紧随的下一个周期拉高SDA(就是4所标记的那个)。
9.C发出结束信号。

    就是这样子了,不要问我为什么过程这么繁杂,DataSheet里就是这么规定的。有意见的话,问AD公司去吧 ^_^。

6.举个用KeilC实现开始信号的例子
    上面已经把关键的地方和值得注意的事项讲完了.至于其中的开始、结束等信号,用微控制器很容易实现的。比如产生开始信号:

 设备:
    控制器: AT89C51
    传感器: AD7416

 接线:
    AT89C51的P3.4  <------> AD7416的SCL
    AT89C51的P3.5 <------> AD7416的SDA

//////////////////////////////////////////////////////////////////////
// Start()
// send start signal, tell AD7416 to start
void Start()
{
 SCL = 0;  //先让SCL 为低电平
 Delay();  // 延时几个微秒,让信号线有足够的时间变化为我们设置的电平.
 SDA = 1;  //在SCL为L的时候,改变SDA的状态
 Delay(); 
 SCL = 1;  // SCL 为H
 Delay();
 SDA = 0;  //此处实现SDA由高到低的跳变,开始信号就此产生
 Delay();
}

//////////////////////////////////////////////////////////////////////
//delay some time
void Delay()
{
 _nop_();
 _nop_();
}


    这么简单就完了?
    当然不是,不过上面给出的一个完整的Start()函数 告诉大家如何用代码控制开始信号的产生.把这个搞清楚后,接下来的停止信号、应答信号以及发送和接收有效数据信号都大同小异.

 

这是一个最简单的从AD7416中读取温度值的代码.我昨天测了,室内温度12度(如下图)




 下载KeilC51写的完整代码:
http://blog.vckbase.com/Files/HateMath/AD7416.rar

(全文结束)

posted on 2005-11-18 14:20 HateMath的网上田园 阅读(3648) 评论(14)  编辑 收藏
Comments
  • # re: I2C 总线之初体验
    roo
    Posted @ 2005-11-18 21:06
    虽然没看太懂,但还是长见识了,玩硬件真爽~
  • # re: I2C 总线之初体验
    freedk
    Posted @ 2005-11-18 23:42
    室内温度12。。~~~~~~~~~~~~~
  • # 呵呵,怎么看起来象定时炸弹啊?
    京山游侠
    Posted @ 2005-11-19 00:36
    呵呵,象定时炸弹
  • # re: I2C 总线之初体验
    zuilang
    Posted @ 2005-11-19 11:01
    剪红线?剪黑线??轰。。。。。
  • # re: I2C 总线之初体验
    ppa
    Posted @ 2005-11-21 09:07
    为什么不用串口通信呢?只有一个外设
  • # re: 为什么不用串口通信呢?只有一个外设
    HateMath
    Posted @ 2005-11-21 10:15
    re:ppa 
    在实际工程中,串口往往被充分利用的。鉴于AD7416是一个基于I2C总线通讯的器件,我觉得用普通的I/O口控制方便一些。如果用串口和7416通信更方便,不吝赐教。
  • # re: I2C 总线之初体验
    一笑
    Posted @ 2006-04-05 22:21
    说的很清楚啊。让偶看了都忍不住想动笔写写I2C了,嘿嘿。:)
    觉得你有些地方要是预先交代一下就更好了:
    1) I2C有7位地址和7位+扩展8位地址两种的,你用的是前者;
    2) I2C设备分为master和slaver两种,master->slaver和slaver->master的控制流程不同,write和read的控制流程也不同。read又分single read和combine read两种。你用的是slaver,做的是single read。所用的流程是master->slaver的single read的flow chart。
    3) 由于你强调了“注意2”“注意3”这两条,我觉得你有必要说明I2C slaver通知master有两种方式,一种是I2C bus interrupt方式,另一种是master轮寻方式。由于你的master是单片机,所以我想一定应该是论讯方式了,不过也未必,这点你没讲到。:)

    不过总体来说还是很有收获滴,希望能多输出好文档啊.~~
  • # re: I2C 总线之初体验
    HateMath
    Posted @ 2006-04-06 20:54
    to 一笑:

    看了你的comment, 我忍不住赞叹一句:我靠!一笑兄你太强了。

    其实我用iic也不多,就是想写个入门性质的文章。当然,你提及的几个问题都很有建设性,我会考虑适时对文章进行改写(干脆还是你写得了,呵呵)。

    我发现你确实很强啊,软硬都玩的通。那天是不是你说的搞ARM来着?我最近学51和PIC的单片机,下半年想学ARM,到时候希望老兄能指点一二,呵呵。
  • # re: I2C 总线之初体验
    一笑
    Posted @ 2006-04-06 22:06
    ^_^,你偶兄弟就不要客气了,以后多切磋哈。偶一直在手机驱动和平台移植的工作,所以软硬都玩一点,但是不精通哦。哎,有很多问题都是自己琢磨半个月一个月才搞出一个解决方案的。这方面的资料确实太少了,偶又没名师指导:( 不过现在好了,终于找到有共同爱好的哥们儿了:p
  • # re: I2C 总线之初体验
    x-rays
    Posted @ 2006-06-10 13:11
    强.不知道这位大哥有没有这个小系统的汇编程序,让我参考一下.
    邮箱:qingqiang0932@yahoo.com.cn
  • # re: I2C 总线之初体验
    x-forever
    Posted @ 2007-01-18 10:03
    受教了,谢谢!
  • # re: I2C 总线之初体验

    Posted @ 2008-01-19 13:02
    有没有QQ之类的,互相探讨下,电子及其他
  • # re: I2C 总线之初体验
    刘____alan
    Posted @ 2008-01-19 13:04
    我的邮箱是 haiyi617@126.com
    QQ:282070175   请加我,谢谢
  • # re: I2C 总线之初体验
    hatemath
    Posted @ 2008-01-21 16:35
    已发mail,谢谢访问我的blog。
标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]