sht.c


1
// Sensirion SHT Sensor
2
#include <io430.h>
3
#include <intrinsics.h>
4
#include "sht.h"
5
#include "delay.h"
6
7
#define SHTDIR P5DIR
8
#define SHTOUT P5OUT
9
#define SHTIN P5IN
10
11
#define PIN_CLK 0x40
12
#define PIN_DAT 0x80
13
14
#define SHT_CMD_TEMP    0x03
15
#define SHT_CMD_HUMID   0x05
16
#define SHT_CMD_WR_STAT 0x06
17
#define SHT_CMD_RD_STAT 0x07
18
#define SHT_CMD_RESET   0x1E
19
20
#define SHT_VOLTAGE_COMPENSATION_D1_5V   -40.1
21
#define SHT_VOLTAGE_COMPENSATION_D1_4V   -39.8
22
#define SHT_VOLTAGE_COMPENSATION_D1_3_5V -39.7
23
#define SHT_VOLTAGE_COMPENSATION_D1_3_3V -39.7
24
#define SHT_VOLTAGE_COMPENSATION_D1_3V   -39.6
25
#define SHT_VOLTAGE_COMPENSATION_D1_2_5V -39.4
26
27
#define SHT_VOLTAGE_COMPENSATION_D1 SHT_VOLTAGE_COMPENSATION_D1_3_3V
28
29
#define NOP __no_operation()
30
31
inline static char sht_getdat(void)
32
{
33
  NOP;
34
  return (SHTIN&PIN_DAT);
35
}
36
37
inline static void sht_setdat(unsigned char c)
38
{
39
  if (c) SHTDIR&=~PIN_DAT; // bei 1 Pullup wirken lassen
40
  else   SHTDIR|=PIN_DAT;  // ansonsten auf Ausgang schalten,
41
                           // wo eine 0 ausgegeben wird
42
  NOP;
43
}
44
45
inline static void sht_clkhi(void)
46
{
47
  SHTOUT|=PIN_CLK;
48
  NOP;
49
}
50
51
inline static void sht_clklo(void)
52
{
53
  SHTOUT&=~PIN_CLK;
54
  NOP;
55
}
56
57
void sht_init(void)
58
{
59
  SHTDIR|=PIN_CLK;
60
  SHTDIR&=~PIN_DAT;
61
  SHTOUT&=~(PIN_CLK|PIN_DAT);
62
  delayms(50); // Power Up Delay
63
}
64
65
static void sht_start(void)
66
{
67
  int i;
68
  sht_setdat(1);
69
  for (i=0;i<10;i++)
70
  {
71
    sht_clkhi();
72
    sht_clklo();
73
  }
74
  sht_clkhi();
75
  sht_setdat(0);
76
  sht_clklo();
77
  sht_clkhi();
78
  sht_setdat(1);
79
  sht_clklo();
80
}
81
82
static void sht_sendbyte(unsigned char c)
83
{
84
  int i;
85
  // Datenbits rausschieben
86
  for (i=8;i>0;--i)
87
  {
88
    sht_setdat(c&0x80);
89
    sht_clkhi();
90
    sht_clklo();
91
    c<<=1;
92
  }
93
  // Ack empfangen
94
  sht_setdat(1);
95
  sht_clkhi();
96
  sht_clklo();
97
//  while(sht_getdat());
98
}
99
100
static unsigned char sht_recvbyte_msb(unsigned char a)
101
{
102
  int i;
103
  unsigned char c;
104
  sht_setdat(1);
105
  // Datenbits reinschieben
106
  for (i=8;i>0;--i)
107
  {
108
    c<<=1;
109
    sht_clkhi();
110
    if (sht_getdat()) c|=1;
111
    sht_clklo();
112
  }
113
  // Ack senden
114
  sht_setdat(a);
115
  sht_clkhi();
116
  sht_clklo();
117
  sht_setdat(1);
118
  return c;
119
}
120
121
static unsigned char sht_recvbyte_lsb(unsigned char a)
122
{
123
  int i;
124
  unsigned char c;
125
  sht_setdat(1);
126
  // Datenbits reinschieben
127
  for (i=8;i>0;--i)
128
  {
129
    c>>=1;
130
    sht_clkhi();
131
    if (sht_getdat()) c|=128;
132
    sht_clklo();
133
  }
134
  // Ack senden
135
  sht_setdat(a);
136
  sht_clkhi();
137
  sht_clklo();
138
  sht_setdat(1);
139
  return c;
140
}
141
142
static unsigned char sht_crc(unsigned char crc, unsigned char data)
143
{
144
  static const unsigned char crctab[]={
145
      0, 49, 98, 83,196,245,166,151,185,136,219,234,125, 76, 31, 46,
146
     67,114, 33, 16,135,182,229,212,250,203,152,169, 62, 15, 92,109,
147
    134,183,228,213, 66,115, 32, 17, 63, 14, 93,108,251,202,153,168,
148
    197,244,167,150,  1, 48, 99, 82,124, 77, 30, 47,184,137,218,235,
149
     61, 12, 95,110,249,200,155,170,132,181,230,215, 64,113, 34, 19,
150
    126, 79, 28, 45,186,139,216,233,199,246,165,148,  3, 50, 97, 80,
151
    187,138,217,232,127, 78, 29, 44,  2, 51, 96, 81,198,247,164,149,
152
    248,201,154,171, 60, 13, 94,111, 65,112, 35, 18,133,180,231,214,
153
    122, 75, 24, 41,190,143,220,237,195,242,161,144,  7, 54,101, 84,
154
     57,  8, 91,106,253,204,159,174,128,177,226,211, 68,117, 38, 23,
155
    252,205,158,175, 56,  9, 90,107, 69,116, 39, 22,129,176,227,210,
156
    191,142,221,236,123, 74, 25, 40,  6, 55,100, 85,194,243,160,145,
157
     71,118, 37, 20,131,178,225,208,254,207,156,173, 58, 11, 88,105,
158
      4, 53,102, 87,192,241,162,147,189,140,223,238,121, 72, 27, 42,
159
    193,240,163,146,  5, 52,103, 86,120, 73, 26, 43,188,141,222,239,
160
    130,179,224,209, 70,119, 36, 21, 59, 10, 89,104,255,206,157,172
161
  };
162
163
  return crctab[crc^data];
164
}
165
166
unsigned short sht_measure(char is_rh)
167
{
168
  int i;
169
  unsigned short s;
170
  unsigned char cmd,ch,cl,crc;
171
  unsigned char mycrc;
172
173
  sht_start();
174
  if (is_rh) cmd=SHT_CMD_HUMID;
175
  else       cmd=SHT_CMD_TEMP;
176
  sht_sendbyte(cmd);
177
  delayms(5);
178
  sht_setdat(1);
179
  for (i=0;i<1024;i++)
180
  {
181
    if(sht_getdat()==0) break;
182
    delayms(5);
183
  }
184
  if (sht_getdat()) return 0xfffe;
185
186
  ch=sht_recvbyte_msb(0);
187
  cl=sht_recvbyte_msb(0);
188
  crc=sht_recvbyte_lsb(1);
189
  s=((unsigned short)ch<<8)+(unsigned short)cl;
190
  mycrc=sht_crc(0,cmd);
191
  mycrc=sht_crc(mycrc,ch);
192
  mycrc=sht_crc(mycrc,cl);
193
  if (mycrc!=crc) s=0xffff;
194
195
  return s;
196
}
197
198
// temp is returned in two-digit fixedpoint (celsius*100)
199
short sht_convert_temp(unsigned short raw_temp)
200
{
201
  return ((short)raw_temp+(((short)SHT_VOLTAGE_COMPENSATION_D1)*100));
202
}
203
204
// humidity is returned in one-digit fixedpoint (RH percent*10)
205
unsigned short sht_convert_humid(unsigned short raw_temp,unsigned short raw_humid)
206
{
207
  unsigned long humid;
208
209
  /**** first step: relative humidity ****/
210
211
  // constants from datasheet (values for V4 sensors), shifted and adapted
212
  const unsigned long c1 = (unsigned long)((2.0468 * 100 * (1L<<18))+0.5);
213
  const unsigned long c2 = (unsigned long)((0.0367 * 100 * (1L<<18))+0.5);
214
  const unsigned long c3 = (unsigned long)((1.5955e-6 * 100 * (1L<<27))+0.5);
215
216
  // uncompensated = c2*raw - (c3 * raw * raw) - c1
217
  humid = (c2 * (unsigned long)raw_humid) \
218
        - (((((unsigned long)raw_humid * (unsigned long)raw_humid) >> 7) * c3) >> 2) \
219
        - c1;
220
221
  // humid >> 18 would now be the uncompensated humidity in RH% * 100
222
223
  /**** second step: temperature compensation ****/
224
225
  // constants from datasheet, shifted and adapted
226
  const long t1 = (long)((0.01 * 100 * (1L<<18))+0.5);
227
  const long t2 = (long)((0.00008 * 100 * (1L<<18))+0.5);
228
229
  // humid += (temp-25) * (t1 + t2*raw_temp)
230
  humid += (long)((sht_convert_temp(raw_temp)/100)-25) \
231
           * (t1 + (t2 * (long)raw_humid));
232
233
  // humid >> 18 now is the real humidity in RH% * 100
234
235
  // shift it back and round to RH% * 10
236
  // (the sensor doesn't really provide enough accuracy to justify more resolution)
237
  return (unsigned short)(((humid >> 18)+5)/10);
238
}