单总线、IIC、SPI接口详解(一)
单总线 IIC SPI
大棒棒猪
发布时间: 2019-05-31
阅读: 1727

相信大家在初次接触到单片机的时候,会发现有很多种类的外围设备。如温湿度传感器、时钟芯片、陀螺仪等等。在面对这么多种类型的设备时,很多人都会有种无从下手的感觉。并且一开始也并不知道单片机是怎么把传感器的数据读出来, 也不知道怎么去驱动设备。下面就给大家说说这些接口。

一.单总线

1、采用单总线的设备有非常具有代表性的温度传感器DS18B20以及温湿度传感器DHT11。顾以名思义单总线即只有单根信号线,该线即传输数据也传输时钟,并且数据传输也为双向。此处与spi、i2c以及串口不同。采用这种形式可以节省io口,并且简单。

我们通过DHT11的时序来讲讲单总线的机制以及编程方法。

①总线空闲时,总保持高电平。

②总线都先由主机拉低一段时间(需让从机能够检测到起始信号)在拉高,等待从机响应。

③从机发送低电平响应信号,从机拉高总线电平,表示准备输出

④从机发送信号,主机读取从机信号。

⑤结束后,继续保持总线为高电平

下图为单片机与DHT11通讯过程图

TIM截图20190527233546.png

2、接下来是从机如何表示每bit,信号1与信号0的表示。

在DHT11中,每一bit数据都先以50us的低电平开始,高电平的时间长短来确定该数据位为1或0。

信号0的表示方法如下图,开始以50us的低电平,26-28us的高电平组合表示信号0.

TIM截图20190527234523.png

信号1的表示如下图所示。同样以50us的低电平开始,70us的高电平组合表示信号1.

TIM截图20190527234602.png

3、DHT11的数据,共计40bits。由湿度整数部分8bit+湿度小数部分8bit+温度整数部分8bit+温度小数部分8bit+校验8bit(和校验)。

  (两点注意:①目前小数部分为0,所以只有整数部分有效  ②其他很多传感器采用高8bit+低8bit再除以100表示温湿度与此处不同)

   示例: 0011 0001             0000 0000           0001 0110           0000 0000         0100 0111

             湿度整数部分       湿度小数部分       温度整数部分       温度小数部分         和校验

   00110001=31H=49%

   00010110=16H=22℃

   01000111=47H=71    和校验正确,代表数据正确可靠。即温度22℃,湿度49%。

4、程序部分

sbit DHTbus=P1^0;

void  readBus(void)
      {
    u8 i;
        for(i=0;i<8;i++)       
        {        
           U8FLAG=2;    
        while((!DHTbus)&&U8FLAG++);
        Delay_10us();
        Delay_10us();
        Delay_10us();
        U8temp=0;
        if(DHTbus)U8temp=1;
        U8FLAG=2;
        while((DHTbus)&&U8FLAG++);
        //超时则跳出for循环          
        if(U8FLAG==1)break;
        //判断数据位是0还是1                   
        // 如果高电平高过预定0高电平值则数据位为 1            
        U8busdata<<=1;
          U8busdata|=U8temp;        //0
         }       
    }

void DHT11(void)
    {
       //主机拉低18ms
        DHTbus=0;
       Delay(180);
       DHTbus=1;
       //总线由上拉电阻拉高 主机延时20us
       Delay_10us();
       Delay_10us();
       Delay_10us();
       Delay_10us();
       //主机设为输入 判断从机响应信号
       DHTbus=1;
       //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行      
       if(!DHTbus)         //T !      
       {
       U8FLAG=2;
       //判断从机是否发出 80us 的低电平响应信号是否结束    
       while((!P2_0)&&U8FLAG++);
       U8FLAG=2;
       //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
       while((P2_0)&&U8FLAG++);
       //数据接收状态        
       readBus();
       U8RH_data_H_temp=U8busdata;
       readBus();
       U8RH_data_L_temp=U8busdata;
       readBus();
       U8T_data_H_temp=U8busdata;
       readBus();
       U8T_data_L_temp=U8busdata;
       readBus();
       U8checkdata_temp=U8busdata;
       DHTbus=1; //释放总线
            //数据校验     
       U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
       if(U8temp==U8checkdata_temp)
       {
             U8RH_data_H=U8RH_data_H_temp;
             U8RH_data_L=U8RH_data_L_temp;
          U8T_data_H=U8T_data_H_temp;
             U8T_data_L=U8T_data_L_temp;
             U8checkdata=U8checkdata_temp;
       }
}
}

由于DHT11对延时有要求,所以单片机的延时函数需要大致计算一下时间,确保每次延时都能在DHT11的规定范围内。
 印象中有挺多学弟学习51时,在初次使用DHT11的时候,拿到官方或者别人写好的例程就往单片机里面烧写,发现确实能够得到数据,以为这样就大功告成。
 没曾想之后的项目中使用了功能更加齐全的12C5a60s2,同样的例程烧写到单片机里面时,发现程序没有用了。绞尽脑汁都觉得是单片机或者DHT11出了问题。
 但其实主要还是没有弄清楚DHT11的时序,以及单片机的延时。在实际测试中,相同的以下程序
 void Delay(U16 j)
     {
     u8 i;
        for(;j>0;j--)
         {     
 for(i=0;i<27;i++);
       }
     }
 STC89C52RC与STC12C5A60S2要相差很多,用示波器测出的结果大致为12C5A要比89C52RC快上3-5倍。这也就导致了在普通51单片机上面能正常运行,但是换上12C5A就毫无作用的原因了。


原创作品,未经权利人授权禁止转载。详情见转载须知 举报文章

展开查看更多
点赞 (8)
打赏
当前打赏0人    
大棒棒猪 擅长:工控电子 设计,制造及服务 计算机网络 智能硬件
相关文章推荐
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回

我要举报该内容理由

×
请输入您举报的理由(50字以内)