前言:年前给老师做个红外抄表系统,,现在对当中用到的一些模块总结一下.

1.只有在总线空闲时才允许启动数据传送.

2.在数据传送过程中,当时钟线为高电平时,数据线必须保持稳定状态,不允许有跳变.时钟线为高电平时,数据线的任何电平变化将被看做总线的起始或停止信号.

3. 任何将数据传送到总线的器件作为发送器任何从总线接收数据的器件为接收器, 主器件和从器件都可以作为发送器或接收器但由主器件控制传送数据.

4.有两根数据线:

SDA : IIC数据传送位

SCL : IIC 时钟控制位

下面对IIC的底层驱动加以说明,并给出汇编和C语言的代码,以AT24C64为例.在这之前先定义一些常量和公共代码:

汇编:

SDA   BIT  P3.            ;数据端
SCL   BIT  P3.            ;时钟端

DELAY : NOP        ;延时子程序,根据单片机的晶振不同,延时长短略有不同
        NOP        ;12MHZ晶振
        NOP
        NOP
        NOP
        NOP
        RET

C语言:

sbit SDA = P3.;
sbit SCL = P3.;

void delay(void)       //延时子程序
{
    unsigned char i;
    ;i<;i++);
}

起始信号:

时钟线保持高电平期间,数据线电平从高到低的跳变作为IIC总线的起始信号.

汇编:

       IIC_ST:                ;IIC起始代码
LCALL DELAY
           CLR SCL
LCALL DELAY
        LCALL DELAY
        SETB SDA
LCALL DELAY
        LCALL DELAY
        SETB SCL
LCALL DELAY
        LCALL DELAY
        CLR SDA
LCALL DELAY
LCALL DELAY
        CLR SCL
LCALL DELAY
        RET

C语言:

void iic_start(void)
{
    SCL=;
    delay();
    SDA=;
    delay();
    SCL=;
    delay();
    SDA=;
    delay();
    SCL=;
    delay();
}

停止信号:

时钟线保持高电平期间,数据线电平从低变高.

汇编:

             IIC_SP:
LCALL DELAY
               CLR SCL
LCALL DELAY
LCALL DELAY
                     CLR SDA
LCALL DELAY
LCALL DELAY
                     SETB SCL
LCALL DELAY
LCALL DELAY
                     SETB SDA
LCALL DELAY
                     RET

C语言:

void iic_stop(void)
{
    delay();
    SCL=;
    delay();
    SDA=;
    delay();
    SCL=
    delay();
    SDA=;
    delay();
}

器件寻址:

首先发送一个起始信号,启动发送过程,然后发送它所需要的寻址的从器件的地址.8从位器件地址的高4位固定为1010,接下来的三位为器件的地址位,最低一位作为读写控制位.

1: 表示从器件进行读;

0: 表示对器件进行写.

应答信号:

IIC总线数据传送时,每成功的传送一个字节数据后,接收器都必须产生一个应答信号.应答的器件在第九个时钟周期时将SDA拉低,表示收到一个8位数据.

写操作:(字节模式)

主器件发送起始信号和从器件地址信息(R/W位清0)给从器件,在从器件送回应答信号后,主器件发送两个8位地址字写入从器件的地址指针,主器件在收到从器件的应答信号后,再发送数据到到被寻址的从器件存储单元,从器件再次应答,并在主器件产生停止信号后开始内部数据的擦写.

汇编:

 ;##############写数据到at24c64-ATW2##############
;说明:写一字节数据到at24c64,失败PSW.5置1
;入口参数:A
;出口参数:无
;###############################################
IIC_WB: 

    CLR SCL
