在做总线通信过程中,我们很少会用到这样方法,一般在我们选择MCU的时候都会带有你所需要的通信接口。但是,对于一些简单的通信应该用的场合,一般在一些传感器的数据通信过程中,传感器厂商会将通信协议做一些改变,这些通信协议也没有一个标准的协议规定。以至于传感器的兼容性很差,甚至有时候找不到能够与其通信的MCU,这个时候有一种方法就是用I/O口来模拟通信总线(由于I/O速度的限制一般只适用于低速的通信总线)的时序。之前,用I2C通信做一个温湿度测量的工程,本篇文章就以一个例子来看看如何用I/O口对总线时序进行模拟。

我们平时计算机常用的RS232/485工作在异步工作状态时是有严格的数据时钟限制,也就是我们所说的波特率,通信的两个设备有相同的波特率才能正确的通信。对于同步通信一般没有严格的时间限制,总线通过高低电平来分辨数据是“0”还是“1”,有两个关键的时刻:上升沿,下降沿。它是用过上升沿和下降沿的时刻来读写数据的,也就是说这样的话通信频率不是固定的,因为通信的设备“数”的是上升沿和下降沿的数目,然后读写数据线上的数据。笔者做过实验,将I2C通信的频率降到了10Hz左右,这样用示波器能够很好的捕捉到每一个时钟,通信的结果也是正确的。

好了,直接来看案例吧。

通常我们的I2C的通信时序应该如下图所示,在时钟线拉高的情况下,将数据线拉低就会产生一个启动信号。但是传感器SHT的启动信号却是一个数据线拉低后,时钟线产生一个脉冲,而后再将数据线拉高,这样做的好处是在一定程度上确保了总线正确的启动,但是几乎与之匹配的MCU。这个时候就需要通过I/O模拟的方式来与SHT11完成通信。

 #define IIC_SCL RC0     //I2C时钟线
#define IIC_SDA RC1 //I2C数据线
#define IIC_SCL_DIR TRISC0 //I2C时钟线传输方向
#define IIC_SDA_DIR TRISC1 //I2C数据线传输方向
#define PORT_INPUT 1
#define PORT_OUTPUT 0 #define IIC_SCL_HIGH() IIC_SCL_DIR = PORT_INPUT //时钟线拉高
#define IIC_SCL_LOW() IIC_SCL_DIR = PORT_OUTPUT;IIC_SCL=0//时钟线拉低
#define IIC_SDA_HIGH() IIC_SDA_DIR = PORT_INPUT //数据线拉高
#define IIC_SDA_LOW() IIC_SDA_DIR = PORT_OUTPUT;IIC_SDA=0//数据线拉低 /***************
*SHT11启动时序
***************/
void SHT_START(void)
{
IIC_SCL_HIGH();
IIC_SDA_HIGH();
delay_us();
IIC_SDA_LOW();
delay_us();
IIC_SCL_LOW();
delay_us();
IIC_SCL_HIGH();
delay_us();
IIC_SDA_HIGH();
delay_us();
IIC_SCL_LOW();
}
/***************
*SHT11发送数据时序
***************/
void SHT_SEND(uchar data)
{uchar i,data1;
for(i=;i<;i++)
{
data1=data<<i;
if(!(data1&0x80))
IIC_SDA_LOW();
if(data1&0x80)
IIC_SDA_HIGH();
IIC_SCL_LOW(); //写完1位数据将时钟线拉低,等待发送
delay_us();
IIC_SCL_HIGH(); //时钟线上升沿,发送1位数据
delay_us(); //等待1位数据发送完成
}
IIC_SCL_LOW();
IIC_SDA_HIGH(); //8位数据发送完成,数据线拉高,等待SLAVE器件响应
delay_us();
IIC_SCL_HIGH(); //时钟线拉高,产生上升沿读取数据线是否SLAVE器件有响应
//while(IIC_SDA==1);
delay_us();
IIC_SCL_LOW();
IIC_SDA_HIGH(); //数据线拉高,时钟线拉低,等待转换完成
}
/***************
*SHT11接收数据时序
***************/
uint SHT_REC(void)
{
uint i;
uint REC1=,REC0=,REC=;
for(i=;i<;i++)
{
IIC_SCL_HIGH(); //转换完成,SLAVE器件将数据线拉低,时钟线产生上升沿读取高8位数据
REC1=(REC1<<)+IIC_SDA;
delay_us();
IIC_SCL_LOW(); //将时钟线拉低,等待下一个上升沿的到来
delay_us();
}
SHT_ASK(); //高8位数据接收完毕,发送应答信号
for(i=;i<;i++)
{
IIC_SCL_HIGH(); //转换完成,SLAVE器件将数据线拉低,时钟线产生上升沿读取低8位数据
REC0=(REC0<<)+IIC_SDA;
delay_us();
IIC_SCL_LOW();
delay_us();
}
SHT_STOP(); //低8位数据接收完毕,结束
REC=(REC1<<)+REC0;
return REC;
}
/***************
*SHT11应答时序
***************/
void SHT_ASK(void)
{
IIC_SCL_LOW();
IIC_SDA_LOW(); //数据线拉低
delay_us();
IIC_SCL_HIGH(); //时钟线拉高才生应答信号
delay_us();
IIC_SDA_HIGH();
IIC_SCL_LOW();
delay_us();
}
/***************
*SHT11停止时序
***************/
void SHT_STOP(void)
{
IIC_SDA_HIGH();
IIC_SCL_LOW();
delay_us();
IIC_SCL_HIGH();
delay_us();
IIC_SDA_HIGH();
IIC_SCL_LOW();
}

