打印
[应用相关]

STM32 读取温湿度传感器SHT11

[复制链接]
1896|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wahahaheihei|  楼主 | 2016-1-6 22:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//Code for reading the SHT11 temeprature and humidity sensor with an STM ARM CORTEX-M3 MCU 
////////////////////////////////////////////////////////////////////////////////////////
/*
The function read_temperature_and_humidity() reads the temperature and humidity and stores the data in XX.XX format
*/
/***********************************************************************************************
*          PORT DEFINITION
************************************************************************************************/
#define DATA_WR  GPIOA, GPIO_Pin_6
#define DATA_RD    GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)
#define SCK     GPIOA, GPIO_Pin_7

/*********************************************************************************************************
*          LOCAL DEFINITIONS
*********************************************************************************************************/
//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 RESETa         0x1e   //000   1111    0
#define noACK    0
#define ACKa      1
/*
***********************************************************************************************
*          GLOBAL CONSTANTS
************************************************************************************************/
enum {TEMP,HUMI};
typedef union
{
uint16_t i;
float f;
} value;
////////////////////////////////////////////////////////////////////////////////////////
//char temperature[15];
//char humidity[15];
int16_t  Real_Temperature;
uint16_t Real_Humidity;
int16_t  Temp_Hi_Limit;
int16_t  Temp_Lo_Limit;
uint16_t Humi_Hi_Limit;
uint16_t Humi_Lo_Limit;
   char Temp_Offset,Humi_Offset;
unsigned char DataStatus;// 数据结果标志位  0000 1111   
                               // 1:HumiLow HumidityHigh TempLow TempHigh
