⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sensirionsht11logicp.nc

📁 tinyos2.0版本驱动
💻 NC
字号:
/* * Copyright (c) 2005-2006 Arch Rock Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * - Redistributions of source code must retain the above copyright *   notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright *   notice, this list of conditions and the following disclaimer in the *   documentation and/or other materials provided with the *   distribution. * - Neither the name of the Arch Rock Corporation nor the names of *   its contributors may be used to endorse or promote products derived *   from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE */#include "Timer.h"#include "SensirionSht11.h"/** * SensirionSht11LogicP contains the actual driver logic needed to * read from the Sensirion SHT11 temperature/humidity sensor. It * depends on 2 underlying GeneralIO interfaces, one for the data pin * and one for the clock pin, and one underlying GpioInterrupt.  It * provides the HAL-level SensirionSht11 interface. It's generic, so * you can instantiate it multiple times if you have more than one * Sensirion SHT11 attached to a node.  *  * <p> * This code assumes that the MCU clock is less than 10 MHz.  If you * ever run this on a faster MCU, you'll need to insert a lot of * waits to keep the Sensirion happy. * * @author Gilman Tolle <gtolle@archrock.com> * @version $Revision: 1.4 $ $Date: 2006/12/12 18:23:12 $ */generic module SensirionSht11LogicP() {  provides interface SensirionSht11[ uint8_t client ];  uses interface GeneralIO as DATA;  uses interface GeneralIO as CLOCK;  uses interface GpioInterrupt as InterruptDATA;  uses interface Timer<TMilli>;  uses interface Leds;}implementation {  typedef enum {    CMD_MEASURE_TEMPERATURE = 0x3,    CMD_MEASURE_HUMIDITY = 0x5,    CMD_READ_STATUS = 0x7,    CMD_WRITE_STATUS = 0x6,    CMD_SOFT_RESET = 0x1E,  } sht_cmd_t;  enum {    TIMEOUT_RESET = 11,    TIMEOUT_14BIT = 250,    TIMEOUT_12BIT = 250, //70,    TIMEOUT_8BIT = 250, //15,  } sht_timeout_t;  bool on = TRUE;  bool busy = FALSE;  uint8_t status = 0;  sht_cmd_t cmd;  uint8_t newStatus;  bool writeFail = FALSE;  uint8_t currentClient;  error_t performCommand();  void initPins();  void resetDevice();  void transmissionStart();  void sendCommand(uint8_t _cmd);  void writeByte(uint8_t byte);  error_t waitForResponse();  void enableInterrupt();  uint8_t readByte();  void ack();  void endTransmission();  task void readSensor();  task void signalStatusDone();  command error_t SensirionSht11.reset[ uint8_t client ]() {    if ( !on ) { return EOFF; }    if ( busy ) { return EBUSY; } else { busy = TRUE; }    cmd = CMD_SOFT_RESET;    currentClient = client;    return performCommand();  }  command error_t SensirionSht11.measureTemperature[ uint8_t client ]() {    if ( !on ) { return EOFF; }    if ( busy ) { return EBUSY; } else { busy = TRUE; }    cmd = CMD_MEASURE_TEMPERATURE;    currentClient = client;    return performCommand();  }    command error_t SensirionSht11.measureHumidity[ uint8_t client ]() {    if ( !on ) { return EOFF; }    if ( busy ) { return EBUSY; } else { busy = TRUE; }    cmd = CMD_MEASURE_HUMIDITY;    currentClient = client;    return performCommand();  }  /* FIXME: these don't seem to work */  command error_t SensirionSht11.readStatusReg[ uint8_t client ]() {    if ( !on ) { return EOFF; }    if ( busy ) { return EBUSY; } else { busy = TRUE; }    cmd = CMD_READ_STATUS;    currentClient = client;    return performCommand();  }    /* FIXME: these don't seem to work */  command error_t SensirionSht11.writeStatusReg[ uint8_t client ]( uint8_t val ) {    if ( !on ) { return EOFF; }    if ( busy ) { return EBUSY; } else { busy = TRUE; }    cmd = CMD_WRITE_STATUS;    newStatus = val;    currentClient = client;    return performCommand();  }  // performCommand() returns both error_t and status reg -- fortunately, error_t is 8bit  error_t performCommand() {    initPins();    resetDevice();    transmissionStart();    cmd &= 0x1F; // clear the first 3 address bits to 000    sendCommand(cmd);    if ( waitForResponse() != SUCCESS ) {      busy = FALSE;      return FAIL;    }    switch(cmd) {    case CMD_SOFT_RESET:      call Timer.startOneShot( TIMEOUT_RESET );      break;    case CMD_MEASURE_TEMPERATURE:      enableInterrupt();      if ( status & SHT11_STATUS_LOW_RES_BIT ) {	call Timer.startOneShot( TIMEOUT_12BIT );      } else {	call Timer.startOneShot( TIMEOUT_14BIT );      }      break;    case CMD_MEASURE_HUMIDITY:      enableInterrupt();      if ( status & SHT11_STATUS_LOW_RES_BIT ) {	call Timer.startOneShot( TIMEOUT_8BIT );      } else {	call Timer.startOneShot( TIMEOUT_12BIT );      }      break;    case CMD_READ_STATUS:     {      uint8_t tempStatus;      uint8_t crc;      tempStatus = readByte();      crc = readByte();      endTransmission();      status = tempStatus; // FIXME: need to check CRC!            post signalStatusDone();    }        case CMD_WRITE_STATUS:      writeByte( newStatus );            if ( waitForResponse() != SUCCESS ) {	writeFail = TRUE;      } else {	status = newStatus;      }            post signalStatusDone();    }    // leave the device busy...we're waiting for an interrupt    return SUCCESS;  }  void initPins() {    call CLOCK.makeOutput();    call CLOCK.clr();    call DATA.makeInput();    call DATA.set();    call InterruptDATA.disable();  }    void resetDevice() {    uint8_t i;    call DATA.makeOutput();    call DATA.set();    call CLOCK.clr();    for( i = 0; i < 9; i++ ) {      call CLOCK.set();      call CLOCK.clr();    }  }  void transmissionStart() {    call DATA.makeOutput();    call DATA.set();    call CLOCK.clr();    call CLOCK.set();    call DATA.clr();    call CLOCK.clr();    call CLOCK.set();    call DATA.set();    call CLOCK.clr();  }  void sendCommand(uint8_t _cmd) {    writeByte(_cmd);  }  void writeByte(uint8_t byte) {    uint8_t i;    for( i = 0; i < 8; i++ ) {      if ( byte & 0x80 )	call DATA.set();      else	call DATA.clr();      byte = byte << 1;      call CLOCK.set();      call CLOCK.clr();    }  }  error_t waitForResponse() {    call DATA.makeInput();    call DATA.set();    call CLOCK.set();    if (call DATA.get()) {      // the device didn't pull the DATA line low      // the command wasn't received or acknowledged      return FAIL;    }    call CLOCK.clr();    return SUCCESS;  }  void enableInterrupt() {    call DATA.makeInput();    call DATA.set();    call InterruptDATA.enableFallingEdge();  }  event void Timer.fired() {    switch(cmd) {    case CMD_SOFT_RESET:      // driver has waited long enough for device to reset      busy = FALSE;      signal SensirionSht11.resetDone[currentClient]( SUCCESS );      break;    case CMD_MEASURE_TEMPERATURE:      // timeout expired with no data interrupt      busy = FALSE;      signal SensirionSht11.measureTemperatureDone[currentClient]( FAIL, 0 );      break;    case CMD_MEASURE_HUMIDITY:      // timeout expired with no data interrupt      busy = FALSE;      signal SensirionSht11.measureHumidityDone[currentClient]( FAIL, 0 );      break;    default:      // we're in an unexpected state. what to do?      break;    }  }  async event void InterruptDATA.fired() {    call InterruptDATA.disable();    post readSensor();  }  task void readSensor() {    uint16_t data = 0;    uint8_t crc = 0;    if ( busy == FALSE ) {      // the interrupt was received after the timeout.       // we've already signaled FAIL to the client, so just give up.      return;    }    call Timer.stop();    data = readByte() << 8;    data |= readByte();    crc = readByte();        endTransmission();    switch( cmd ) {    case CMD_MEASURE_TEMPERATURE:      busy = FALSE;      signal SensirionSht11.measureTemperatureDone[currentClient]( SUCCESS, data );      break;    case CMD_MEASURE_HUMIDITY:      busy = FALSE;      signal SensirionSht11.measureHumidityDone[currentClient]( SUCCESS, data );      break;    default:      break; // unknown command - shouldn't reach here    }  }  uint8_t readByte() {    uint8_t byte = 0;    uint8_t i;    for( i = 0; i < 8; i++ ) {      call CLOCK.set();      if (call DATA.get())	byte |= 1;      if (i != 7) 	byte = byte << 1;      call CLOCK.clr();    }    ack();    return byte;  }  void ack() {    call DATA.makeOutput();    call DATA.clr();    call CLOCK.set();    call CLOCK.clr();    call DATA.makeInput();    call DATA.set();  }    void endTransmission() {    call DATA.makeOutput();    call DATA.set();    call CLOCK.set();    call CLOCK.clr();  }  task void signalStatusDone() {    bool _writeFail = writeFail;    switch( cmd ) {    case CMD_READ_STATUS:      busy = FALSE;      signal SensirionSht11.readStatusRegDone[currentClient]( SUCCESS, status );      break;    case CMD_WRITE_STATUS:      busy = FALSE;      writeFail = FALSE;      signal SensirionSht11.writeStatusRegDone[currentClient]( (_writeFail ? FAIL : SUCCESS) );      break;    default:      // shouldn't happen.      break;    }  }  default event void SensirionSht11.resetDone[uint8_t client]( error_t result ) { }  default event void SensirionSht11.measureTemperatureDone[uint8_t client]( error_t result, uint16_t val ) { }  default event void SensirionSht11.measureHumidityDone[uint8_t client]( error_t result, uint16_t val ) { }  default event void SensirionSht11.readStatusRegDone[uint8_t client]( error_t result, uint8_t val ) { }  default event void SensirionSht11.writeStatusRegDone[uint8_t client]( error_t result ) { }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -