在做总线通讯过程中,咱们很少会用到这样办法,一般在咱们挑选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(5);
IIC_SDA_LOW();
delay_us(5);
IIC_SCL_LOW();
delay_us(5);
IIC_SCL_HIGH();
delay_us(5);
IIC_SDA_HIGH();
delay_us(5);
IIC_SCL_LOW();
}
/***************
*SHT11发送数据时序
***************/
void SHT_SEND(uchar data)
{uchar i,data1;
for(i=0;i<8;i++)
{
data1=data<
if(!(data1&0x80))
IIC_SDA_LOW();
if(data1&0x80)
IIC_SDA_HIGH();
IIC_SCL_LOW();//写完1位数据将时钟线拉低,等候发送
delay_us(5);
IIC_SCL_HIGH();//时钟线上升沿,发送1位数据
delay_us(5); //等候1位数据发送完结
}
IIC_SCL_LOW();
IIC_SDA_HIGH();//8位数据发送完结,数据线拉高,等候SLAVE器材呼应
delay_us(5);
IIC_SCL_HIGH();//时钟线拉高,发生上升沿读取数据线是否SLAVE器材有呼应
//while(IIC_SDA==1);
delay_us(5);
IIC_SCL_LOW();
IIC_SDA_HIGH();//数据线拉高,时钟线拉低,等候转化完结
}
/***************
*SHT11接纳数据时序
***************/
uint SHT_REC(void)
{
uint i;
uint REC1=0,REC0=0,REC=0;
for(i=0;i<8;i++)
{
IIC_SCL_HIGH();//转化完结,SLAVE器材将数据线拉低,时钟线发生上升沿读取高8位数据
REC1=(REC1<<1)+IIC_SDA;
delay_us(5);
IIC_SCL_LOW(); //将时钟线拉低,等候下一个上升沿的到来
delay_us(5);
}
SHT_ASK(); //高8位数据接纳完毕,发送应对信号
for(i=0;i<8;i++)
{
IIC_SCL_HIGH();//转化完结,SLAVE器材将数据线拉低,时钟线发生上升沿读取低8位数据
REC0=(REC0<<1)+IIC_SDA;
delay_us(5);
IIC_SCL_LOW();
delay_us(5);
}
SHT_STOP();//低8位数据接纳完毕,完毕
REC=(REC1<<8)+REC0;
return REC;
}
/***************
*SHT11应对时序
***************/
void SHT_ASK(void)
{
IIC_SCL_LOW();
IIC_SDA_LOW();//数据线拉低
delay_us(5);
IIC_SCL_HIGH();//时钟线拉高才生应对信号
delay_us(5);
IIC_SDA_HIGH();
IIC_SCL_LOW();
delay_us(5);
}
/***************
*SHT11中止时序
***************/
void SHT_STOP(void)
{
IIC_SDA_HIGH();
IIC_SCL_LOW();
delay_us(5);
IIC_SCL_HIGH();
delay_us(5);
IIC_SDA_HIGH();
I%&&&&&%_SCL_LOW();
}