一、概述

  为了非常方便地对 I2C 从器件进行快速的、正确的读写操作,我们为此而设计出虚拟 I2C 总线操作平台软件包。本软件包是主方式下的虚拟 I2C 总线软件包,只要用户给子程序提供几个主要的参数,即可轻松地完成任何 I2C 总线外围器件的应用程序设计。
  I2C 总线是 PHILIPS 公司推出的芯片间串行数据传输总线,2 根线(SDA、SCL)即可实现完善的全双工同步数据传送,能够十分方便地地构成多机系统和外围器件扩展系统。I2C 器件是把 I2C 的协议植入器件的 I/O 接口,使用时器件直接挂到 I2C 总线上,这一特点给用户在设计应用系统带来了极大的便利。I2C 器件无须片选信号,否选中是由主器件发出的 I2C 从地址决定的,而 I2C 器件的从地址是由 I2C 总线委员会实行统一发配。我们推出的 I2C 总线的操作平台软件包,只要你给出器件从地址[,子地址,注 PCF8574 无子地址 ] 即可进行字节读、字节写、多字节读、多字节写,能够非常方便地使用 I2C 器件,无须你介入底层的 I2C 操作协议。

  二、编程序软件包
  此软件包是用在单主 I2C 总线上,硬件接口是SDA、SCL,使用MCU 的 I/O 口来模拟 SDA/SCL 总线。设计有/无子地址的子程序是根据 I2C 器件的特点,目的在于将地址和数据彻底分开。软件包的接口界面为
IRDBYTE  无子地址  读单字节数据  现行地址读
IWRBYTE   无子地址  写单字节数据  现行地址写
IRDNBYTE   有子地址  读 N 字节数据
IWRNBYTE  有子地址  写 N 字节数据
  说明:现行地址读/写即专指无子地址的器件,不给定子地址的读/写操作。
软件包占用内部资源:R0 R1 R2 R3 ACC Cy。
使用前须定义变量:SLA 器件从地址,SUBA 器件子地址,NUMBYTE 读/写的字节数,位变量 ACK
使用前须定义常量:SDA、SCL 总线位,MTD 发送数据缓冲区首址, MRD 接收数据缓冲区首址。

;**************************************************************************************
;VI2C_ASM.ASM
;I2C 软件包的底层子程序,使用前要定义好 SCL 和 SDA。在标准 80C51 模式(12 Clock)下,对主频要求是;不高于 12MHz(1 个机器周期 1us);若 Fosc>12MHz,则要增加相应的 NOP 指令数.;在使用本软件包时,请在你的程序的未尾加入$INCLUDE (VI2C_ASM.ASM)即可
;*************************************************************************************
;启动 I2C 总线子程序
START:
    SETB    SDA       ;setb:一个指令周期,一个机器周期,1us
    NOP            ;nop:一个指令周期,一个机器周期,1us
    SETB    SCL            ;起始条件建立时间大于 4.7us
    NOP
    NOP
    NOP
    NOP
    NOP
    CLR     SDA       ;clr:一个指令周期,1us
    NOP                   ;起始条件锁定时大于 4us
    NOP
    NOP
    NOP
    NOP
    CLR   SCL           ;钳住总线,准备发数据
    NOP
    RET           ;ret:2个指令周期,2us

;结束总线子程序
STOP:
    CLR     SDA
    NOP
    SETB    SCL            ;发送结束条件的时钟信号
    NOP                    ;结束总线时间大于 4us
    NOP
    NOP
    NOP
    NOP
    SETB    SDA            ;结束总线
    NOP                    ;保证一个终止信号和起始信号的空闲时间大于 4.7us
    NOP
    NOP
    NOP
    RET                

;发送应答信号子程序
MACK:
    CLR     SDA            ;将 SDA 置 0
    NOP
    NOP
    SETB    SCL
    NOP                    ;保持数据时间 即 SCL 为高时间大于 4.7us
    NOP
    NOP
    NOP
    NOP
    CLR     SCL
    NOP
    NOP
    RET                    

;发送非应答信号
MNACK:
    SETB    SDA            ;将 SDA 置 1
    NOP
    NOP
    SETB    SCL
    NOP
    NOP                    ;保持数据时间,即SCL为高时间大于4.7us
    NOP
    NOP
    NOP
    CLR     SCL
    NOP
    NOP
    RET

; 检查应答位子程序
; 返回值,ACK=1 时表示有应答
CACK:
    SETB    SDA
    NOP
    NOP
    SETB    SCL
    CLR     ACK
    NOP
    NOP
    MOV     C,SDA
    JC      CEND      ;jc:2个指令周期,2us
    SETB    ACK            ;判断应答位
CEND:
    NOP
    CLR     SCL
    NOP
    RET

;发送字节子程序
;字节数据放入 ACC
;每发送一字节要调用一次CACK子程序,取应答位
WRBYTE:
    MOV     R0,#08H
WLP:
    RLC     A              ;取数据位   rlc:1个指令周期,1us
    JC      WR1
    SJMP    WR0            ;判断数据位 sjmp:2个指令周期,2us
WLP1:
    DJNZ    R0,WLP      ;djnz:2个指令周期,2us
    NOP
    RET
WR1:
    SETB    SDA            ;发送 1
    NOP
    SETB    SCL
    NOP
    NOP
    NOP
    NOP
    NOP
    CLR     SCL
    SJMP    WLP1
WR0:
    CLR     SDA            ;发送 0
    NOP
    SETB    SCL
    NOP
    NOP
    NOP
    NOP
    NOP
    CLR     SCL
    SJMP    WLP1

;读取字节子程序
;读出的值在 ACC
;每取一字节要发送一个应答/非应答信号
RDBYTE:
    MOV     R0,#08H
RLP:
    SETB    SDA
    NOP
    SETB    SCL            ;时钟线为高,接收数据位
    NOP
    NOP
    MOV     C,SDA          ;读取数据位
    MOV     A,R2
    CLR     SCL            ;将SCL拉低,时间大于4.7us
    RLC     A              ;进行数据位的处理
    MOV     R2,A
    NOP
    NOP
    NOP
    DJNZ    R0,RLP        ;未够8位,再来一次
    RET

; 无子地址器件写字节数据
; 入口参数: 数据为 ACC 器件从地址SLA
; 占用: A R0 CY
IWRBYTE:
    PUSH    ACC
IWBLOOP:
    LCALL   START         ;起动总线
    MOV     A,SLA
    LCALL   WRBYTE        ;发送器件从地址
    LCALL   CACK
    JNB     ACK,RETWRB    ;无应答则跳转
    POP     ACC           ;写数据
    LCALL   WRBYTE
    LCALL   CACK
    LCALL   STOP
    RET
RETWRB:
    POP     ACC
    LCALL   STOP
    RET

;无子地址器件读字节数据
;入口参数: 器件从地址 SLA
;出口参数: 数据为 ACC
;占用 AR0 R2CY
IRDBYTE:
    LCALL   START
    MOV     A,SLA        ;发送器件从地址
    INC     A
    LCALL   WRBYTE
    LCALL   CACK
    JNB     ACK,RETRDB
    LCALL   RDBYTE        ;进行读字节操作
    LCALL   MNACK        ;发送非应信号
RETRDB:
    LCALL   STOP        ;结束总线
    RET

; 向器件指定子地址写 N 个数据
; 入口参数: 器件从地址 SLA 器件子地址 SUBA发送数据缓冲区 MTD 发送字节数 NUMBYTE
; 占用AR0R1R3CY
IWRNBYTE:
    MOV     A,NUMBYTE
    MOV     R3,A
    LCALL   START        ;起动总线
    MOV     A,SLA
    LCALL   WRBYTE        ;发送器件从地址
    LCALL   CACK
    JNB     ACK,RETWRN    ;无应答则退出
    MOV     A,SUBA        ;指定子地址
    LCALL   WRBYTE
    LCALL   CACK
    MOV     R1,#MTD
WRDA:
    MOV     A,@R1
    LCALL   WRBYTE        ;开始写入数据
    LCALL   CACK
    JNB     ACK,IWRNBYTE
    INC     R1
    DJNZ    R3,WRDA        ;判断写完没有
RETWRN:
    LCALL   STOP
    RET

;向器件指定子地址读取 N 个数据
;入口参数: 器件从地址 SLA 器件子地址 SUBA 接收字节数 NUMBYTE
;出口参数: 接收数据缓冲区 MTD
;占用 AR0R1R2R3CY
IRDNBYTE:
    MOV      R3,NUMBYTE
    LCALL    START
    MOV      A,SLA
    LCALL    WRBYTE        ;发送器件从地址
    LCALL    CACK
    JNB      ACK,RETRDN
    MOV      A,SUBA        ;指定子地址
    LCALL    WRBYTE
    LCALL    CACK
    LCALL    START         ;重新起动总线
    MOV      A,SLA
    INC      A             ;准备进行读操作
    LCALL    WRBYTE
    LCALL    CACK
    JNB      ACK,IRDNBYTE
    MOV      R1,#MRD
RDN1:
    LCALL    RDBYTE        ;读操作开始
    MOV      @R1,A
    DJNZ     R3,SACK
    LCALL    MNACK         ;最后一字节发非应答位
RETRDN:
    LCALL    STOP          ;并结束总线
    RET
SACK:
    LCALL    MACK
    INC      R1
    SJMP     RDN1

  三、应用举例

;为软件包定义变量
ACK            BIT     10H        ;应答标志位
SLA            DATA    50H        ;器件从地址
SUBA          DATA    51H        ;器件子地址
NUMBYTE        DATA    52H        ;读/写的字节数

;使用前定义常量
SDA            EQU     P1.       ;I2C总线定义
SCL            EQU     P1.
MTD            EQU     30H        ;发送数据缓冲区首址(缓冲区 30H-3FH)
MRD            EQU     40H        ;接收数据缓冲区首址(缓冲区 40H-4FH)

;定义器件地址
CSI24WCXX      EQU     0A0H

    ORG     0000H
    AJMP    MAIN

    ORG     0080H