void mikrosekund(int cas)
{   
int i; int j; //int k=0;
for (i=0;i<cas;i++)
{
  for (j=0;j<1;j++)
  {  
  ;
  ;
  ;
  }
}
}
void datain(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void dataout(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void sckout(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/***********************************************************************************************
*         FUNCTION PROTOTYPES
***********************************************************************************************/
char s_softreset(void);
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode);
//char s_write_statusreg(unsigned char *p_value);
//char s_read_statusreg(unsigned char *p_value, unsigned char *p_checksum);
/*
***********************************************************************************************
*         FUNCTION PROTOTYPES
*          HARDWARE SPECIFIC
***********************************************************************************************
*/
void s_transstart(void);
void s_connectionreset(void);
char s_read_byte(unsigned char ack);
char s_write_byte(unsigned char value);

/*
*********************************************************************************************************
*                             SOFT RESET THE SENSOR
*
* Description : Soft reset, resets the interface, clears the status register to default values
*    Wait minimum 11 ms before next command
* Arguments   : none
*   
* Returns     : 1 if no response from the sensor
* Notes    :
*********************************************************************************************************/
char s_softreset(void)
{
  unsigned char error_bit=0;  
  s_connection_reset();              //reset communication
  error_bit+=s_write_byte(RESETa);       //send RESET-command to sensor
  return error_bit;                     //error=1 in case of no response from the sensor
}
/*****************************************************************************************************
*                   MAKE MEASUREMENT ON HUMIDITY AND TEMPERATURE IN 12BITS ADN 14BITS
*
* Description : Makes a measurement (humidity/temperature) with checksum
* Arguments   :
*   
* Returns     :
* Notes    : It takes approximately 11/55/210 ms for a 8/12/14bit measurement.
*    Measurement data is stored until readout.
*    Two bytes of measurement data and one byte of CRC checksum will then be transmitted.
*    The uC must acknowledge each byte by pulling the DATA line low.
*********************************************************************************************************/
char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
{
unsigned error_bit=0;
unsigned int i;

s_transstart();                   //transmission start
switch(mode)
{                     //send command to sensor
  case TEMP : error_bit+=s_write_byte(MEASURE_TEMP); break;
  case HUMI : error_bit+=s_write_byte(MEASURE_HUMI); break;
  default     : break;  
}
(mode==HUMI)?msDelay(55):msDelay(210);

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

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

return error_bit;
}
/*
*********************************************************************************************************
*                             TRANSMISSION START SEQUENCE
*
* Description : To initiate a transmission, a 揟ransmission Start?sequence has to be issued.
* Arguments   : none
*   
* Returns     : none
* Notes    :
*      generates a transmission start
*            _____         ________
*      DATA:       |_______|
*        ___     ___
*      SCK : ___|   |___|   |______
*********************************************************************************************************
*/
void s_transstart(void)
{  
   GPIO_ResetBits(SCK); //SCK=0;                   //Initial state
   datain();// DATA_TRIS = 1;   //pullup resistor brings DATA pin high
   mikrosekund(1);
   GPIO_SetBits(SCK); //SCK=1;
   mikrosekund(1);
   dataout(); GPIO_ResetBits(DATA_WR); //DATA_TRIS=0;   // DATA_WR=0; DATA_TRIS=0;
   mikrosekund(1);
   GPIO_ResetBits(SCK);//SCK=0;  
   mikrosekund(5);
   GPIO_SetBits(SCK);//SCK=1;
   mikrosekund(1);
   datain();// DATA_TRIS=1;       //pullup resistor brings DATA pin high
   mikrosekund(1);
   GPIO_ResetBits(SCK);//SCK=0;   
}

/*
*********************************************************************************************************
*                              CONNECTION RESET SEQUENCE
*
* Description : This sequence resets the interface only. The status register preserves its content.
* Arguments   : none
*   
* Returns     : none
* Notes    :
*      communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
*            _____________________________________________________         ________
*     DATA:                                                  |_______|
*               _    _    _    _    _    _    _    _    _        ___     ___
*     SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
*********************************************************************************************************
*/
void s_connection_reset(void)
{  
  unsigned char i;
dataout();//DATA_TRIS  = 0;    //set data pin an output
GPIO_SetBits(DATA_WR); //DATA_WR     = 1;   //set data pin high
sckout(); //SCK_TRIS = 0;   //set CLK pin an output low
GPIO_ResetBits(SCK);// SCK   = 0;

  for(i=0;i<9;i++)              //9 SCK cycles for connection reset sequence
  { GPIO_SetBits(SCK);//SCK=1;
mikrosekund(1);
    GPIO_ResetBits(SCK);//SCK=0;
mikrosekund(1);
  }
  s_transstart();             //transmission start
}

/*
*********************************************************************************************************
*                             LOW LEVEL READ FUNCTION
*
* Description : Read a byte form the Sensibus and gives an acknowledge in case of "ack == ACK"
* Arguments   : 'ack'  ACK (1) if acknowledge required
*      noACK (0) in case acknowledge NOT required
*   
* Returns     : return the byte read from the sensor
* Notes    :
*********************************************************************************************************
*/
char s_read_byte(unsigned char ack)
{
  unsigned char i,val=0;
  datain(); //DATA_TRIS = 1;                    //set DATA line an input
  GPIO_ResetBits(SCK);//SCK = 0;
  for (i=0x80;i>0;i/=2)             //shift bit for masking
  { GPIO_SetBits(SCK);//SCK=1;                          //clk for SENSI-BUS
mikrosekund(2);
    if (DATA_RD) val=(val | i);        //read bit  
    GPIO_ResetBits(SCK);//SCK=0;        
mikrosekund(2);
  }
if(ack==ACKa)
{
dataout();// DATA_TRIS = 0;
  GPIO_ResetBits(DATA_WR);//DATA_WR = 0;
}
   GPIO_SetBits(SCK);//SCK=1;                          //clk #9 for ack
mikrosekund(5);      //pulse-width approx. 5 us         
   GPIO_ResetBits(SCK);//SCK=0;         
    datain();// DATA_TRIS = 1;                  //release DATA-line
  return val;
}
/*
*********************************************************************************************************
*                             LOW LEVEL WRITE FUNCTION
*
* Description : Write a byte on the Sensibus and checks the acknowledge
* Arguments   : 'value' is the byte to write to the sensor
*   
* Returns     : 1 in case of an error (no acknowledge) from the sensor
* Notes    :
*********************************************************************************************************
*/
char s_write_byte(unsigned char value)
{
  unsigned char i,error_bit=0;
  dataout();//DATA_TRIS = 0;
  for (i=0x80;i>0;i/=2)                //shift bit for masking
  {
   if (i & value) GPIO_SetBits(DATA_WR);// DATA_WR=1;             //masking value with i , write to SENSI-BUS
    else GPIO_ResetBits(DATA_WR); //DATA_WR=0;

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

////////////////konec kode za branje temp
void calc_sht1x(float *p_humidity ,float *p_temperature)
// calculates temperature [癈] and humidity [%RH]
// input :  humi [Ticks] (12 bit)
//          temp [Ticks] (14 bit)
// output:  humi [%RH]
//          temp [deg Cel]
{ float rh=*p_humidity;                 // rh:      Humidity [Ticks] 12 Bit
  float t=*p_temperature;               // t:       Temperature [Ticks] 14 Bit
  float rh_lin;                         // rh_lin:  Humidity linear
  float rh_true;                        // rh_true: Temperature compensated humidity
  float t_C;                            // t_C   :  Temperature [癈]
  t_C=t*0.01 - 40;                      //calc. temperature from ticks to [deg Cel]
  rh_lin=0.0405*rh - 0.0000028*rh*rh - 4.0;      //calc. humidity from ticks to [%RH]
  rh_true=(t_C-25)*(0.01+0.00008*rh)+rh_lin;     //calc. temperature compensated humidity [%RH]
  if(rh_true>100)rh_true=100;           //cut if the value is outside of
  if(rh_true<0.1)rh_true=0.1;           //the physical possible range
  //if(t_C<0)t_C=0;//by idea
  *p_temperature=t_C;                   //return temperature [deg Cel]
  *p_humidity=rh_true;                  //return humidity[%RH]
}
void read_temperature_and_humidity(void)
{
value humi_val, temp_val;
unsigned char error_bit, checksum;
////s_softreset();             //reset the SHT10 sensor

msDelay(20);  // itcakam 20 mirko sekund, da se senzor umiri
error_bit=0;
    error_bit+=s_measure((unsigned char*)&humi_val.i,&checksum,HUMI);   //measure humidity
    error_bit+=s_measure((unsigned char*)&temp_val.i,&checksum,TEMP);   //measure temperature
    if(error_bit!=0)
{
   s_connection_reset(); //in case of an error: connection reset     
}                 
    else
{
       humi_val.f=(float)humi_val.i;        //converts integer to float
       temp_val.f=(float)temp_val.i;        //converts integer to float
     calc_sht1x(&humi_val.f,&temp_val.f);      //calculate humidity, temperature
  //sprintf(temperature, "%f", temp_val.f,);
  //sprintf(humidity, "%f", humi_val.f);
  ////
  Real_Temperature=(int16_t)(temp_val.f*10);
  Real_Humidity=(uint16_t)(humi_val.f*10);      
  // 温度
  Real_Temperature=Real_Temperature+Temp_Offset;
  wg=Real_Temperature%10;    // ge
  ws=(Real_Temperature%100)/10;    // shi
  wb=(Real_Temperature%1000)/100;  // Bai
  
  // 湿度
  Real_Humidity=Real_Humidity+Humi_Offset;
  if(Real_Humidity>990)Real_Humidity=990;
  sg=Real_Humidity%10;   // ge
  ss=(Real_Humidity%100)/10;    // shi
  sb=(Real_Humidity%1000)/100;  // Bai
}
}


沙发
gejigeji521| | 2016-1-31 11:07 | 只看该作者
好东西,收藏了

使用特权

评论回复
板凳
wahahaheihei|  楼主 | 2016-2-14 11:01 | 只看该作者
温湿度传感器SHT11数据手册(中文)版.pdf (347.86 KB)

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

217

主题

3042

帖子

12

粉丝