原创 对SHT1x的驱动实现(一)

2010-9-7 13:32 2139 11 11 分类: 消费电子

<1> 介绍
当我们进行湿度测量时, 我们处于工作的习惯, 仍然期待选择一款数字式的传感器. 实际上, 因为我们供货商的推荐, 我们选用了 SENSIRION 的 SHT1x 温湿度数字传感器. 这是一只有着2只数据脚的 sensor. 一根 sck, 一根 data. 本文中, 我们记录下若干驱动过程中遇到一些有兴趣的要点, 或者可以与诸位同仁进行更深入的讨论.

<2> 参考文档
1. Datasheet: from webpage of sensirion

<3> 驱动流程
我们记录下我们的理解如下:
1. Send a command 是一个固有约定格式的过程.
2. 在一个下降沿中, 保持 low. 同时在下一个上升沿中保持 data 为 low. 表示发送开始.
3. 一个字节的 cmd byte.
4. 多送一个 0 bit, 表示确认发送结束.
5. release data, 等待 sensor 将 data 拉底, 通知测量结束.
6. 每次读取完毕一个 byte, 在新的 low 被拉低通知后, 应该主动进行一个 ACK 脉冲, 进行确认. 完毕确认后, 如果还有跟随需要 readout 的 byte, 则可以再次读取.
7. 被读取的温度数据或者湿度数据, 都会在此跟随一个 CRC byte. 读取了 CRC byte, 并完成 ACK, 那么整个测量的过程, 就算结束. 不过, SHT1x 也提供了我们一个小的技巧, 可以不去读 CRC(假设CRC 在我们的应用中没有使用). 这就是, 在读取完毕最后一个有效温度或者湿度数据后, 我们不进行 ACK. 也就是保持 release data. 那么 datasheet 告诉我们, SHT1x 将 明白, 我们打算忽略 CRC byte. SHT1x 将结束这次(温度湿度数据)的发送过程, 并在此进行到 sleep (待机)状态.

<4> 实际操作中对 transstart 和 connection reset 的使用
尽管我们会习惯性感觉, 每次 measure 的过程, 是否只用做 transstart 就可以开始. 但是实际使用中, Allen 发现单纯依赖 transstart 总是似乎没有那么可靠. 最后的代码中, 我们在每次 measure 之前, 都使用了 connectionreset, 来保证每次通讯的可靠性.
那么在我们的调试中为什么会出这个 condition? 我们猜测: 存在这样的可能, 就是在调试的过程中, 我们常常并没有一个完成的 write + read 的 whole process. 这样就造成了 sensor 无法判断上一个 measure 的过程是否结束. 从而会导致 connection event 的连接失效. 但是既然存在着这样的 invalid 的可能性, 我们每次执行 connectionreset, 也应该是合理的?

<5> 完成温度转化的时间
Datasheet 说, 完成 14bit 的温度测量的时间, 要长过完成 12bit 的湿度测试量的时间. Datasheet 给出的标准的温度测量的时间是 320ms. 我们的调试结果是, 不到 300ms, 温度的转换过程即可实现.

<6> 代码的例子
首先我们要声明, 从 SENSIRION 的网站上, 下载 dirver sample code, 是必须的. 而我们这里提供的, 被我们调试过的代码, 由于我们在硬件上的保护电路的使用. 我们把单一的 data 拆成了 input 和 output 两路.
因此, 可能会给阅读我们的 code sample 带来不便. 同时, 我们还必须指出, 保护电路至少带给我们 4us 的延时. 而在一个典型的 sensor 电路中, 应该不会有这样 delay 的存在. 我们对这些不便之处表示歉意.

/*
 * sht1x.c
 *
 * DESCRIPTION:
 *      Measure Temparature and relative humidity.
 *
 * FUNCTION:
 *      @ Use sht1x_measure() to answer uart measure command.
 *      @ Use sht1x_do_convert() to do convert process.
 *      @ After about 500ms, use TBD() to get vaule with timer.
 *
 * NOTE:
 *      We use input/output trax unit to do out/in job, we think it will protect the mcu io.
 *
 * $Author: Allen Zhan; ; ;
 * $Create Date: 2010/08/29 10:59 Beijin Timezone $
 *
 * Copyright 2010 Shenzhen GV Technology Co., Ltd. <>.  All rights reserved.
 *
 */