MAIN:
    MOV     R4,#0F0H         ;延时,等待其它芯片复位好
    DJNZ    R4,$        

;对24WCXX 指定单元进行写操作,指定的子地址放入SUBA,数据依次放入MTD缓冲区
WR24WCXX:
    MOV     SLA,#CSI24WCXX
    MOV     SUBA,#30H        ;指定存储地址
    MOV     NUMBYTE,#01H     ;写入一字节数据
    MOV     MTD,#58H         ;写入的数据放入 MTD 缓冲区
    LCALL   IWRNBYTE
    SJMP    $                ;操作结束
    ;
    $INCLUDE (VI2C_ASM.ASM)  ;包含 VIIC 软件包
    ;
END

  

模拟IIC总线汇编程序软件包的更多相关文章

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

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

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

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

  3. 模拟IIC总线多设备挂载(12864OLED屏幕+GY30光照传感器)

    最终效果展示 OLED屏幕和GY30光照传感器(BH1750FVI)都连接在一个IIC(I2C)总线上,所以只需要接4根线即可.获取到的光照强度可以在OLED上实时显示并通过串口打印.IIC是IO模拟 ...

  4. RT-thread 设备驱动组件之IIC总线设备

    本文主要介绍RT-thread中IIC总线设备驱动,涉及到的主要文件有:驱动框架文件(i2c_core.c,i2c_dev.c,i2c-bit-ops.c,i2c_dev.h,i2c.h):底层硬件驱 ...

  5. IIC总线

    一. 概述 1. IIC总线是PHILIPS公司推出的一种串口总线,是具备多主机系统所需的包括总线裁决和高低速器件同步功能的高性能串口总线. 2. IIC总线只有两根双向信号线.一根是数据线SDA,一 ...

  6. stm32软件模拟IIC读取PX4FLOW光流传感器数据

    这段时间在做全国光电设计大赛,用到了px4的px4flow光流传感器,用软件模拟iic读取数据不定期会导致px4flow死机,查了资料和光流的源码,发现这个光流用了stm32的硬件iic,所以对软件模 ...

  7. 模拟IIC协议时序

    IIC是飞利浦公司开发的两线式串行总线,主要应用在单片机和外围电子器件之间的数据通讯. IIC总线优点是节约总线数,稳定,快速,是目前芯片制造上非常流行的一种总线,大多数单片机已经片内集成了IIC总线 ...

  8. lpc1788IO口模拟IIC

    #ifndef __MYIIC_H_ #define __MYIIC_H_ #include "common.h" #include "delay.h" #in ...

  9. STM32F10X -- 模拟IIC程序

    听说STM32的IIC硬件做的很鸡肋,所以在这里通过模拟的方式实现IIC协议.此程序能成功对AT24C02操作. 程序中的带参数宏 IIC_DELAY(time)的功能是延时time us,在实际中具 ...

随机推荐

  1. windows driver inf文件

    原来修改了inf文件会导致签名过的驱动包哈希值不正确了啊.现在才知道. = = http://www.chiphell.com/thread-827956-1-1.html

  2. logstash 发送zabbix 给消息加上type

    input { file { type => "zj_api" path => ["/data01/applog_backup/zjzc_log/zj-api ...

  3. bzoj1190

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1190 神题...... F[i][j]表示容量为j*2^i+W第i-1位到第0位的最大价值, ...

  4. jQuery手机触屏左右滑动切换焦点图特效代码

    原文地址:http://www.17sucai.com/pins/4857.html 演示地址:http://www.17sucai.com/pins/demoshow/4857 干净演示地址:htt ...

  5. c++之命名空间namespace

    1命名空间解决全局变量的冲突 main.h文件 #pragma once // data命名空间的名称 namespace data { ;//外部全局变量冲突 } main.cpp #include ...

  6. PHP的错误处理方式

    错误类型 PHP 主要有两种错误:触发错误和异常.其中触发错误大概可以分为:编译错误.引擎错误和运行时错误,其中前两个是无法捕获的:异常都是可以捕获的,当没有尝试捕获时则会中断代码. 触发错误可以通过 ...

  7. Android仿IOS回弹效果 ScrollView回弹 总结

    Android仿IOS回弹效果  ScrollView回弹 总结 应项目中的需求  须要仿IOS 下拉回弹的效果 , 我在网上搜了非常多 大多数都是拿scrollview 改吧改吧 试了一些  发现总 ...

  8. php缓存方案

    一.说说Memcached优化方案 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态.数据 ...

  9. 查看linux版本和内核信息

    一.查看Linux内核版本命令(两种方法): 1.cat /proc/version [root@localhost ~]# cat /proc/versionLinux version 2.6.32 ...

  10. 使用区域组织 ASP.NET MVC 应用程序

    MVC 模式可将应用程序的模型(数据)逻辑与其呈现逻辑和业务逻辑分离. 在 ASP.NET MVC 中,这种逻辑分离还在项目结构中以物理方式实现,在该项目结构中,控制器和视图保存在使用命名约定定义关系 ...