?»??»?/********************************************* This program was produced by the CodeWizardAVR V1.23.8c Standard Automatic Program Generator ?Copyright 1998-2003 HP InfoTech s.r.l. http://www.hpinfotech.ro e-mail:office@hpinfotech.ro Project : The Sensirion SHT11 Humidity & Temperature Demo Version : 1.000 Date : 22/08/2003 Author : Wayne Peacock Company : Embedtronics Go to www.embedtronics.com for more information www.sensirion.com for sensor datasheet Disclaimer: The Author takes no responsibility for the use of this code. Use at your own risk! This code or part there of is licensed only for private use and NOT for commercial use. Parts of this code Copyright MST (c) Sensirion AG Chip type : AT90S8535 Clock frequency : 4.000000 MHz Memory model : Small External SRAM size : 0 Data Stack size : 192 SHT1X Humidity and Temperature Sensor AVR Pin 1 GND Pin 2 Data (PB0) Pin 3 Serial Clock (PB1) Pin 4 VDD (2.4V to 5.5V) AVR PB2 - Heater On/Off Switch Pin PB2 high - Heater On Pin PB2 low - Heater Off *********************************************/ #include <90s8535.h> #include #include #include // Alphanumeric LCD Module functions #asm .equ __lcd_port=0x1B #endasm #include // Declare your global variables here typedef union { unsigned int i; float f;} value; enum {TEMP,HUMI}; sfrb PINB = 0x16; sfrb PORTB = 0x18; sfrb DDRB = 0x17; #define SHT_DATA_OUT DDRB.0 #define SHT_DATA_IN PINB.0 #define SHT_SCK PORTB.1 #define HEAT_SW PINB.2 // Heater On or Off #define noACK 0 #define ACK 1 //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 RESET 0x1e //000 1111 0 const float C1=-4.0; // for 12 Bit const float C2=+0.0405; // for 12 Bit const float C3=-0.0000028; // for 12 Bit const float T1=+0.01; // for 14 Bit @ 5V const float T2=+0.00008; // for 14 Bit @ 5V typedef struct{ unsigned char second; //enter the current time, date, month, and year unsigned char minute; unsigned char hour; unsigned char date; unsigned char month; unsigned int year; }time; time t; char lcd_buffer[33]; // Function Prototypes interrupt [TIM2_OVF] void timer2_ovf_isr(void); char not_leap(void); //SHT Functions char SHT_WriteByte(unsigned char value); char SHT_ReadByte(unsigned char ack); void s_transstart(void); void s_connectionreset(void); char s_softreset(void); char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode); void calc_sth11(float *p_humidity ,float *p_temperature); float calc_dewpoint(float h,float t); char s_write_statusreg(unsigned char *p_value); char s_read_statusreg(unsigned char *p_value, unsigned char *p_checksum); void main(void) { // Declare your local variables here value humi_val, temp_val; unsigned char error, checksum, status; float dew_point; t.hour = 23; t.minute = 30; t.second = 00; t.date = 22; t.month = 8; t.year = 2003; // Input/Output Ports initialization // Port A initialization // Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In Func7=In // State0=T State1=T State2=T State3=T State4=T State5=T State6=T State7=T PORTA=0x00; DDRA=0x00; // Port B initialization // Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In Func7=In // State0=T State1=T State2=T State3=T State4=T State5=T State6=T State7=T PORTB=0x00; DDRB=0x00; // Port C initialization // Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In Func7=In // State0=T State1=T State2=T State3=T State4=T State5=T State6=T State7=T PORTC=0x00; DDRC=0x00; // Port D initialization // Func0=In Func1=In Func2=In Func3=In Func4=In Func5=Out Func6=In Func7=In // State0=T State1=T State2=T State3=T State4=T State5=0 State6=T State7=T PORTD=0x00; DDRD=0x20; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped TCCR0=0x00; TCNT0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer 1 Stopped // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: TOSC1 pin // Clock value: PCK2/128 // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x08; TCCR2=0x05; TCNT2=0x00; OCR2=0x00; // External Interrupt(s) initialization // INT0: Off // INT1: Off GIMSK=0x00; MCUCR=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x40; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off // Analog Comparator Output: Off ACSR=0x80; // LCD module initialization lcd_init(20); lcd_putsf("- SHT11 Monitor -"); //sprintf(lcd_buffer,"No. of Visitors = %d",visitor); //lcd_gotoxy(0,2); //lcd_puts(lcd_buffer); // Setup Sensibus Pins PORTB.1 = 0; // ClockLow DDRB.1 = 1; // SCK is an output PORTB.0 = 0; // Always Zero // Toggle DDRB.0 for Data s_connectionreset(); /* while (1) { s_transstart(); //transmission start error+=SHT_WriteByte(MEASURE_TEMP); //send command to sensor for (i=0;i<65535;i++) if(SHT_DATA_IN==0) break; //wait until sensor has finished the measurement if(SHT_DATA_IN) error+=1; //or timeout (~2 sec.) is reached MSB =SHT_ReadByte(ACK); //read the first byte (MSB) LSB =SHT_ReadByte(ACK); //read the second byte (LSB) checksum =SHT_ReadByte(noACK); //read checksum sprintf(lcd_buffer,"T= %u %u %u",MSB,LSB,checksum); lcd_gotoxy(0,1); lcd_puts(lcd_buffer); delay_ms(500); } */ while (1) { error=0; // Check heater pin if(HEAT_SW) status = 0b00000100; // Heater On else status = 0b00000000; // Heater Off s_write_statusreg(&status); error+=s_measure((unsigned char*) &humi_val.i,&checksum,HUMI); error+=s_measure((unsigned char*) &temp_val.i,&checksum,TEMP); if(error!=0) s_connectionreset(); else{ humi_val.f=(float)humi_val.i; //converts integer to float temp_val.f=(float)temp_val.i; //converts integer to float calc_sth11(&humi_val.f,&temp_val.f); //calculate humidity, temperature dew_point=calc_dewpoint(humi_val.f,temp_val.f); //calculate dew point sprintf(lcd_buffer,"T:%5.1fC H:%5.1f%%",temp_val.f,humi_val.f); lcd_gotoxy(0,1); lcd_puts(lcd_buffer); if (HEAT_SW) sprintf(lcd_buffer,"DP:%5.1fC Heat On ",dew_point); else sprintf(lcd_buffer,"DP:%5.1fC Heat Off ",dew_point); lcd_gotoxy(0,2); lcd_puts(lcd_buffer); } // Global enable interrupts #asm("sei") delay_ms(1000); #asm("cli") } } // Timer 2 overflow interrupt service routine interrupt [TIM2_OVF] void timer2_ovf_isr(void) { // Place your code here if (++t.second==60) //keep track of time, date, month, and year { t.second=0; if (++t.minute==60) { t.minute=0; if (++t.hour==24) { t.hour=0; if (++t.date==32) { t.month++; t.date=1; } else if (t.date==31) { if ((t.month==4) || (t.month==6) || (t.month==9) || (t.month==11)) { t.month++; t.date=1; } } else if (t.date==30) { if(t.month==2) { t.month++; t.date=1; } } else if (t.date==29) { if((t.month==2) && (not_leap())) { t.month++; t.date=1; } } if (t.month==13) { t.month=1; t.year++; } } } } sprintf(lcd_buffer,"%02d:%02d:%02d %02d/%02d/%04d",t.hour, t.minute, t.second, t.date, t.month, t.year); lcd_gotoxy(0,3); lcd_puts(lcd_buffer); } char not_leap(void) //check for leap year { if (!(t.year%100)) return (char)(t.year%400); else return (char)(t.year%4); } //---------------------------------------------------------------------------------- // writes a byte on the Sensibus and checks the acknowledge //---------------------------------------------------------------------------------- char SHT_WriteByte(unsigned char value) { unsigned char i,error=0; for (i=0x80;i>0;i/=2) //shift bit for masking { if (i & value) SHT_DATA_OUT=0; //masking value with i , write to SENSI-BUS else SHT_DATA_OUT=1; SHT_SCK=1; //clk for SENSI-BUS delay_us(5); //pulswith approx. 5 us SHT_SCK=0; } SHT_DATA_OUT=0; //release DATA-line SHT_SCK=1; //clk #9 for ack error=SHT_DATA_IN; //check ack (DATA will be pulled down by SHT11) SHT_SCK=0; return error; //error=1 in case of no acknowledge } //---------------------------------------------------------------------------------- // reads a byte form the Sensibus and gives an acknowledge in case of "ack=1" //---------------------------------------------------------------------------------- char SHT_ReadByte(unsigned char ack) { unsigned char i,val=0; SHT_DATA_OUT=0; //release DATA-line for (i=0x80;i>0;i/=2) //shift bit for masking { SHT_SCK=1; //clk for SENSI-BUS if (SHT_DATA_IN) val=(val | i); //read bit SHT_SCK=0; } SHT_DATA_OUT=ack; //in case of "ack==1" pull down DATA-Line SHT_SCK=1; //clk #9 for ack delay_us(5); //pulswith approx. 5 us SHT_SCK=0; SHT_DATA_OUT=0; //release DATA-line return val; } //---------------------------------------------------------------------------------- // generates a transmission start // _____ ________ // DATA: |_______| // ___ ___ // SCK : ___| |___| |______ //---------------------------------------------------------------------------------- void s_transstart(void) { SHT_DATA_OUT=0; SHT_SCK=0; //Initial state delay_us(1); SHT_SCK=1; delay_us(1); SHT_DATA_OUT=1; delay_us(1); SHT_SCK=0; delay_us(5); SHT_SCK=1; delay_us(1); SHT_DATA_OUT=0; delay_us(1); SHT_SCK=0; } //---------------------------------------------------------------------------------- // communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart // _____________________________________________________ ________ // DATA: |_______| // _ _ _ _ _ _ _ _ _ ___ ___ // SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |______ //---------------------------------------------------------------------------------- void s_connectionreset(void) { unsigned char i; SHT_DATA_OUT=0; SHT_SCK=0; //Initial state for(i=0;i<9;i++) //9 SCK cycles { SHT_SCK=1; delay_us(1); SHT_SCK=0; } s_transstart(); //transmission start } //---------------------------------------------------------------------------------- // resets the sensor by a softreset //---------------------------------------------------------------------------------- char s_softreset(void) { unsigned char error=0; s_connectionreset(); //reset communication error+=SHT_WriteByte(RESET); //send RESET-command to sensor return error; //error=1 in case of no response form the sensor } //---------------------------------------------------------------------------------- // makes a measurement (humidity/temperature) with checksum //---------------------------------------------------------------------------------- char s_measure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode) { unsigned error=0; unsigned int i; s_transstart(); //transmission start switch(mode){ //send command to sensor case TEMP : error+=SHT_WriteByte(MEASURE_TEMP); break; case HUMI : error+=SHT_WriteByte(MEASURE_HUMI); break; default : break; } for (i=0;i<65535;i++) if(SHT_DATA_IN==0) break; //wait until sensor has finished the measurement if(SHT_DATA_IN) error+=1; // or timeout (~2 sec.) is reached *(p_value+1) =SHT_ReadByte(ACK); //read the first byte (MSB) *(p_value) =SHT_ReadByte(ACK); //read the second byte (LSB) *p_checksum =SHT_ReadByte(noACK); //read checksum return error; } //---------------------------------------------------------------------------------------- // calculates temperature [°C] and humidity [%RH] // input : humi [Ticks] (12 bit) // temp [Ticks] (14 bit) // output: humi [%RH] // temp [°C] //---------------------------------------------------------------------------------------- void calc_sth11(float *p_humidity ,float *p_temperature) { //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 [°C] t_C=*p_temperature*0.01 - 40; //calc. temperature from ticks to [°C] rh_lin=C3*(*p_humidity)*(*p_humidity) + C2*(*p_humidity) + C1; //calc. humidity from ticks to [%RH] rh_true=(t_C-25)*(T1+T2*(*p_humidity))+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 *p_temperature=t_C; //return temperature [°C] *p_humidity=rh_true; //return humidity[%RH] } //-------------------------------------------------------------------- // calculates dew point // input: humidity [%RH], temperature [°C] // output: dew point [°C] //-------------------------------------------------------------------- float calc_dewpoint(float h,float t) { float logEx,dew_point; logEx=0.66077+7.5*t/(237.3+t)+(log10(h)-2); dew_point = (logEx - 0.66077)*237.3/(0.66077+7.5-logEx); return dew_point; } //---------------------------------------------------------------------------------- // reads the status register with checksum (8-bit) //---------------------------------------------------------------------------------- char s_read_statusreg(unsigned char *p_value, unsigned char *p_checksum) { unsigned char error=0; s_transstart(); //transmission start error=SHT_WriteByte(STATUS_REG_R); //send command to sensor *p_value=SHT_ReadByte(ACK); //read status register (8-bit) *p_checksum=SHT_ReadByte(noACK); //read checksum (8-bit) return error; //error=1 in case of no response form the sensor } //---------------------------------------------------------------------------------- // writes the status register with checksum (8-bit) //---------------------------------------------------------------------------------- char s_write_statusreg(unsigned char *p_value) { unsigned char error=0; s_transstart(); //transmission start error+=SHT_WriteByte(STATUS_REG_W);//send command to sensor error+=SHT_WriteByte(*p_value); //send value of status register return error; //error>=1 in case of no response form the sensor }