在做总线通信过程中,我们很少会用到这样方法,一般在我们选择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. 0505-Hystrix保护应用-Turbine集群状态监控

    https://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#_turbine

  2. python删除所有的中文字符、非ASCII或非英文字符,检查字符串是否包含非ASCII

    Your ''.join() expression is filtering, removing anything non-ASCII; you could use a conditional exp ...

  3. linux 学习笔记之文件与管理

    前言: 对于windows来说,文件的系统管理都是非常简单的(这个应该有一个捂脸),通常就是重命名,复制,移动,删除,查看文件属性,查看文件内容,寻找文件.其实在图形化行中的linux也是有这样子功能 ...

  4. 用Maven构建Mahout项目实现协同过滤userCF--单机版

    本文来自:http://blog.fens.me/hadoop-mahout-maven-eclipse/ 前言 基于Hadoop的项目,不管是MapReduce开发,还是Mahout的开发都是在一个 ...

  5. mysqlbinlog作用

    mysqlbinlog:解析mysql的binlog日志 在 mysql-bin.index里面记录了所有的binlog文件,它是一个索引 binlog日志的作用:用来记录mysql内部增删改查等对m ...

  6. Matplot相关(二)——统计图

    Matplotlib:其能够支持所有的2D作图和部分3D作图.能通过交互环境做出印刷质量的图像. ————————缩写定义———————— import matplot.pyplot as plt — ...

  7. HackerRank - common-child【DP】

    HackerRank - common-child[DP] 题意 给出两串长度相等的字符串,找出他们的最长公共子序列e 思路 字符串版的LCS AC代码 #include <iostream&g ...

  8. 经典iOS第三方库源码分析 - YYModel

    YYModel介绍 YYModel是一个针对iOS/OSX平台的高性能的Model解析库,是属于YYKit的一个组件,创建是ibireme. 其实在YYModel出现之前,已经有非常多的Model解析 ...

  9. [国家集训队] calc(动规+拉格朗日插值法)

    题目 P4463 [国家集训队] calc 集训队的题目真是做不动呀\(\%>\_<\%\) 朴素方程 设\(f_{i,j}\)为前\(i\)个数值域\([1,j]\),且序列递增的总贡献 ...

  10. Apache 日志管理

    日志参数 %% 百分号(Apache2.0.44或更高的版本) %a 远端IP地址 %A 本机IP地址 %B 除HTTP头以外传送的字节数 %b 以CLF格式显示的除HTTP头以外传送的字节数,也就是 ...