友情推荐网上购书渠道:
EDN网(ednchina)购书入口   >>>
互动出版网(china-pub)购书入口   >>>
当当网(dangdang)购书入口   >>>
淘宝网(taobao)购书入口   >>>
更多购书渠道……   >>> 

设为首页加入收藏联系匠人管理入口21IC首页21IC博客21IC社区侃单片机回复的贴参与的贴

天气预报
百宝日历

百宝专栏

  • 首页 相册 标签
  • 电脑应用(65)
  • 供需信息(22)
  • 写书近况(82)
  • 匠人文集(115)
  • 硬件技术(171)
  • 匠人公告(86)
  • 与非门专栏(545)
  • 匠人笔记(115)
  • 团队撰写(96)
  • 汽车电子(52)
  • 编程技巧(465)
  • 程序宝典(476)
  • 网络酷文(472)
  • 开发工具(19)
  • 资料宝藏(274)
  • 项目管理(11)
  • 藏经宝阁(42)
  • 趣味设计(5)
  • 社区热贴(2)
  • 比尔盖茨熊专栏(0) 
  • 百宝信息

    载入中...

    百宝流量

    (2006-07-01开始)



    匠人手记

    芯片专题

    器件专题

    软件专题

    硬件专题

    综合专题

    项目专题

    原创专题

    器件检测
    LCD LED
    按键 触摸键
    E2PROM
    电池 电机
    电阻 电容 电感

    指令系统
    软件算法
    编程规范
    滤波算法
    串行通讯

    PCB设计
    I2C PWM
    红外遥控
    充电技术
    中断 ADC 

    匠人手记
    匠人夜话
    网络心路
    一周热点串烧
    从零开始玩PIC
    DIY旋转时钟

    I2C 24LC02 C读写例程(PIC单片机)
    pcbomb 发表于 2008-4-22 10:11:00  阅读全文 | 回复(0) | 引用通告 | 编辑

    1   I2C总线特点
       I2C总线最主要的优点是其简单性和有效性。由于接口直接在组件之上,因此I2C总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件。I2C总线的另一个优点是,它支持多主控(multimastering), 其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。

    2   I2C总线工作原理
    I2C总线上的数据稳定规则,SCL为高电平时SDA上的数据保持稳定,SCL为低电平时允许SDA变化。如果SCL处于高电平时,SDA上产生下降沿,则认为是起始位,SDA上的上升沿认为是停止位。通信速率分为常规模式(时钟频率100kHz)和快速模式(时钟频率400kHz)。同一总线上可以连接多个带有I2C接口的器件,每个器件都有一个唯一的地址,既可以是单接收的器件,也可以是能够接收发送的器件。

    每次数据传输都是以一个起始位开始,而以停止位结束。传输的字节数没有限制。最高有效位将首先被传输,接收方收到第8位数据后会发出应答位。数据传输通常分为两种:主设备发送从设备接收和从设备发送主设备接收。这两种模式都需要主机发送起始位和停止位,应答位由接收方产生。从设备地址一般是1或2个字节,用于区分连接在同一I2C上的不同器件。

    I2C总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。
       开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
       结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
       应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。

    在I2C总线中只有主发送和主接收两种操作方式。在系统初始化时,由指令控制CPU送出相关的数据,经接口送到I2C寄存器内。通过初始化这些寄存器,可以实现I2C总线的主模式控制,以及实现I2C总线上的从设备读写。

          当主设备和其中的一个从设备交换数据时,主设备首先发出一个启动Start信号,这个信号被所有的从设备接收。即从设备准备接收CPU的信号,然后主设备再发出它要通信的从设备地址。接下来,所有的从设备将收到的这个地址和它们自己的地址进行比较。

    如果收到的地址和它们自己的地址不同,则什么都不做,只是等待主设备发出停止stop信号;如果收到的地址和它自己的地址相同,它就发出一个信号给主设备,这个信号称为应答Acknowledge信号。当主设备收到应答信号后,它就开始向从设备发送数据或者从从设备接收数据。当所有操作都进行完毕时,主设备发出一个Stop信号,通信完毕,释放I2C总线;然后所有的从设备都等待下一次Start信号的到来。

    3   总线基本操作
       I2C规程运用主/从双向通讯。器件发送数据到总线上,则定义为发送器,器件接收数据则定义为接收器。主器件和从器件都可以工作于接收和发送状态。 总线必须由主器件(通常为微控制器)控制,主器件产生串行时钟(SCL)控制总线的传输方向,并产生起始和停止条件。SDA线上的数据状态仅在SCL为低电平的期间才能改变,SCL为高电平的期间,SDA状态的改变被用来表示起始和停止条件。
    3.1 控制字节
       在起始条件之后,必须是器件的控制字节,其中高四位为器件类型识别符(不同的芯片类型有不同的定义,EEPROM一般应为1010),接着三位为片选,最后一位为读写位,当为1时为读操作,为0时为写操作。

    1.写过程

    (1)上电后等待一个延时(1ms)。

    (2)器件寻址,给一个起始信号(SCL为高电平时SDA给一个下降沿)。发送从器件地址,高5位为10110,然后根据A1/A0(如果和器件的地址相同则那个器件会应答)进行读/写控制(O为读)。

    (3)应答,器件在SCL的第9个周期时SDA给出一个低电平,作为应答信号。

    (4)开始写有两种模式:字节写模式和页写模式。

    ·字节模式:给出A15~A8应答,给出A7~A0应答;然后给出DATA和停止信号     (SCL为高电平时,SDA给出一个上升沿),接着要等待一个擦写时间。

    ·页写模式:给出地址以后连续给出64个数据。如果多于64个数据,则地址计数器自动翻转。(如果少于64昵,估计是没有问题的,但是需要实验验证。)

    (5)判断擦写操作是否完毕的一个方法(应答查询),如果器件还处于擦写状态,则不会应答器件寻址;如果有应答,则说明擦写完毕。

    2.读过程

    (1)上电以后等待一个延时(lms)。

    (2)器件寻址。

    (3)应答。

    (4)开始读有三种模式:立即当前地址读、选择/随机读、连续读。

    ·立即当前地址读:如果上次读/写的操作地址为N,则现在是N+1。不需要ACK,但是需要Stop信号。

    ·选择/随机读:先伪写(用于给出一个地址),然后再次启动,读取数据。

    ·连续读:读取一个以后给一个应答,这样器件会再给出下一个地址的数据内容。

    (5)开始数据传输Start后、停止数据传输Stop前,SCL高电平期间,SDA上为有效数据。

    /*******************************************************************
    一、程序说明:
    1, 24LC02器件地址是1010000R/W.
    2, 数组写入24LC02采取页写方式.
    3, 数组code从24LC02读出时采取自由读方式.
    4, 采用4.00M晶体。
    5,采用软件I2C。

    二、硬件连接:
    1, SDA------->23 pin.(当然你可以任意选择脚位)
    2, SCL------->18 Pin.(当然你可以任意选择脚位)
    3, PORTD----->外接8个LED,显示读出的数据,在这里,读出的刚好是一个闪动的流水灯状态。

    *******************************************************************/
    #i nclude "pic.h"

    #define uchar unsigned char
    #define nop() asm("nop"
    #define SCL TRISC3
    #define SDA TRISC4

    void start_i2c();
    void stop_i2c();
    void send_byte(uchar c);
    uchar receive_byte();
    void I_send_str(uchar sla,uchar suba,uchar *s,uchar no);
    void delay_250ms();
    void i2c_error ();

    uchar code[]={0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
    uchar no,ack,c,data;


    void main(void)
    {
    uchar i;
    TRISC=0Xff; //C口设为输入 RC3为SCL线,RC4为SDA线。
    PORTC=0X00;
    TRISD=0X00; //D口为输出,显示IC24LC02中读出的内容
    PORTD=0X00; //初始显示全亮

    I_send_str(0xa0,0x00,code,9); //页写入code数组到24LC02,器件地址为0Xa0,子地址为0X00,共9个数。

    delay_250ms();


    ///////////开始读出到D口进行显示,根据Random read时序图。
    while (1)
    {
    for (i=0x00;i<0x09;i++)
    {
    start_i2c();
    send_byte(0xa0); //发送器件地址,即DEVICE ADDRESS。
    if (ack==0) i2c_error(); //如果24LC02无应答。则进入I2C ERROR错误指示。
    send_byte(i); //发送字地址,即WORD ADDRESS。D口显示数组。
    if (ack==0) i2c_error();
    start_i2c(); //重新启动总线。
    send_byte(0xa1); //发送读命令和器件地址DEVICE ADDRESS。
    if (ack==0) i2c_error();
    data=receive_byte();
    stop_i2c();
    PORTD=data;
    delay_250ms();
    }
    }
    }


    /*******************************************************************
    起动总线函数
    函数原型: void start_i2c();
    Function: start on the I2C bus
    *******************************************************************/
    void start_i2c()
    {
    SDA=1; //发送启始条件的数据信号
    nop();
    SCL=1;
    nop();nop();nop();nop();nop(); //24LC02要求建立时间大于4,7S
    SDA=0; //发送起始信号
    nop();nop();nop();nop();nop();
    SCL=0; //钳住I2C总线,准备发送数据或接收数据
    nop();nop();
    }


    /*******************************************************************
    停止总线函数
    函数原型: void stop_i2c();
    Function: stop the I2C bus
    *******************************************************************/
    void stop_i2c()
    {

    SDA=0; //发送结束条件的数据信号
    nop();
    SCL=1;
    nop();nop();nop();nop();nop();
    SDA=1;
    nop();nop();nop();nop();
    }

    /*=================================================================
    字节数据传送函数
    函数原型: void send_byte(uchar c);
    Function: 将数据C发送出去,可以是地址,也可以是数据,发完后等待回应,并对此状态
    位进行操作(不应答或非应答都使ack=0 ),发送数据正常,ack=1;ack=0
    表示被控器无应答或损坏。
    ==================================================================*/
    void send_byte(uchar c)
    {
    uchar bit_count;
    for (bit_count=0;bit_count<8;bit_count++)
    {
    if ((c<<bit_count)&0x80) {SDA=1;}
    else {SDA=0;}
    nop();
    SCL=1;
    nop();nop();nop();nop();nop();
    SCL=0;
    }
    nop();nop();
    SDA=1;
    nop();nop();
    SCL=1;
    nop();nop();nop();
    if (RC4==1) ack=0;
    else ack=1; //用ASK=1为有应答信号
    SCL=0;
    nop();nop();
    }

    /*==================================================================
    字节数据接收函数
    函数原型:uchar receive_byte();
    FUNCTION: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
    发完后请用应答函数。
    ===================================================================*/
    uchar receive_byte()
    {
    uchar retc,bit_count;
    retc=0;
    SDA=1;
    for (bit_count=0;bit_count<8;bit_count++)
    {
    nop();
    SCL=0;
    nop();nop();nop();nop();nop();
    SCL=1;
    nop();nop();
    retc=retc<<1;
    if (RC4==1) retc=retc+1;
    nop();nop();
    }
    SCL=0;
    nop();nop();
    return (retc);
    }


    /*================================================================
    向有子地址器件发送多字节数据函数
    函数原型: bit I_send_str(uchar sla,uchar suba,uchar *s,uchar no);
    Function: 从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla。如果
    返回1表示操作成功,否则操作有误。
    =================================================================*/
    void I_send_str(uchar sla,uchar suba,uchar *s,uchar no)
    {
    uchar i;
    start_i2c();
    send_byte(sla);
    if (ack==0) i2c_error();
    send_byte(suba);
    if (ack==0) i2c_error();
    for (i=0;i<no;i++)
    {
    send_byte(*s);
    if (ack==0) i2c_error();
    s++;
    }
    stop_i2c();
    // return(1);
    }

    /*****************************************************************
    延时函数
    函数原型: void delay_250ms();
    FUNCTION: 延明250ms
    *****************************************************************/
    void delay_250ms()
    {
    unsigned int d=24999;
    while (--d);
    }

    /*****************************************************************
    总线错误函数
    函数原型: void i2c_error();
    Function: 通过RD7闪动8次表示总线操作失败一次报警。
    *****************************************************************/
    void i2c_error ()
    {
    uchar i;
    for (i=0;i<8;i++)
    {
    RD7=0;
    delay_250ms();
    RD7=1;
    delay_250ms();
    }

    }
    /**********END**************/

    看《匠人手记》,与匠人同行!北航出版,正在热卖!

    发表评论:
    载入中...

    广告5号位 [投放]


    学习板、开发板、编程器、下载器、仿真器(查看详情……)

    站内搜索


    站外搜索


    百度  google
    mp3  歌词 
    图片  FLASH 
    知道  文档
    新闻  词典 
    地图  mp3 
    软件  天网 
    雅虎  爱问 
    搜狗  讯雷 
    网讯  华军 
    天空 

    21IC器件搜索
    百宝箱分站
  • 《匠人的百宝箱》21IC站
  • 《匠人的百宝箱》21IC笔记团队
  • 《匠人的百宝箱》MCUBLOG站
  • 《匠人的百宝箱》MCUBLOG笔记团队
  • 《匠人的百宝箱》EDN站
  • 《匠人手记》EDN书友会
  • 《匠人的百宝箱》与非网站
  • 《匠人的百宝箱》新浪站
  • 《匠人的百宝箱》百度站
  • 《匠人的百宝箱》网易126站
  • 《匠人的百宝箱》网易163站
  • 《匠人的百宝箱》互动出版网站
  • 广告4号位 [投放]

     
     
     

    新鲜货色

    匠人手记

    近期动态

    载入中...

      《匠人手记》购书全攻略 
     书友近况:淘书手记答疑与讨论:什么是散转程序 
     《匠人手记》新书艳照
     EDN《匠人手记》签名售书优惠活动开始报名啦!
     欢迎加入《匠人手记》EDN书友会
     欢迎加入《匠人手记》书友会Q群
     《匠人手记》终稿目录
     《匠人手记》封面,请大家先睹为快
     上周六收到了北航寄来的《匠人手记》清样,让大家先睹为快

    匠人原创

    粉丝评论

    往日酷贴

    载入中...

    载入中...



     网络酷文:博客,改变的不仅仅是图书 
     网络酷文:C语言宏定义技巧C语言 条件编译详解

      21IC上海2008-04聚会报名进行中。。。 
     两分钟让你明白什么是ERP![转]
      神奇的Duff's Device 算法
      实用一线通讯电路及软件设计方法
      程序员的“七年之痒”
      史上最短但最精彩的武侠小说
      网络无厘头文学《缺钙水浒》(爆笑)

     你的博客还能持续多久(转贴)
     电动车无刷电机控制器软件设计要点(作者:谢渊斌)

    大千八卦

    友情连接

    新浪新闻:
    新浪财经:
    AK58新闻:
    新浪股票:
    新浪股票:
    证券之星:

     [更多酷站连接]

     

     

    [欢迎交换连接]

    [百宝箱之与非门分舵]

    [电脑圈圈的家当]

    [IC921的博客]

    [柔月阁]

    [八楼的呼吸]

    [hotpower 的水潭]

    [xwj的文君阁]

    [所长的BLOG]

    [阿摆手记]

    [电子伙伴]

    [unaided的笔记]

    [小飞的笔记]

    [单片机开发联盟]

    [网址之家]

    [好东西网址大全]

    [美萍中文精选]

    [数字电视之家]

    [SMARTCODE电子书斋]

    [软件开发之窗]

    [Armoric]

    [我爱研发网]

    [infernal的笔记]

    [雄鹰的空中加油站]

    [SunK]

    [逍遥电子]

    [ningpanda的博客]

    [C-Design]

    [一网见天下]

    [海边淘沙]

    [嵌入式365]

    [水牛的仓库]

    [股剩是怎样炼成的]

    [PIC论坛]

    [ICC AVR开发网]

    [中国高校自动化网]

     

     

     

    MCU博客-中国电子工程师博客网 

    大学生电子网 

     

     

     

     

     

    !!! 《匠人的百宝箱》 !!!