普通IO口模拟实现I2C通信及应用解析

发布者:GHR2596最新更新时间:2018-05-20 来源: eefocus关键字:普通IO口  模拟实现  I2C通信 手机看文章 扫描二维码
随时随地手机看文章

根据I2C通信规范(具体可以参考“浅谈I2C总线”),通过普通IO端口模拟可以实现单片机(主设备)与从设备的I2C通信,其中SCL通过IO口延时高低电平变化实现,SDA根据SCL状态变化产生开始信号,结束信号,以及实现发送接收数据等,以下是相关代码

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  

* @Purpose:  I2C Communication driver(By IO)  

* @Author:  Purple  

* @Version:  1.0  

* @Date:  Create By Purple 2014.08.09  

*   

*   

* Copyright (C) BlueWhale Tech.     

* All rights reserved.    

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */  

  

  

#ifndef IICDRV_H  

#define IICDRV_H  

  

  

/* Include Files */  

  

  

/* Macros */  

#define I2C_SDA         PTT_PTT0   //举例以Freescale PT0端口为SDA线,PT1端口为SCL线  

#define I2C_SDA_IO      DDRT_DDRT0  

#define I2C_SCL         PTT_PTT1  

#define I2C_SCL_IO      DDRT_DDRT1  

  

#define IO_OUT_MODE     1   //Freescale:1为输出模式,0为输入模式;NEC:0为输出模式,1为输入模式  

#define IO_IN_MODE      0  

  

  

/* Function Prototypes */  

void I2CStart(void);  

void I2CStop(void);  

void I2CFree(void);  

void I2CSendACK(void);  

void I2CSendNoACK(void);  

bool I2CCheckACK(void);  

void I2CNoAck(void);  

void I2CSendByte(unsigned char sendData);  

unsigned char I2CReceiveByte(void);  

  

  

#endif  

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  

* @Purpose:  I2C Communication driver(By IO)  

* @Author:  Purple  

* @Version:  1.0  

* @Date:  Create By Purple 2014.08.09  

*   

*   

* Copyright (C) BlueWhale Tech.     

* All rights reserved.    

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */  

  

  

/* Include Files */  

#include "IICDrv.h"  

  

  

/* Function Prototypes */  

static void I2CDelay(void);  

  

  

/* Function Definitions */  

/*  

 * FunctionName: I2CDelay  

 * Purpose: I2C时序模拟SCL时间间隔(周期),需要根据Slave性能及单片机工作频率调整  

 * Parameters: 无  

*/  

static void I2CDelay(void)  

{  

    _asm("nop");  

    _asm("nop");  

    _asm("nop");  

    _asm("nop");  

    _asm("nop");  

}  

  

  

/*  

 * FunctionName: I2CStart  

 * Purpose: 模拟I2C开始信号  

 * Parameters: 无  

*/  

void I2CStart(void)  

{  

    I2C_SDA_IO=IO_OUT_MODE;     //设置SDA端口为输出端口  

    I2C_SCL_IO=IO_OUT_MODE;     //设置SCL端口为输出端口  

      

    I2C_SCL=1;  

    I2CDelay();  

    I2C_SDA=1;  

    I2CDelay();  

    I2C_SDA=0;  

    I2CDelay();  

    I2C_SCL=0;  

    I2CDelay();  

}  

  

/*  

 * FunctionName: I2CStop  

 * Purpose: 模拟I2C结束信号  

 * Parameters: 无  

*/  

void I2CStop(void)  

{  

    I2C_SDA_IO=IO_OUT_MODE;     //设置SDA端口为输出端口  

    I2C_SCL_IO=IO_OUT_MODE;     //设置SCL端口为输出端口  

      

    I2C_SCL = 0;  

    I2CDelay();  

    I2C_SDA = 0;  

    I2CDelay();  

    I2C_SDA = 1;  

    I2CDelay();  

    I2C_SCL = 1;  

    I2CDelay();  

}  

  

/*  

 * FunctionName: I2CFree  

 * Purpose: 模拟I2C空闲状态信号  

 * Parameters: 无  

*/  

void I2CFree(void)  

{  

    I2C_SDA_IO=IO_OUT_MODE;     //设置SDA端口为输出端口  

    I2C_SCL_IO=IO_OUT_MODE;     //设置SCL端口为输出端口  

      

    I2C_SDA = 1;  

    I2CDelay();  

    I2C_SCL = 1;  

    I2CDelay();  

}  

  

/*  

 * FunctionName: I2CSendACK  

 * Purpose: 模拟I2C发送ACK响应  

 * Parameters: 无  

*/  

void I2CSendACK(void)  

{  

    I2C_SDA_IO=IO_OUT_MODE;     //设置SDA端口为输出端口  

    I2C_SCL_IO=IO_OUT_MODE;     //设置SCL端口为输出端口  

      

    I2C_SCL=0;  

    I2CDelay();  

    I2C_SDA=0;  

    I2CDelay();  

    I2C_SCL=1;  

    I2CDelay();  

    I2C_SCL=0;  

    I2CDelay();  

}  

  

/*  

 * FunctionName: I2CSendNoACK  

 * Purpose: 模拟I2C无ACK响应  

 * Parameters: 无  

*/  

void I2CSendNoACK(void)  

{  

    I2C_SDA_IO=IO_OUT_MODE;   //设置SDA端口为输出端口  

    I2C_SCL_IO=IO_OUT_MODE;   //设置SCL端口为输出端口  

  

    I2C_SCL=0;  

    I2CDelay();  

    I2C_SDA=1;  

    I2CDelay();  

    I2C_SCL=1;  

    I2CDelay();  

    I2C_SCL=0;  

    I2CDelay();  

}  

  

/*  

 * FunctionName: I2CCheckACK  

 * Purpose: 检查I2C是否有ACK响应  

 * Parameters: 无  

*/  

bool I2CCheckACK(void)  

{  

    bool tempACK;  

      

    I2C_SDA_IO=IO_OUT_MODE;   //设置SDA端口为输出端口  

    I2C_SCL_IO=IO_OUT_MODE;   //设置SCL端口为输出端口  

  

    I2C_SDA=1;  

    I2CDelay();  

    I2C_SCL = 1;  

    I2C_SDA_IO=IO_IN_MODE;    //设置SDA端口为输入端口,检查Slave是否有响应  

    I2CDelay();  

    if(I2C_SDA)  

        tempACK=FALSE;  

    else  

        tempACK=TRUE;  

  

    I2C_SCL=0;  

    I2CDelay();  

  

    return tempACK ;  

}  

  

/*  

 * FunctionName: I2CSendByte  

 * Purpose: 模拟I2C发送一个字节数据  

 * Parameters: sendData-发送的一个字节数据  

*/  

void I2CSendByte(unsigned char sendData)  

{  

    unsigned char serialNum = 0;  

  

    I2C_SDA_IO=IO_OUT_MODE;   //设置SDA端口为输出端口  

    I2C_SCL_IO=IO_OUT_MODE;   //设置SCL端口为输出端口  

  

    for(serialNum=8;serialNum>=1;serialNum--)   //以MSB方式按位发送一个字节数据  

    {  

        I2C_SDA = (sendData>>(serialNum-1))&0x01;  

        I2CDelay();  

        I2C_SCL = 1;  

        I2CDelay();  

        I2C_SCL = 0;  

        I2CDelay();  

    }  

}  

  

/*  

 * FunctionName: I2CReceiveByte  

 * Purpose: 模拟I2C接收一个字节数据  

 * Parameters: 无  

*/  

unsigned char I2CReceiveByte(void)  

{     

    unsigned char serialNum = 0;  

    unsigned char dataValue=0;  

  

    I2C_SDA_IO=IO_IN_MODE;    //设置SDA端口为输入端口  

    I2C_SCL_IO=IO_OUT_MODE;   //设置SCL端口为输出端口  

  

    for(serialNum=0;serialNum<=7;serialNum++)//以MSB方式按位接收一个字节数据  

    {  

        I2C_SCL=1;  

        I2CDelay();  

        if(I2C_SDA) dataValue|=(0b10000000>>serialNum);  

        I2C_SCL=0;  

        I2CDelay();  

    }  

  

    return dataValue;  

}  