用I/O口模拟总线时序的更多相关文章

  1. 【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)

     版权声明:本文为博主原创文章,允许转载,但希望标注转载来源. https://blog.csdn.net/qq_38410730/article/details/80312357 IIC的基本介绍 ...

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

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

  3. MSP430的IO口模拟I2C总线对AT24C25进行读写程序

    功能: 实现MSP430口线模拟I2C总线协议与24C04通信.                                           ** 描述: 主系统工作时钟为12MHz,I2C工 ...

  4. 51单片机GPIO口模拟串口通信

    51单片机GPIO口模拟串口通信 标签: bytetimer终端存储 2011-08-03 11:06 6387人阅读 评论(2) 收藏 举报 本文章已收录于:   分类: 深入C语言(20) 作者同 ...

  5. stm32 普通IO口模拟串口通信

    普通IO口模拟串口通信 串口通信协议 串口传输 默认 波特率9600 1起始位 1停止位 其他0 数据位是8位(注意图上的给错了). 传输时,从起始位开始,从一个数据的低位(LSB)开始发送,如图从左 ...

  6. 使用软件模拟spi 时序时注意点

    软件模拟 spi 时序有以下几个点需要注意: cs 使能后到第一个 sck 边沿需要延时. 最后一个sck 边沿到下一个 cs 需要延时. sck 的高电平和低电平本身需要维持时间. mosi 需要先 ...

  7. S5PV210之GPIO模拟I2c时序之pcf8591与at24xx linux3.0.8驱动

    目录:一. 说明 二. 驱动程序说明及问题 三. 案例一       四. 案例二 一. 说明 mini210开发板上带了at24c08, 看了linux内核自带的at24.c的驱动程序,编译下载到看 ...

  8. lpc1788IO口模拟IIC

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

  9. GPIO软件模拟IIC时序

    一.MPU6050中的IIC时序 1.1 START和STOP SDA和SCL在高电平时,SDA拉低表示START.SCL拉低,表示可以传输数据. SDA和SCL在低电平时,SDA拉高表示STOP. ...

随机推荐

  1. 【我的Android进阶之旅】Realm数据库学习资料汇总(持续更新)

    介绍 realm是一个跨平台移动数据库引擎,支持iOS.OS X(Objective-C和Swift)以及Android. 2014年7月发布.由YCombinator孵化的创业团队历时几年打造,是第 ...

  2. Q35+uefi or bios+legacy // PCI | PCIE

    1:首先统一可扩展固件接口(UEFI)是一种规范定义操作系统和平台固件之间的软件接口. UEFI旨在替代基本输入/输出系统(BIOS)固件接口.(legacy) 硬件平台厂商越来越多地采用UEFI管理 ...

  3. Longest Palindromic Substring-Dynamic Programing

    Longest Palindromic Substring Given a string S, find the longest palindromic substring in S. Analysi ...

  4. VS2013 IIS Express 无法显示站点目录列表

      VS2013 默认使用IIS Express作为虚拟服务器,或许出于与安全考虑该版本的IIS Express默认关闭站点目录列表显示的功能,访问时会出现以下错误:   为了方便起见,我使用了全局设 ...

  5. libvirt-qemu-虚拟机设备热插拔

    cpu热插拔 # virsh setvcpus $domain_name --count 4 --live (--config可写入配置文件永久保存) #前提条件和后续激活参考<libvirt- ...

  6. Dispose 与 close 方法 的区别

    Dispose : 释放 托管 与 非托管资源. Finalize : 释放 非托管资源. Close: 关闭资源后,可以再次使用资源.

  7. [pixhawk笔记]3-架构概览

    本文主要内容翻译自:https://dev.px4.io/en/concept/architecture.html 总体架构: PX4代码由两层组成:PX4飞行栈和PX4中间件.其中,前者是一套飞行控 ...

  8. 20145201《Java程序设计》第十周学习总结

    教材学习内容总结 网络编程 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据. 程序员所作的事情就是把数据发送到指定的位置,或者接收到指定的数据,这个就是狭义的网络编程范畴. 在发送和接收 ...

  9. COS-4进程及进程管理

    操作系统是用户和计算机的接口,同时也是计算机硬件和其他软件的接口.操作系统的功能包括管理计算机系统的硬件.软件及数据资源,控制程序运行,改善人机界面,为其它应用软件提供支持,让计算机系统所有资源最大限 ...

  10. 使用John the ripper工具来尝试破解Linux密码

    这篇文章主要介绍了使用John the ripper工具来尝试破解Linux密码的方法,这款工具可能主要被用来破解系统用户的密码以获得文件操作权限,需要的朋友可以参考下 John有别于Hdra之类的工 ...