//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
}
}
|