需要注意模拟SCL采用的延时需要根据从设备的特性来调整,延时时间不能小于从设备的最小SCL间隔时间

既然已经通过IO端口实现了I2C通信,那么,我们就可以用以上代码实现单片机与相应从设备I2C的通信了,以EEPROM 24C04为例,以下是读取和写入EEPROM数据相关函数的代码


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  

* @Purpose:  Communication with EEPROM 24C04  

* @Author:  Purple  

* @Version:  1.0  

* @Date:  Create By Purple 2014.08.09  

*   

*   

* Copyright (C) BlueWhale Tech.     

* All rights reserved.    

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */  

  

  

/* Include Files */  

#include "EEApp.h"  

  

  

  

/* Function Definitions */  

/*  

 * FunctionName: Slave24C04Write  

 * Purpose: 向EEPROM24C04中写入一个字节数据  

 * Parameters: tarAddress-写入数据的起始地址  

 *             wrNumber-待写入数据的长度(字节单位)  

 *             wrPointer-待写入数据的首字节地址  

*/  

void Slave24C04Write(unsigned char tarAddress,unsigned char wrNumber,unsigned char* wrPointer)  

{  

    bool rxdACK;  

  

    I2CStart();  

  

    I2CSendByte(SLAVE_ADDRESS);   //发送24C04的器件地址,地址LSB最后一位为0代表写入,1代表读取  

    rxdACK=I2CCheckACK();  

    I2CSendByte(tarAddress);   //发送写入数据的起始地址  

    rxdACK=I2CCheckACK();  

  

    for(;wrNumber!=0;wrNumber--,wrPointer++)  

    {  

        I2CSendByte(*wrPointer);   //按字节写入数据  

        rxdACK=I2CCheckACK();  

    }  

  

    I2CStop();  

}  

  

/*  

 * FunctionName: Slave24C04Read  

 * Purpose: 从EEPROM24C04中读取一个字节数据  

 * Parameters: tarAddress-读取数据的起始地址  

 *             wrNumber-读取数据的长度(字节单位)  

 *             wrPointer-读取数据的首字节存放地址  

*/  

void Slave24C04Read(unsigned char tarAddress,unsigned char rdNumber,unsigned char* rdPointer)  

{  

    bool rxdACK;  

      

    I2CStart();  

    I2CSendByte(SLAVE_ADDRESS);   //发送24C04的器件地址  

    rxdACK=I2CCheckACK();  

    I2CSendByte(tarAddress);   //发送读取数据的起始地址  

    rxdACK=I2CCheckACK();  

  

    I2CStart();  

    I2CSendByte(SLAVE_ADDRESS+1);  //发送24C04的器件地址,地址LSB最后一位为1代表读取  

    rxdACK=I2CCheckACK();  

  

    for(;rdNumber!=0;rdNumber--,rdPointer++)  

    {  

        *rdPointer=I2CReceiveByte();   //按字节读取数据  

  

        if(rdNumber!=1)  

            I2CSendACK();  

        else  

            I2CSendNoACK();  

    }  

  

    I2CStop();  

}  

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  

* @Purpose:  Communication with EEPROM 24C04  

* @Author:  Purple  

* @Version:  1.0  

* @Date:  Create By Purple 2014.08.09  

*   

*   

* Copyright (C) BlueWhale Tech.     

* All rights reserved.    

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */  

  

  

#ifndef EEAPP_H  

#define EEAPP_H  

  

  

/* Include Files */  

#include "IICDrv.h"  

  

  

/* Macros */  

#define SLAVE_ADDRESS   (0xA0)  

  

  

/* Function Prototypes */  

void Slave24C04Write(unsigned char tarAddress,unsigned char wrNumber,unsigned char* wrPointer);  

void Slave24C04Read(unsigned char tarAddress,unsigned char rdNumber,unsigned char* rdPointer);  

  

  

  

#endif  

需要注意不同的从设备要根据应用电路调整相应的从设备地址。

