在做总线通信过程中,我们很少会用到这样方法,一般在我们选择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. Linux下套接字具体解释(九)---poll模式下的IO多路复用server

    參照 poll调用深入解析-从poll的实现来讲poll多路复用模型,非常有深度 poll多路复用 poll的机制与select相似,与select在本质上没有多大差别.管理多个描写叙述符也是进行轮询 ...

  2. Leetcode 之 Valid Triangle Number

    611. Valid Triangle Number 1.Problem Given an array consists of non-negative integers, your task is ...

  3. 2017年最有价值的IT认证——From Global Knowledge

  4. 001-ant design pro安装、目录结构、项目加载启动【原始、以及idea开发】

    一.概述 1.1.脚手架概念 编程领域中的“脚手架(Scaffolding)”指的是能够快速搭建项目“骨架”的一类工具.例如大多数的React项目都有src,public,webpack配置文件等等, ...

  5. PHP逐字符读取数据

    <?php $file = fopen("Minot.txt", "r") or exit("Unable to open file!" ...

  6. __name__ = '__main__'有什么用

    很多新手刚开始学习python的时候经常会看到python 中__name__ = \'__main__\' 这样的代码,可能很多新手一开始学习的时候都比较疑惑,python 中__name__ = ...

  7. linux:查看磁盘硬件信息hdparm,smartctl

    smartctl 命令 这个一个用于控制和监控支持smart技术的硬盘的命令.通常配合 -a 选项我们可以查看到比较详尽的硬盘信息(比如序列号.硬盘容量.已运行时间.硬盘健康状况等).用法如下: sm ...

  8. Spark机器学习5·回归模型(pyspark)

    分类模型的预测目标是:类别编号 回归模型的预测目标是:实数变量 回归模型种类 线性模型 最小二乘回归模型 应用L2正则化时--岭回归(ridge regression) 应用L1正则化时--LASSO ...

  9. 【Flask】WTForms文件上传下载

    # 文件上传笔记:1. 在模版中,form表单中,需要指定`encotype='multipart/form-data'`才能上传文件.2. 在后台如果想要获取上传的文件,那么应该使用`request ...

  10. MySQL-5.7 DELETE语句详解

    1.语法 (1)单表 DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name [PARTITION (partition_name [, partit ...