J4:
    RLC A
    LCALL DELAY
    LCALL DELAY
    MOV SDA,C
    LCALL DELAY
    LCALL DELAY
    SETB SCL
    LCALL DELAY
    LCALL DELAY
    CLR SCL
    DJNZ R2,J4
    SETB SDA
    LCALL DELAY
    LCALL DELAY
    SETB SCL     ;第九个时钟周期
    LCALL DELAY
    LCALL DELAY
    JB SDA,J1     ;正常情况下,第九个时钟周期收到的SDA应为低
    CLR SCL      ;释放总线
    LCALL DELAY
    LCALL DELAY
    CLR PSW.      ;接收成功
    LJMP edw
J1:
    CLR SCL  ;释放总线
     ;接收失败
edw:  RET

C语言:

void iic_write_byte(unsigned char w_byte)
{
    unsigned char i;
    SCL=;
    ;i<;i++)
    {
        delay();
        if((w_byte<<i)&0x80)
            SDA=;
        else
            SDA=;
        delay();
        SCL=;
        delay();
        SCL=;
    }
    SDA=;
    delay();
    SCL=;  //第九个时钟周期
    delay();
    )  //正常情况下,第九个时钟周期时,收到的SDA应该为低电平
    {           //写入出错
        SCL=;
        PSW.=;  //出错标志
    }
    else
    {             //写入成功
        SCL=;
        PSW.=;  //成功标志
    }
}

读操作:

读操作的初始化方式和写操作一样,仅把R/W位置1.

读操作的种类:

1. 立即/当前地址读(本例未用)

2. 选择/随机读: 允许对任意字节进行读,首先发送起始信号,从器件地址和它想读的字节数数据地址,执行一个伪写操作,在AT24C64应答之后,主器件重新发送起始信号和从器件地址,此时R/W位置1.AT24C64响应并发送应答信号,然后输出所要求的一个8位字节数据.主器件不发送应答信号但产生一个停止信号.

汇编1:

;/** 单字节读 **/
;读出的一个字节存放在A中
IIC_RB:
    CLR A
    CLR C
    LCALL DELAY
    LCALL DELAY
    CLR SCL
    LCALL DELAY
    LCALL DELAY

J5:
    SETB SCL
    LCALL DELAY
    LCALL DELAY
    MOV C,SDA
    RLC A
    LCALL DELAY
    LCALL DELAY
    CLR SCL
    LCALL DELAY
    LCALL DELAY
    DJNZ R2,J5
    CLR SDA
    LCALL DELAY
    LCALL DELAY
    SETB SCL   ;第九个时钟周期,应将SDA拉低作为应答信号
    LCALL DELAY
    LCALL DELAY
    CLR SCL   ;释放总线
    LCALL DELAY
    LCALL DELAY
    SETB SDA
RET

汇编2:

;################序列读最后一字节###############
;读最后一字节时需要发送停止信号
IIC_RL:
    CLR A
    CLR C
    LCALL DELAY
    LCALL DELAY
    CLR SCL
    LCALL DELAY
    LCALL DELAY

    J50: SETB SCL
    LCALL DELAY
    LCALL DELAY

    MOV C,SDA
    RLC A
    LCALL DELAY
    LCALL DELAY
    CLR SCL
    LCALL DELAY
    LCALL DELAY
    DJNZ R2,J50
    SETB SDA
    LCALL DELAY
    LCALL DELAY
    SETB SCL                ;停止信号
    LCALL DELAY
    LCALL DELAY
    RET

C语言1: 单字节读

unsigned char iic_read_byte(void)
{
    unsigned ;
    delay();
    SCL=;
    delay();
    ;i<;i++)
    {
        SCL=;
        delay();
        j<<=;
        )
            j+=;
        delay();
        SCL=;
        delay();
    }
    SDA=;
    delay();
    SCL=;
    delay();
    SCL=;
    delay();
    SDA=;

    return j;
}

C语言2: 序列读最后一字节

unsigned char iic_read_last_byte(void)
{
    unsigned ;
    delay();
    SCL=;
    delay();
    ;i<;i++)
    {
        SCL=;
        delay();
        j<<=;
        )
            j+=;
        delay();
        SCL=;
        delay();
    }
    SDA=;
    delay();
    SCL=;    //停止信号
    delay();
    return j;
}

举例: 以AT公司生产的IIC器件EEPROM: at24c64为例,对该器件进行读写

1.      原理图

AT24C64器件简介:

2.将位于R0(buf)所指向的地址单元中的COUNT(count)个数据写入AT24C64的ADDRH,ADDRL(addrh,dddrl)地址单元中.(括号内为c语言变量)

汇编:(会用到上面给出的IIC驱动子程序以及定义的一些变量和接口)

ADDRH   EQU 13H
ADDRL   EQU 14H           ;定义读写AT24C64的首地址

STOR1:
          ;写入的字节数
    MOV  ADDRH,#xx    ; 写入到AT24C64的地址字
    MOV  ADDRL,#xx
    LCALL WRDAT     ;将位于R0所指向的地址单元中的COUNT个数据写入
;AT24C64的ADDRH,ADDRL地址单元中

;###########所有参数写入AT24C64,共4字节#################
;说明:将表号和用户电量共四字节数据写入AT24C64中
;入口参数:
;    1.数据间接寻址地址-R0
;    2.写入到AT24C64的地址字-ADDRH,ADDRL
;    3.写入字节数-COUNT
;出口参数:无
;#######################################################

WRDAT:
    LCALL IIC_ST         ;START
    MOV A,#0A0H
    LCALL IIC_WB        ;写器件寻址00H(第一片AT24C64)  将A中的字符发送
    ,WRDAT
    MOV A,ADDRH
    LCALL IIC_WB
    ,WRDAT
    MOV A,ADDRL
    LCALL IIC_WB       ;存储单元地址
    ,WRDAT
    MOV R7,COUNT
WRDAT0:
    MOV A,@R0
    LCALL IIC_WB        ;写入数据
    ,WRDAT
    INC R0
    DJNZ R7,WRDAT0
    LCALL IIC_SP     ;停止
    LCALL DL20MS   ;延时,等待将数据擦写到at24c64中
    RET

C语言:

unsigned char count=0x04;
unsigned char addrh=0xxx;
unsigned char addrl=0xxx;
unsigned char t_buf[];

while(!write_byte(t_buf,addrh,addrl,count));

/*###########所有参数写入AT24C64,共4字节#################
//说明:将表号和用户电量共四字节数据写入AT24C64中
//入口参数:
;    1.数据间接寻址地址-buf
;    2.写入到AT24C64的地址字-addh,addrl
;    3.写入字节数-count
;出口参数:1表示写成功,0表示写失败
;#######################################################*/
bit write_byte(unsigned char * buf,             //
            unsigned char addrh,
            unsigned char addrl,
            unsigned char count)
{
    unsigned char i;
    iic_start();                    //start
    iic_write_byte(0x0a0);          //写器件寻址0x00(第一片at24c64)
    )
        ;
    iic_write_byte(addrh);
    )
        ;
    iic_write_byte(addrl);
    )
        ;
    ;i<count;i++)
    {
        iic_write_byte(*buf);
        )
            ;
        buf++;
    }
    iic_stop();
    ;
}

2.      从at24c64的ADDRH,ADDRL(addrh,addrl)地址单元中读出COUNT(count)个数据存放到单片机R0(buf)指定的地址单元中.(括号中为C语言变量)

汇编: (会用到上面给出的IIC驱动子程序以及定义的一些变量和接口)

ADDRH   EQU 13H
ADDRL   EQU 14H           ;定义读写AT24C64的首地址

STOR1:
              ;读出入的字节数
        MOV  ADDRH,#xx    ; 读入的AT24C64的地址字
        MOV  ADDRL,#xx
        LCALL LDDAT      ; 从at24c64中读数据

;/*############从at24c64中读数据#########################
; 入口参数:
LDDAT:
        LCALL IIC_ST         ;START
        MOV A,#0A0H                ;对器件进行写
        LCALL IIC_WB        ;虚写操作器件寻址00H(第一片AT24C64)
        ,LDDAT
        MOV A,ADDRH
        LCALL IIC_WB       ;
        ,LDDAT
        MOV A,ADDRL
        LCALL IIC_WB        ;虚写存储单元地址
        ,LDDAT
        ;以上为先初始化一个读数据地址
        LCALL IIC_ST         ;START
        MOV A,#0A1H
        LCALL IIC_WB        ;读操作器件寻址00H(第一片AT24C64)
        ,LDDAT
        MOV R7,COUNT
        CJNE R7,#,LD01
        LJMP LDDAT1
LD01:
        DEC R7
LDDAT0:
        LCALL IIC_RB        ;现行地址读(0000H)
        MOV @R0,A
        INC R0
        DJNZ R7,LDDAT0
LDDAT1:
        LCALL IIC_RL            ;读最后一字节,读完后给AT24C64发停止信号
        MOV @R0,A
        inc r0
        LCALL IIC_SP                    ;停止信号
        RET

C语言:

unsigned char count=0x04;
unsigned char addrh=0xxx;
unsigned char addrl=0xxx;
unsigned char r_buf[];
while(!read_byte(r_buf,addrh,addrl,count));
/*            */
bit read_byte(unsigned char *buf,            //存放读到的数据
                 unsigned char addrh,
                 unsigned char addrl,        //要读的数据地址
                 unsigned char count)        //需要读的个数
{
    unsigned char i;
    iic_start();
    iic_write_byte(0x0a0);                 //对器件进行寻址,虚写操作器件 寻址00H(第一片)
    )
        ;
    iic_write_byte(addrh);                  //虚写存储单元地址
    )
        ;
    iic_write_byte(addrl);                   //虚写存储单元地址
    )
        ;
    //以上为初始化一个读数据地址
    iic_start();                            //重发起始信号
    iic_write_byte(0x0a1);                    //对器件读命令
    )
           ;
    )
    {
        *buf=iic_read_last_byte();
        buf++;
    }
    else
    {
        ;i<count;i++)
        {
            *buf=iic_read_byte();
            buf++;
        }
    }
    iic_stop();
    ;
}