采用IO口来模拟I2C通信,一般仅用于单片机没有I2C功能的情况下,如果单片机本身具有I2C功能,还是应该通过配置单片机相应的寄存器,通过中断来实现I2C通信,因为模拟SCL采用的延时就是一个空等待,对于整个操作系统来说,这是一个资源浪费,同时还有可能会影响到其他任务的运行。



关键字:普通IO口  模拟实现  I2C通信 引用地址:普通IO口模拟实现I2C通信及应用解析

上一篇:GPIO模拟I2C程序实现
下一篇:STM8S 模拟I2C程序

推荐阅读最新更新时间:2024-03-16 16:03

I2C总线通信接口的CPLD实现
    摘要: 介绍采用ALTERA公司的可编程器件,实现I2C总线的通信接口的基本原理;给出部分VHDL语言描述。该通信接口号专用的接口芯片相比,具有使用灵活,系统配置方便的特点。     关键词: I2C总线 CPLD VHDL I2C总线是PHILIPS公司开发的一种简单、双向二线制同步串行总线。它只需要两根线(串行时钟线和串行数据线)即可在连接于总线上的器件之间传送信息。该总线是具备多主机系统所需要的包括裁决和高低速设备同步等功能的高性能串行总线,应用极为广泛。 目前,虽然市场上有专用I2C总线接口芯片,但是地址可选范围小,性能指标固定,功能单一,而且使用不方便。针对I2C总线的电气特性及其通信协
[工业控制]
DC/DC 控制器兼有数字电源系统管理功能和模拟控制环路,以实现 ±0.5% 的 VOUT 准确度
LTC3883 / LTC3883-1 是一款通用、单通道、多相 (PolyPhase®)、降压型 控制器 ,具有 数字电源 系统管理、高性能模拟控制环路、内置驱动器、远程输出电压检测和电感器温度检测功能。为了最大限度地减小解决方案尺寸和成本,LTC3883 / LTC3883-1 采用了 凌力尔特公司 正在申请专利的自动校准程序以测量电感器  DC  电阻,在跨电感器两端逐周期测量电流时 (无损耗 DCR 检测) 得到准确的输出电流测量值。LTC3883/-1 基于流行的双通道 LTC3880/-1。 数字电源 管理 今天数据中心系统的挑战是,尽可能提高系统所有层面的效率,包括负载点、电路板、机架甚至安装层面,以变得更加环
[电源管理]
DC/DC 控制器兼有数字电源系统管理功能和<font color='red'>模拟</font>控制环路,以<font color='red'>实现</font> ±0.5% 的 VOUT 准确度
结合数字电源和模拟控制环路实现高精度电源管理
尽管电源管理对新式电子系统的可靠运行至关重要,但是在今天以数字方式管理的系统中,稳压器也许是最后一个仍然存在的“盲点”。就稳压器而言,很少有办法直接配置或监视关键电源系统运行参数。因此,希望全面实现数字控制的电源设计师必须使用混杂在一起的排序器、微控制器和电压监察器,以设定基本的稳压器启动和安全功能。目前已有数字可编程 DC/DC转换器可用,特别是那些为VRM内核电源而设计并具备VID输出电压控制功能的转换器,但是这类有特定应用目标的转换器不能直接沟通重要的工作参数,例如实时电流。 LTC3880/ LTC3880-1结合了双输出同步降压型DC/DC控制器和拥有通过基于I2C的PMBus总线使用全面的电源管理功能,这解决了复杂
[电源管理]
结合数字电源和<font color='red'>模拟</font>控制环路<font color='red'>实现</font>高精度电源管理
基于SX52的嵌入式模拟系统的研究与实现
1 引言 信息家电(3C或说是IA)对人们来说已经不再是一个陌生的名字了,它是利用电脑、电信和电子技术与传统家电相结合的创新产品, 是为数字化与网络技术更广泛地深人家庭生活而设计的新型家用电器。要将它们与外部网络(如Internet)连接进行信息交互,利用家庭网关进行集中式管理无疑是一个理想的解决方案。家庭网关就是这样一种简单的、智能的、标准化的、灵活的整个家庭网络接口单元,它可以从不同的外部网络接收通讯信号,通过家庭网络传递信号给某个消费设备。但是,目前家庭网关在体系结构、功能分配等方面的标准还未确定,对其的研究正在如火如荼进行中。 本文采用SX52嵌入式网络单片机集成式开发系统主模块模拟家庭网关,并利用其外围扩展模块模拟信
[单片机]
基于SX52的嵌入式<font color='red'>模拟</font>系统的研究与<font color='red'>实现</font>
I2C总线通信接口的CPLD实现
    摘要: 介绍采用ALTERA公司的可编程器件,实现I2C总线的通信接口的基本原理;给出部分VHDL语言描述。该通信接口号专用的接口芯片相比,具有使用灵活,系统配置方便的特点。     关键词: I2C总线 CPLD VHDL I2C总线是PHILIPS公司开发的一种简单、双向二线制同步串行总线。它只需要两根线(串行时钟线和串行数据线)即可在连接于总线上的器件之间传送信息。该总线是具备多主机系统所需要的包括裁决和高低速设备同步等功能的高性能串行总线,应用极为广泛。 目前,虽然市场上有专用I2C总线接口芯片,但是地址可选范围小,性能指标固定,功能单一,而且使用不方便。针对I2C总线的电气特性及其通信协
