传感器的离线判断

最近在做大棚物联网的小项目,其中各个节点上都挂有多个传感器,包括空气温湿度传感器SHT1X,土壤温度DS18B20,光照传感器BH1750等。现在要对各个传感器的在线状态做一个判断,确定各个传感器是否都在线,以便于后台及时维修和管理。

之前用的方式较为简单,就是不插上传感器,单片机会读到一个异常的值(看起来就很不正常的值),但是这种方式还是有些缺陷的,根本的做法是根据芯片时序来判断,即利用芯片将单片机IO口拉低这个动作来确定传感器芯片是否存在。

在SHT1X的手册中,有这么一段:

SHT1x 会以下述方式表示已正确地接收到指令:在第8 SCK 时钟的下降沿之后,将DATA下拉为低电平(ACK位)。在第9 SCK时钟的下降沿之后,释放DATA(恢复高电平)

因此一个自然的想法就是利用这一特点来检测:

  u8 SHT1x_Write_Byte(u8 value)
{
    u8 i=0,error=0;
      u8 bit;
    SDA_SET_OUT();
    for(i=0x80;i>0;i/=2)
    {
        if(i&value)SDA_Pin_OUT(1);
        else SDA_Pin_OUT(0);
        
        delay_us(30);
        SCL_Pin_OUT(1);
        delay_us(30);
        SCL_Pin_OUT(0);
        delay_us(30);
    }                                          //到这个地方正好是第8个SCK时钟的下降沿
    
        SDA_SET_IN();
        delay_us(30);
        bit=GPIO_ReadInputDataBit(GPIOA, SDA);   //判断DATA 是否被拉为低电平
        error=bit;
       SCL_Pin_OUT(1);
       delay_us(30);
       SCL_Pin_OUT(0);
       bit=GPIO_ReadInputDataBit(GPIOA, SDA); 
       error=(error<<1)|(bit&0x01);                //如果打印信息是1,则表明存在,若是3,则表明不存在
    
    return error;  
}

 
  

稳妥起见,将SDA输入模式配置为内部上拉,因为不插器件的时候IO是浮空状态,不知道读的是什么。

void SDA_SET_IN(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = SDA;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    
    //GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);    
}


测试结果表明,该方法可以作为有效的检测手段。

然后是DS18B20,这个单总线的器件判断是否在线也很简单

主机首先发出一个480-960微秒的低电平脉冲,然后释放总线变为高电平,并在随后的480微秒时间内对总线进行检测,如果有低电平出现说明总线上有器件已做出应答。若无低电平出现一直都是高电平说明总线上无器件应答。

做为从器件的DS18B20在一上电后就一直在检测总线上是否有480-960微秒的低电平出现,如果有,在总线转为高电平后等待15-60微秒后将总线电平拉低60-240微秒做出响应存在脉冲,告诉主机本器件已做好准备。若没有检测到就一直在检测等待。

将初始化函数改为有返回值类型,返回0说明器件存在,返回1说明器件不存在。

u8 ds18b20init()
{
    u8 err;
    DQOUTINT();
    ds18b20_dq_L;
    delay_us(500);
    ds18b20_dq_H;
    delay_us(70);
    DQININT();   
    delay_us(20);
    if(GPIO_ReadInputDataBit(GPIO_ds18b20,dq)==1)
    {
        err=1;  
    }
    else
    {
        err=0;
    }        
    delay_us(480);
    
    return err;
}

实验结果表明,该方法是有效的。










你可能感兴趣的:(杂谈)