#include "..\inc\config.h"
#include "..\inc\utils.h"
#include "..\inc\sht1x.h"


//// predefine
#define noACK               0
#define ACK                 1
                                        //adr  command  r/w
#define STATUS_REG_W        0x06        //000   0011    0
#define STATUS_REG_R        0x07        //000   0011    1
#define MEASURE_TEMP        0x03        //000   0001    1
#define MEASURE_HUMI        0x05        //000   0010    1
#define RESET               0x1e        //000   1111    0


// writes a byte on the Sensibus and checks the acknowledge
U8 sht1x_write_byte(U8 value)
{
        U8 error = 0; 

        // send byte to sensor
        for(U32 i=0x80; i>0; i/=2) {
            if (i & value)
                IO0CLR = SENSIBUS_DATA_OUT_PIN;         // data=1
            else
                IO0SET = SENSIBUS_DATA_OUT_PIN;         // data=0
            IO0CLR = SENSIBUS_SCK_PIN;                  // sck=1
            delay_mcu(32);                              // pulswith approx. 8us in our system
            IO0SET = SENSIBUS_SCK_PIN;                  // sck=0
            delay_mcu(32);                              // 4us for our min trax module
        }

        // check ack from sensor
        IO0CLR = SENSIBUS_DATA_OUT_PIN;                 // data=1, release DATA-line
        IO0CLR = SENSIBUS_SCK_PIN;                      // sck=1, clk #9 for ack
        delay_mcu(32);                                  // 4us for our min trax module       
        if( (IO0PIN&SENSIBUS_DATA_IN_PIN) == 0x00 )     // check ack (DATA will be pulled down by SHT11, data=1)
            error = 1;                                  // data=1, still high shows error
        else
            error = 0;                                  // data=0, sensor pull low data line as acknowledge
        IO0SET = SENSIBUS_SCK_PIN;                      // sck=0   
       
        // do system delay waiting data line release and return to data=1
        delay_mcu(32);
       
        return error;                                   //error=1 in case of no acknowledge
}


// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
U8 sht1x_read_byte(U8 ack)
{
        U8 val = 0;
       
        // read byte from sensor
        IO0CLR = SENSIBUS_DATA_OUT_PIN;                 // data=1, release DATA-line
        delay_mcu(32);                                  // 4us
        for(U32 i=0x80; i>0; i/=2) {                     
            IO0CLR = SENSIBUS_SCK_PIN;                  // sck=1
            delay_mcu(32);                              // 4us
            if( (IO0PIN&SENSIBUS_DATA_IN_PIN) == 0x00 ) // if data==1
                val=(val | i);                          //read bit             
            IO0SET = SENSIBUS_SCK_PIN;                  // sck=0
            delay_mcu(32);                              // 4us
        }
       
        // in case of "ack==1" pull down DATA-Line
        if(ack)
            IO0SET = SENSIBUS_DATA_OUT_PIN;             // data=0
        else
            IO0CLR = SENSIBUS_DATA_OUT_PIN;             // data=1 
        delay_mcu(32);                                  // 4us
        IO0CLR = SENSIBUS_SCK_PIN;                      // sck=1, clk #9 for ack
        delay_mcu(32);                                  // 4us
        IO0SET = SENSIBUS_SCK_PIN;                      // sck=0       
        IO0CLR = SENSIBUS_DATA_OUT_PIN;                 // data=1, release DATA-line
        delay_mcu(32);                                  // 4us

        return val;
}



对SHT1x的驱动实现(一)
对SHT1x的驱动实现(二)

文章评论0条评论)

登录后参与讨论
我要评论
0
11
关闭 站长推荐上一条 /2 下一条