[半导体设计/制造]
STM32F10x_硬件I2C主从通信(轮询发送,中断接收)
Ⅰ、写在前面 关注我分享文章的朋友应该知道我在前面讲述过(软件、硬件)I2C主机控制从机EEPROM的例子。在I2C通信主机控制程序是比较常见的一种,可以说在实际项目中,很多应用都会使用到I2C通信。但在实际项目中作为I2C从机的应用相对要少的多,本文主要讲述关于【STM32F10x_硬件I2C主从通信】中STM32作为从机的例子。 在学习本问内容之前,如果对I2C协议还不太了解的朋友请先去了解一下I2C协议,或看我之前关于I2C通信的文章(我微信公众号和博客都有)。 关于STM32硬件I2C作为从机的文章网上很少(我在写本文之前也在百度、谷歌等网站上搜索了解过),我猜测大概的原因主要是两点:1.使用该功能的人比较少; 2
[单片机]
STM32F10x_硬件<font color='red'>I2C</font>主从<font color='red'>通信</font>(轮询发送,中断接收)
51单片机入门经验分享9-定时器模拟实现PWM呼吸灯效果
众所周知,PWM的应用是及其广泛的,现在很多高速的单片机内部都集成了硬件PWM,使用起来也很简单,配置好频率和装入计数值就可以工作了,但是在一些低成本的场合,我们选择的单片机没有硬件PWM功能模块,但是我们还存在这个需求怎么办呢?这个时候,我们需要用PWM来模拟实现他,但实现PWM必须要了解PWM的原理,这里我们先了解下。 PWM全称是脉冲宽度调制解调,比如1个小灯,按照500MS亮一次,500MS灭一次,周期是1S,频率是1HZ,在这里,1个周期说明白了就是2个方波,有高电平和低电平组成,在周期固定的情况下,我们通过不断的调整高电平所占的整个周期比例,即所谓的占空比,就可以实现小灯”不是那么亮“的效果,如果连续起来,就可以实
[单片机]
51单片机入门经验分享9-定时器<font color='red'>模拟</font><font color='red'>实现</font>PWM呼吸灯效果
LPC11C14通信接口之I2C
1、什么是IIC? IIC的英文全称Inter-IntegratedCircuit(集成电路总线),是一种多向控制总线,由飞利浦半导体公司在八十年代初设计,主要是用来连接整体电路(ICS)。在IIC中,多个芯片可以连接到同一总线结构下,同时每个芯片都可以作为实施数据传输的控制源,这种方式简化了信号传输总线。 因此,IIC实质是用来在芯片和外围器件之间连接的通信接口。 2、IIC接线 IIC通信一共要有2根线:SCL(时钟线)和SDA(数据线) SCL时钟线:控制IIC通信双方进行数据传递控制 SDA数据线:IIC通信双方数据传输 一个主设备可以连接多个从设备,那么究竟什么是主设备,
[单片机]
LPC11C14<font color='red'>通信</font>接口之<font color='red'>I2C</font>
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved