[应用相关] STM32 读取温湿度传感器SHT11

[复制链接]
 楼主| wahahaheihei 发表于 2016-1-6 22:46 | 显示全部楼层 |阅读模式
  1. //Code for reading the SHT11 temeprature and humidity sensor with an STM ARM CORTEX-M3 MCU
  2. ////////////////////////////////////////////////////////////////////////////////////////
  3. /*
  4. The function read_temperature_and_humidity() reads the temperature and humidity and stores the data in XX.XX format
  5. */
  6. /***********************************************************************************************
  7. *          PORT DEFINITION
  8. ************************************************************************************************/
  9. #define DATA_WR  GPIOA, GPIO_Pin_6
  10. #define DATA_RD    GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)
  11. #define SCK     GPIOA, GPIO_Pin_7

  12. /*********************************************************************************************************
  13. *          LOCAL DEFINITIONS
  14. *********************************************************************************************************/
  15. //adr  command  r/w
  16. #define STATUS_REG_W  0x06   //000   0011    0
  17. #define STATUS_REG_R  0x07   //000   0011    1
  18. #define MEASURE_TEMP  0x03   //000   0001    1
  19. #define MEASURE_HUMI  0x05   //000   0010    1
  20. #define RESETa         0x1e   //000   1111    0
  21. #define noACK    0
  22. #define ACKa      1
  23. /*
  24. ***********************************************************************************************
  25. *          GLOBAL CONSTANTS
  26. ************************************************************************************************/
  27. enum {TEMP,HUMI};
  28. typedef union
  29. {
  30. uint16_t i;
  31. float f;
  32. } value;
  33. ////////////////////////////////////////////////////////////////////////////////////////
  34. //char temperature[15];
  35. //char humidity[15];
  36. int16_t  Real_Temperature;
  37. uint16_t Real_Humidity;
  38. int16_t  Temp_Hi_Limit;
  39. int16_t  Temp_Lo_Limit;
  40. uint16_t Humi_Hi_Limit;
  41. uint16_t Humi_Lo_Limit;
  42.    char Temp_Offset,Humi_Offset;
  43. unsigned char DataStatus;// 数据结果标志位  0000 1111   
  44.                                // 1:HumiLow HumidityHigh TempLow TempHigh
  45. void mikrosekund(int cas)
  46. {   
  47. int i; int j; //int k=0;
  48. for (i=0;i<cas;i++)
  49. {
  50.   for (j=0;j<1;j++)
  51.   {  
  52.   ;
  53.   ;
  54.   ;
  55.   }
  56. }
  57. }
  58. void datain(void)
  59. {
  60.   GPIO_InitTypeDef GPIO_InitStructure;
  61.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  62.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  63.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  64.     GPIO_Init(GPIOA, &GPIO_InitStructure);
  65. }
  66. void dataout(void)
  67. {
  68.   GPIO_InitTypeDef GPIO_InitStructure;
  69.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  70.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  71.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  72.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  73. }

  74. void sckout(void)
  75. {
  76.   GPIO_InitTypeDef GPIO_InitStructure;
  77.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  78.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  79.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  80.   GPIO_Init(GPIOA, &GPIO_InitStructure);
  81. }
  82. /***********************************************************************************************
  83. *         FUNCTION PROTOTYPES
  84. ***********************************************************************************************/
  85. char s_softreset(void);
  86. char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode);
  87. //char s_write_statusreg(unsigned char *p_value);
  88. //char s_read_statusreg(unsigned char *p_value, unsigned char *p_checksum);
  89. /*
  90. ***********************************************************************************************
  91. *         FUNCTION PROTOTYPES
  92. *          HARDWARE SPECIFIC
  93. ***********************************************************************************************
  94. */
  95. void s_transstart(void);
  96. void s_connectionreset(void);
  97. char s_read_byte(unsigned char ack);
  98. char s_write_byte(unsigned char value);

  99. /*
  100. *********************************************************************************************************
  101. *                             SOFT RESET THE SENSOR
  102. *
  103. * Description : Soft reset, resets the interface, clears the status register to default values
  104. *    Wait minimum 11 ms before next command
  105. * Arguments   : none
  106. *   
  107. * Returns     : 1 if no response from the sensor
  108. * Notes    :
  109. *********************************************************************************************************/
  110. char s_softreset(void)
  111. {
  112.   unsigned char error_bit=0;  
  113.   s_connection_reset();              //reset communication
  114.   error_bit+=s_write_byte(RESETa);       //send RESET-command to sensor
  115.   return error_bit;                     //error=1 in case of no response from the sensor
  116. }
  117. /*****************************************************************************************************
  118. *                   MAKE MEASUREMENT ON HUMIDITY AND TEMPERATURE IN 12BITS ADN 14BITS
  119. *
  120. * Description : Makes a measurement (humidity/temperature) with checksum
  121. * Arguments   :
  122. *   
  123. * Returns     :
  124. * Notes    : It takes approximately 11/55/210 ms for a 8/12/14bit measurement.
  125. *    Measurement data is stored until readout.
  126. *    Two bytes of measurement data and one byte of CRC checksum will then be transmitted.
  127. *    The uC must acknowledge each byte by pulling the DATA line low.
  128. *********************************************************************************************************/
  129. char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
  130. {
  131. unsigned error_bit=0;
  132. unsigned int i;

  133. s_transstart();                   //transmission start
  134. switch(mode)
  135. {                     //send command to sensor
  136.   case TEMP : error_bit+=s_write_byte(MEASURE_TEMP); break;
  137.   case HUMI : error_bit+=s_write_byte(MEASURE_HUMI); break;
  138.   default     : break;  
  139. }
  140. (mode==HUMI)?msDelay(55):msDelay(210);

  141. for (i=0;i<65535;i++) if(DATA_RD==0) break; //wait until sensor has finished the measurement
  142. if(DATA_RD) error_bit+=1;       //or timeout (~2 sec.) is reached

  143. *(p_value+1)  = s_read_byte(ACKa);     //read the first byte (MSB)
  144. *(p_value) = s_read_byte(ACKa);      //read the second byte (LSB)
  145. *p_checksum  = s_read_byte(noACK);    //read checksum

  146. return error_bit;
  147. }
  148. /*
  149. *********************************************************************************************************
  150. *                             TRANSMISSION START SEQUENCE
  151. *
  152. * Description : To initiate a transmission, a 揟ransmission Start?sequence has to be issued.
  153. * Arguments   : none
  154. *   
  155. * Returns     : none
  156. * Notes    :
  157. *      generates a transmission start
  158. *            _____         ________
  159. *      DATA:       |_______|
  160. *        ___     ___
  161. *      SCK : ___|   |___|   |______
  162. *********************************************************************************************************
  163. */
  164. void s_transstart(void)
  165. {  
  166.    GPIO_ResetBits(SCK); //SCK=0;                   //Initial state
  167.    datain();// DATA_TRIS = 1;   //pullup resistor brings DATA pin high
  168.    mikrosekund(1);
  169.    GPIO_SetBits(SCK); //SCK=1;
  170.    mikrosekund(1);
  171.    dataout(); GPIO_ResetBits(DATA_WR); //DATA_TRIS=0;   // DATA_WR=0; DATA_TRIS=0;
  172.    mikrosekund(1);
  173.    GPIO_ResetBits(SCK);//SCK=0;  
  174.    mikrosekund(5);
  175.    GPIO_SetBits(SCK);//SCK=1;
  176.    mikrosekund(1);
  177.    datain();// DATA_TRIS=1;       //pullup resistor brings DATA pin high
  178.    mikrosekund(1);
  179.    GPIO_ResetBits(SCK);//SCK=0;   
  180. }

  181. /*
  182. *********************************************************************************************************
  183. *                              CONNECTION RESET SEQUENCE
  184. *
  185. * Description : This sequence resets the interface only. The status register preserves its content.
  186. * Arguments   : none
  187. *   
  188. * Returns     : none
  189. * Notes    :
  190. *      communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
  191. *            _____________________________________________________         ________
  192. *     DATA:                                                  |_______|
  193. *               _    _    _    _    _    _    _    _    _        ___     ___
  194. *     SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
  195. *********************************************************************************************************
  196. */
  197. void s_connection_reset(void)
  198. {  
  199.   unsigned char i;
  200. dataout();//DATA_TRIS  = 0;    //set data pin an output
  201. GPIO_SetBits(DATA_WR); //DATA_WR     = 1;   //set data pin high
  202. sckout(); //SCK_TRIS = 0;   //set CLK pin an output low
  203. GPIO_ResetBits(SCK);// SCK   = 0;

  204.   for(i=0;i<9;i++)              //9 SCK cycles for connection reset sequence
  205.   { GPIO_SetBits(SCK);//SCK=1;
  206. mikrosekund(1);
  207.     GPIO_ResetBits(SCK);//SCK=0;
  208. mikrosekund(1);
  209.   }
  210.   s_transstart();             //transmission start
  211. }

  212. /*
  213. *********************************************************************************************************
  214. *                             LOW LEVEL READ FUNCTION
  215. *
  216. * Description : Read a byte form the Sensibus and gives an acknowledge in case of "ack == ACK"
  217. * Arguments   : 'ack'  ACK (1) if acknowledge required
  218. *      noACK (0) in case acknowledge NOT required
  219. *   
  220. * Returns     : return the byte read from the sensor
  221. * Notes    :
  222. *********************************************************************************************************
  223. */
  224. char s_read_byte(unsigned char ack)
  225. {
  226.   unsigned char i,val=0;
  227.   datain(); //DATA_TRIS = 1;                    //set DATA line an input
  228.   GPIO_ResetBits(SCK);//SCK = 0;
  229.   for (i=0x80;i>0;i/=2)             //shift bit for masking
  230.   { GPIO_SetBits(SCK);//SCK=1;                          //clk for SENSI-BUS
  231. mikrosekund(2);
  232.     if (DATA_RD) val=(val | i);        //read bit  
  233.     GPIO_ResetBits(SCK);//SCK=0;        
  234. mikrosekund(2);
  235.   }
  236. if(ack==ACKa)
  237. {
  238. dataout();// DATA_TRIS = 0;
  239.   GPIO_ResetBits(DATA_WR);//DATA_WR = 0;
  240. }
  241.    GPIO_SetBits(SCK);//SCK=1;                          //clk #9 for ack
  242. mikrosekund(5);      //pulse-width approx. 5 us         
  243.    GPIO_ResetBits(SCK);//SCK=0;         
  244.     datain();// DATA_TRIS = 1;                  //release DATA-line
  245.   return val;
  246. }
  247. /*
  248. *********************************************************************************************************
  249. *                             LOW LEVEL WRITE FUNCTION
  250. *
  251. * Description : Write a byte on the Sensibus and checks the acknowledge
  252. * Arguments   : 'value' is the byte to write to the sensor
  253. *   
  254. * Returns     : 1 in case of an error (no acknowledge) from the sensor
  255. * Notes    :
  256. *********************************************************************************************************
  257. */
  258. char s_write_byte(unsigned char value)
  259. {
  260.   unsigned char i,error_bit=0;
  261.   dataout();//DATA_TRIS = 0;
  262.   for (i=0x80;i>0;i/=2)                //shift bit for masking
  263.   {
  264.    if (i & value) GPIO_SetBits(DATA_WR);// DATA_WR=1;             //masking value with i , write to SENSI-BUS
  265.     else GPIO_ResetBits(DATA_WR); //DATA_WR=0;

  266. mikrosekund(5);   //add by idea
  267.                         
  268.     GPIO_SetBits(SCK);//SCK=1;                             //clk for SENSI-BUS
  269. mikrosekund(5);            //pulse-width approx. 5 us
  270.     GPIO_ResetBits(SCK);//SCK=0;
  271. mikrosekund(5);
  272.   }
  273.   datain();//DATA_TRIS=1;                             //release DATA-line, let SHT10 sensor controls DATA line
  274.   GPIO_SetBits(SCK);//SCK=1;                               //clk #9 for ack
  275.   error_bit=DATA_RD;                          //check ack (DATA will be pulled down by SHT11)
  276.   GPIO_ResetBits(SCK);//SCK=0;        
  277.   return error_bit;                        //error=1 in case of no acknowledge
  278. }

  279. ////////////////konec kode za branje temp
  280. void calc_sht1x(float *p_humidity ,float *p_temperature)
  281. // calculates temperature [癈] and humidity [%RH]
  282. // input :  humi [Ticks] (12 bit)
  283. //          temp [Ticks] (14 bit)
  284. // output:  humi [%RH]
  285. //          temp [deg Cel]
  286. { float rh=*p_humidity;                 // rh:      Humidity [Ticks] 12 Bit
  287.   float t=*p_temperature;               // t:       Temperature [Ticks] 14 Bit
  288.   float rh_lin;                         // rh_lin:  Humidity linear
  289.   float rh_true;                        // rh_true: Temperature compensated humidity
  290.   float t_C;                            // t_C   :  Temperature [癈]
  291.   t_C=t*0.01 - 40;                      //calc. temperature from ticks to [deg Cel]
  292.   rh_lin=0.0405*rh - 0.0000028*rh*rh - 4.0;      //calc. humidity from ticks to [%RH]
  293.   rh_true=(t_C-25)*(0.01+0.00008*rh)+rh_lin;     //calc. temperature compensated humidity [%RH]
  294.   if(rh_true>100)rh_true=100;           //cut if the value is outside of
  295.   if(rh_true<0.1)rh_true=0.1;           //the physical possible range
  296.   //if(t_C<0)t_C=0;//by idea
  297.   *p_temperature=t_C;                   //return temperature [deg Cel]
  298.   *p_humidity=rh_true;                  //return humidity[%RH]
  299. }
  300. void read_temperature_and_humidity(void)
  301. {
  302. value humi_val, temp_val;
  303. unsigned char error_bit, checksum;
  304. ////s_softreset();             //reset the SHT10 sensor

  305. msDelay(20);  // itcakam 20 mirko sekund, da se senzor umiri
  306. error_bit=0;
  307.     error_bit+=s_measure((unsigned char*)&humi_val.i,&checksum,HUMI);   //measure humidity
  308.     error_bit+=s_measure((unsigned char*)&temp_val.i,&checksum,TEMP);   //measure temperature
  309.     if(error_bit!=0)
  310. {
  311.    s_connection_reset(); //in case of an error: connection reset     
  312. }                 
  313.     else
  314. {
  315.        humi_val.f=(float)humi_val.i;        //converts integer to float
  316.        temp_val.f=(float)temp_val.i;        //converts integer to float
  317.      calc_sht1x(&humi_val.f,&temp_val.f);      //calculate humidity, temperature
  318.   //sprintf(temperature, "%f", temp_val.f,);
  319.   //sprintf(humidity, "%f", humi_val.f);
  320.   ////
  321.   Real_Temperature=(int16_t)(temp_val.f*10);
  322.   Real_Humidity=(uint16_t)(humi_val.f*10);      
  323.   // 温度
  324.   Real_Temperature=Real_Temperature+Temp_Offset;
  325.   wg=Real_Temperature%10;    // ge
  326.   ws=(Real_Temperature%100)/10;    // shi
  327.   wb=(Real_Temperature%1000)/100;  // Bai
  328.   
  329.   // 湿度
  330.   Real_Humidity=Real_Humidity+Humi_Offset;
  331.   if(Real_Humidity>990)Real_Humidity=990;
  332.   sg=Real_Humidity%10;   // ge
  333.   ss=(Real_Humidity%100)/10;    // shi
  334.   sb=(Real_Humidity%1000)/100;  // Bai
  335. }
  336. }


gejigeji521 发表于 2016-1-31 11:07 | 显示全部楼层
好东西,收藏了
 楼主| wahahaheihei 发表于 2016-2-14 11:01 | 显示全部楼层
温湿度传感器SHT11数据手册(中文)版.pdf (347.86 KB, 下载次数: 14)
您需要登录后才可以回帖 登录 | 注册

本版积分规则

231

主题

3196

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部

231

主题

3196

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部