IIC总线协议的更多相关文章

  1. IIC总线协议---以存储芯片at24c64为例

    IIC总线协议 前言:年前给老师做个红外抄表系统,,现在对当中用到的一些模块总结一下. 1.只有在总线空闲时才允许启动数据传送. 2.在数据传送过程中,当时钟线为高电平时,数据线必须保持稳定状态,不允 ...

  2. IIC总线协议基础1

    文档类别 文档标识 IIC总线协议基础1 当前版本号 V0.2 作    者 Louis 完毕时间 2015-05-27 IIC总线协议基础1 IIC总线协议基础1. 1.            II ...

  3. 用I/O口模拟IIC总线协议遇到的一些问题

    最近做的一个项目,是基于IIC总线通信的传感器系统.由于另外一个传感器使用的是类IIC协议,而不是标准IIC,所以MCU不能与其通信,最后没有办法,只有通过I/O口模拟的方式实现IIC的总线通信.具体 ...

  4. IIC总线协议和时序

    IIC标准速率为100Kbit/s,快速模式400Kbit/s,支持多机通信,支持多主控模块,但是同一时刻只允许有一个主控.由数据线SDA和时钟SCL构成串行总线:每个电路模块都有唯一地址.I2C设备 ...

  5. 十天学会单片机Day5 IIC总线AT2402芯片(EEPROM)应用

    1.采用串行总线技术可以使系统的硬件设计大大简化.系统的体积减小.可靠性提高.同时,系统的更改和扩充极为容易. 常用的串行扩展总线有: IIC (Inter IC BUS)总线.单总线(1-WIRE ...

  6. 【接口时序】6、IIC总线的原理与Verilog实现

    一. 软件平台与硬件平台 软件平台: 1.操作系统:Windows-8.1 2.开发套件:ISE14.7 3.仿真工具:ModelSim-10.4-SE .ChipScope 硬件平台: 1. FPG ...

  7. 对 IIC 总线的理解、调用函数以及常见面试问题

    一.IIC 总线概述: IIC 即Inter-Integrated Circuit(集成电路总线) I2C总线是PHLIPS公司推出的一种串行总线, I2C总线只有两根双向信号线.一根是数据线SDA, ...

  8. 十天学会单片机Day6 学会看数据手册 (IIC总线PCF859芯片( A/D D/A)应用)

    1.实际电路 2.引脚图 3.地址 高四位为固定地址1001,A2A1A0可编程地址,通过观察实际电路,可知A2A1A0 为000.最低位为读写为,1为读,0为写. 4.控制字 控制寄存器的高半字节用 ...

  9. C51—模拟IIC总线实现EEPROM存取数据

    a - 什么是IIC总线 -什么是EEPROM -IIC总线的通信格式 模块化设计注解 整体代码 - 什么是IIC总线 IIC总线是同步通信的一种特殊形式,具有接线口少.控制简单.器件封装形式小.通信 ...

随机推荐

  1. MST最小生成树及Prim普鲁姆算法

    MST在前面学习了Kruskal算法,还有一种算法叫做Prim的.这两者的区别是Prim算法适合稠密图,比如说鸟巢这种几乎所有点都有相连的图.其时间复杂度为O(n^2),其时间复杂度与边的数目无关:而 ...

  2. [RxJS] map vs flatMap

    What's the difference between map and flatmap? First, let's show what map is. To show that, I need a ...

  3. android中listview的一些样式设置

    在Android中,ListView是最常用的一个控件,在做UI设计的时候,很多人希望能够改变一下它的背景,使他能够符合整体的UI设计,改变背景背很简单只需要准备一张图片然后指定属性 android: ...

  4. WCF - 绑定

    从整个基础架构来看 WCF可分为服务模型层和信道层 模型层提供了一个统一的可扩展的编程模型 而信道层提供了对请求信息的接收和处理 而作为WCF通信的三要素之一的绑定 是它实现了组成整个信道层的信道栈 ...

  5. 织梦dede编辑器ckeditor如何添加中文字体不乱码

    dedecms内容编辑器ckeditor没有中文字体,找了很多教程都是千篇一律,而且都是错的,终于找到了一篇,结合自己的实际操作,来教您如何添加中文字体,并且解决乱码问题.   工具/原料 dedec ...

  6. Nodejs服务器端脚本

    首先是安装,安装很简单,下载一个msi文件后一路下一步,没有难度, 测试的时候,如果你发现你的环境变量里面没有自动添加进去,也可以进行手动添加环境变量 之后在命令窗口输入: 得到nodejs的版本就说 ...

  7. angularJS function

    angular.bootstrap 启动Angular angular.element 相当于轻量的JQuery 使用方法: angular.element('#qq'); angular.eleme ...

  8. ORACLE添加作业

    --创建job declare job number; beginsys.dbms_job.submit(job,'prc_into_actiwager;',sysdate,'sysdate+30/( ...

  9. Android开发手记(32) 使用摄像头拍照

    在Android中,使用摄像头拍照一般有两种方法, 一种是调用系统自带的Camera,另一种是自己写一个摄像的界面. 我们要添加如下权限: <uses-permission android:na ...

  10. 前端过滤XSS攻击

    日常开发过程中,对于存在用户交互的一些门户网站等,过滤xss攻击是必不可少的. 此处主要记录下我在工作过程中的简单处理方法. 前端过滤XSS攻击, 我这里用的是开源工程 js-xss,官网地址:htt ...