sht11.c

00001 /*
00002  * Copyright (c) 2007, Swedish Institute of Computer Science
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * @(#)$Id: sht11.c,v 1.3 2008/11/10 21:10:36 adamdunkels Exp $
00030  */
00031 
00032 /*
00033  * Device driver for the Sensirion SHT1x/SHT7x family of humidity and
00034  * temperature sensors.
00035  */
00036 
00037 #include <stdio.h>
00038 
00039 #include <io.h>
00040 
00041 #include <dev/sht11.h>
00042 #include "sht11-arch.h"
00043 
00044 #define SDA_0()   (SHT11_PxDIR |=  BV(SHT11_ARCH_SDA))  /* SDA Output=0 */
00045 #define SDA_1()   (SHT11_PxDIR &= ~BV(SHT11_ARCH_SDA))  /* SDA Input */
00046 #define SDA_IS_1  (SHT11_PxIN & BV(SHT11_ARCH_SDA))
00047 
00048 #define SCL_0()   (SHT11_PxOUT &= ~BV(SHT11_ARCH_SCL))  /* SCL Output=0 */
00049 #define SCL_1()   (SHT11_PxOUT |=  BV(SHT11_ARCH_SCL))  /* SCL Output=1 */
00050 
00051                                 /* adr   command  r/w */
00052 #define  STATUS_REG_W   0x06    /* 000    0011    0 */
00053 #define  STATUS_REG_R   0x07    /* 000    0011    1 */
00054 #define  MEASURE_TEMP   0x03    /* 000    0001    1 */
00055 #define  MEASURE_HUMI   0x05    /* 000    0010    1 */
00056 #define  RESET          0x1e    /* 000    1111    0 */
00057 
00058 /* This can probably be reduced to 250ns according to data sheet. */
00059 #define delay_400ns() _NOP()
00060 /*---------------------------------------------------------------------------*/
00061 static void
00062 sstart(void)
00063 {
00064   SDA_1(); SCL_0();
00065   delay_400ns();
00066   SCL_1();
00067   delay_400ns();
00068   SDA_0();
00069   delay_400ns();
00070   SCL_0();
00071   delay_400ns();
00072   SCL_1();
00073   delay_400ns();
00074   SDA_1();
00075   delay_400ns();
00076   SCL_0();
00077 }
00078 /*---------------------------------------------------------------------------*/
00079 static void
00080 sreset(void)
00081 {
00082   int i;
00083   SDA_1();
00084   SCL_0();
00085   for(i = 0; i < 9 ; i++) {
00086     SCL_1();
00087     delay_400ns();
00088     SCL_0();
00089   }
00090   sstart();                     /* Start transmission, why??? */
00091 }
00092 /*---------------------------------------------------------------------------*/
00093 /*
00094  * Return true if we received an ACK.
00095  */
00096 static int
00097 swrite(unsigned _c)
00098 {
00099   unsigned char c = _c;
00100   int i;
00101   int ret;
00102 
00103   for(i = 0; i < 8; i++, c <<= 1) {
00104     if(c & 0x80) {
00105       SDA_1();
00106     } else {
00107       SDA_0();
00108     }
00109     SCL_1();
00110     delay_400ns();
00111     SCL_0();
00112   }
00113 
00114   SDA_1();
00115   SCL_1();
00116   delay_400ns();
00117   ret = !SDA_IS_1;
00118 
00119   SCL_0();
00120 
00121   return ret;
00122 }
00123 /*---------------------------------------------------------------------------*/
00124 static unsigned
00125 sread(int send_ack)
00126 {
00127   int i;
00128   unsigned char c = 0x00;
00129 
00130   SDA_1();
00131   for(i = 0; i < 8; i++) {
00132     c <<= 1;
00133     SCL_1();
00134     delay_400ns();
00135     if(SDA_IS_1) {
00136       c |= 0x1;
00137     }
00138     SCL_0();
00139   }
00140 
00141   if(send_ack) {
00142     SDA_0();
00143   }
00144   SCL_1();
00145   delay_400ns();
00146   SCL_0();
00147 
00148   SDA_1();                      /* Release SDA */
00149 
00150   return c;
00151 }
00152 /*---------------------------------------------------------------------------*/
00153 #define CRC_CHECK
00154 #ifdef CRC_CHECK
00155 static unsigned char
00156 rev8bits(unsigned char v)
00157 {
00158   unsigned char r = v;
00159   int s = 7;
00160 
00161   for (v >>= 1; v; v >>= 1) {
00162     r <<= 1;
00163     r |= v & 1;
00164     s--;
00165   }
00166   r <<= s;                  /* Shift when v's highest bits are zero */
00167   return r;
00168 }
00169 /*---------------------------------------------------------------------------*/
00170 /* BEWARE: Bit reversed CRC8 using polynomial ^8 + ^5 + ^4 + 1 */
00171 static unsigned
00172 crc8_add(unsigned acc, unsigned byte)
00173 {
00174   int i;
00175   acc ^= byte;
00176   for(i = 0; i < 8; i++) {
00177     if(acc & 0x80) {
00178       acc = (acc << 1) ^ 0x31;
00179     } else {
00180       acc <<= 1;
00181     }
00182   }
00183   return acc & 0xff;
00184 }
00185 #endif /* CRC_CHECK */
00186 /*---------------------------------------------------------------------------*/
00187 /*
00188  * Power up the device. The device can be used after an additional
00189  * 11ms waiting time.
00190  */
00191 void
00192 sht11_init(void)
00193 {
00194   /*
00195    * SCL Output={0,1}
00196    * SDA 0: Output=0
00197    *     1: Input and pull-up (Output=0)
00198    */
00199   SHT11_PxOUT |= BV(SHT11_ARCH_PWR);
00200   SHT11_PxOUT &= ~(BV(SHT11_ARCH_SDA) | BV(SHT11_ARCH_SCL));
00201   SHT11_PxDIR |= BV(SHT11_ARCH_PWR) | BV(SHT11_ARCH_SCL);
00202 }
00203 /*---------------------------------------------------------------------------*/
00204 /*
00205  * Power of device.
00206  */
00207 void
00208 sht11_off(void)
00209 {
00210   SHT11_PxOUT &= ~BV(SHT11_ARCH_PWR);
00211   SHT11_PxOUT &= ~(BV(SHT11_ARCH_SDA) | BV(SHT11_ARCH_SCL));
00212   SHT11_PxDIR |= BV(SHT11_ARCH_PWR) | BV(SHT11_ARCH_SCL);
00213 }
00214 /*---------------------------------------------------------------------------*/
00215 /*
00216  * Only commands MEASURE_HUMI or MEASURE_TEMP!
00217  */
00218 static unsigned int
00219 scmd(unsigned cmd)
00220 {
00221   unsigned long n;
00222 
00223   if(cmd != MEASURE_HUMI && cmd != MEASURE_TEMP) {
00224     return -1;
00225   }
00226 
00227   sstart();                     /* Start transmission */
00228   if(!swrite(cmd)) {
00229     goto fail;
00230   }
00231 
00232   for(n = 0; n < 250000; n++) {
00233     if(!SDA_IS_1) {
00234       unsigned t0, t1, rcrc;
00235       t0 = sread(1);
00236       t1 = sread(1);
00237       rcrc = sread(0);
00238 #ifdef CRC_CHECK
00239       {
00240         unsigned crc;
00241         crc = crc8_add(0x0, cmd);
00242         crc = crc8_add(crc, t0);
00243         crc = crc8_add(crc, t1);
00244         if(crc != rev8bits(rcrc)) {
00245           goto fail;
00246         }
00247       }
00248 #endif
00249       return (t0 << 8) | t1;
00250     }
00251   }
00252 
00253  fail:
00254   sreset();
00255   return -1;
00256 }
00257 /*---------------------------------------------------------------------------*/
00258 /*
00259  * Call may take up to 210ms.
00260  */
00261 unsigned int
00262 sht11_temp(void)
00263 {
00264   return scmd(MEASURE_TEMP);
00265 }
00266 /*---------------------------------------------------------------------------*/
00267 /*
00268  * Call may take up to 210ms.
00269  */
00270 unsigned int
00271 sht11_humidity(void)
00272 {
00273   return scmd(MEASURE_HUMI);
00274 }
00275 /*---------------------------------------------------------------------------*/
00276 #if 1 /* But ok! */
00277 unsigned
00278 sht11_sreg(void)
00279 {
00280   unsigned sreg, rcrc;
00281 
00282   sstart();                     /* Start transmission */
00283   if(!swrite(STATUS_REG_R)) {
00284     goto fail;
00285   }
00286 
00287   sreg = sread(1);
00288   rcrc = sread(0);
00289 
00290 #ifdef CRC_CHECK
00291   {
00292     unsigned crc;
00293     crc = crc8_add(0x0, STATUS_REG_R);
00294     crc = crc8_add(crc, sreg);
00295     if (crc != rev8bits(rcrc))
00296       goto fail;
00297   }
00298 #endif
00299 
00300   return sreg;
00301 
00302  fail:
00303   sreset();
00304   return -1;
00305 }
00306 #endif
00307 /*---------------------------------------------------------------------------*/
00308 #if 0
00309 int
00310 sht11_set_sreg(unsigned sreg)
00311 {
00312   sstart();                     /* Start transmission */
00313   if(!swrite(STATUS_REG_W)) {
00314     goto fail;
00315   }
00316   if(!swrite(sreg)) {
00317     goto fail;
00318   }
00319 
00320   return 0;
00321 
00322  fail:
00323   sreset();
00324   return -1;
00325 }
00326 #endif
00327 /*---------------------------------------------------------------------------*/
00328 #if 0
00329 int
00330 sht11_reset(void)
00331 {
00332   sstart();                     /* Start transmission */
00333   if(!swrite(RESET)) {
00334     goto fail;
00335   }
00336 
00337   return 0;
00338 
00339  fail:
00340   sreset();
00341   return -1;
00342 }
00343 #endif
00344 /*---------------------------------------------------------------------------*/

Generated on Mon Apr 11 14:23:28 2011 for Contiki 2.5 by  doxygen 1.6.1