วันพฤหัสบดีที่ 17 พฤศจิกายน พ.ศ. 2554

การเชื่อมต่อ PIC16F877 กับ SHT11


/*
Program : Read SHT11
Author  : Somlak Mangnimit
Date    : 16/11/2011
Device  : PIC16F877 @20Mhz
*/

#include <htc.h>
#include <math.h>
#include <stdio.h>

#define _XTAL_FREQ 20000000

__CONFIG(FOSC_HS & WDTE_OFF & LVP_OFF);

#include "clcd.c"

#define SHT_SCK             PORTBbits.RB4
#define SHT_DATA            PORTBbits.RB5

#define SHT_SCK_DDR         TRISBbits.TRISB4
#define SHT_DATA_DDR        TRISBbits.TRISB5

#define SHT_SCK_LOW()       SHT_SCK_DDR=0; SHT_SCK=0;
#define SHT_SCK_HIGH()      SHT_SCK_DDR=0; SHT_SCK=1;

#define SHT_DATA_LOW()      SHT_DATA_DDR=0; SHT_DATA=0;
#define SHT_DATA_HIGH()     SHT_DATA_DDR=0; SHT_DATA=1;
#define SHT_DATA_FLOAT()    SHT_DATA_DDR=1; SHT_DATA=0;

//SHT1x address=000 is currently supported
//SHT1x command code
                                    //adr  command  r/w
#define SHT_STATUS_REG_W    0x06    //000   0011    0
#define SHT_STATUS_REG_R    0x07    //000   0011    1
#define SHT_MEASURE_TEMP    0x03    //000   0001    1
#define SHT_MEASURE_HUMI    0x05    //000   0010    1
#define SHT_RESET           0x1e    //000   1111    0

//constant use for SHT1x Humidity Measurement
#define C1  -4.0
#define C2  +0.0405
#define C3  -0.0000028

//constant use for SHT1x Temperature Measurement
#define D1  -40.0
#define D2  +0.01

//constant use for SHT1x True Humidity Measurement
#define T1  +0.01
#define T2  +0.00008

//-----------
//delay usec
//-----------
void delay_us(unsigned int us){
while(--us){__delay_us(1);}
}

//-----------
//delay msec
//-----------
void delay_ms(unsigned int ms){
while(--ms){__delay_ms(1);}
}

//-----------------------------------
//SHT1x Transmission Start condition
//-----------------------------------
void SHTStart(void){
SHT_DATA_HIGH();                    //Initial state
SHT_SCK_LOW();
delay_us(2);
SHT_SCK_HIGH();
delay_us(1);
SHT_DATA_LOW();
delay_us(1);
SHT_SCK_LOW();
delay_us(2);
SHT_SCK_HIGH();
delay_us(1);
SHT_DATA_HIGH();
delay_us(1);
SHT_SCK_LOW();
}

//-----------------------
//SHT1x Connection Reset
//-----------------------
void SHTConReset(void){
unsigned char i;
SHT_DATA_HIGH();
SHT_SCK_LOW();
delay_us(2);
    for(i=0;i<9;i++){               //9 SCK cycles
        SHT_SCK_HIGH();
        delay_us(2);
        SHT_SCK_LOW();
        delay_us(2);
    }
SHTStart();
delay_ms(250);
}

//----------------------------------------------
//SHT1x Address & Command Mode with address=000
//----------------------------------------------
unsigned char SHTWrite(unsigned char Data){
unsigned char i;
    for (i=0x80;i>0;i/=2){                  //shift bit for masking data
        delay_us(1);
        if(i&Data){SHT_DATA_HIGH();}
        else{SHT_DATA_LOW();}
        delay_us(1);                        //Snend Clock each bit
        SHT_SCK_HIGH();
        delay_us(2);
        SHT_SCK_LOW();
    }
SHT_DATA_FLOAT();     //Change DATA Line to Input
delay_us(2);
SHT_SCK_HIGH();       //Clock for Acknowledge
delay_us(2);
i = SHT_DATA;         //Get Acknowledge
SHT_SCK_LOW();
delay_ms(250);
return(i);
}

//---------------------
//Read data from SHT1x
//---------------------
long SHTRead(void){
long lTmp,lValue,lVal1=0,lVal2=0;
unsigned char i;
//get MSB from SHT1x
SHT_DATA_FLOAT();               //Change to Input
    for(i=0;i<8;i++){
        lVal1<<=1;
        delay_us(1);
        SHT_SCK_HIGH();         //Send Clock Hight
        delay_us(1);
        lTmp = SHT_DATA;        //Read Data Bit
        delay_us(1);
        SHT_SCK_LOW();          //Send Clock Low
        delay_us(1);
        if(lTmp){lVal1|=1;}     //store in lVal1
    }

//Acknowledge for Next byte
SHT_DATA_LOW();
delay_us(1);
SHT_SCK_HIGH();
delay_us(2);
SHT_SCK_LOW();
delay_us(1);

//get LSB from SHT1x
SHT_DATA_FLOAT();               //Change to Input
    for(i=0;i<8;i++){
        lVal2<<=1;
        delay_us(1);
        SHT_SCK_HIGH();         //Send Clock Hight
        delay_us(1);
        lTmp = SHT_DATA;        //Read Data Bit
        delay_us(1);
        SHT_SCK_LOW();          //Send Clock Low
        delay_us(1);
        if(lTmp){lVal2|=1;}     //store in lVal2
    }

//noAcknowledge
SHT_DATA_HIGH();
delay_us(1);
SHT_SCK_HIGH();
delay_us(2);
SHT_SCK_LOW();

//Makes a 16 bit number out of two 8 bit numbers.
lValue = (unsigned int)(lVal1&0xff)*0x100+(lVal2&0xff);
return(lValue);
}

//-------------------------------------------------------------------
//SHT1x Soft Reset
//resets the interface, clears the status register to default values
//wait minimum 11ms before next command
//-------------------------------------------------------------------
void SHTSoftReset(void){
SHTConReset();
SHTWrite(SHT_RESET);
}


unsigned char buffer[20];
void clr_buffer(void){
char x;
for(x=0;x<20;x++){buffer[x]=0x20;}
}

//-------------
//Main Program
//-------------
void main(void){
long lValue_rh,lValue_temp,Status_reg;
float fRh_lin,fRh_true,fTemp_true,fDew_point,fLogEW;
unsigned char ER;

TRISB = 0b11110000;
TRISC = 0b11111000;

SHTConReset();
lcd_init();

SHTStart();
SHTWrite(SHT_STATUS_REG_R);
Status_reg = SHTRead();
Status_reg = (int)Status_reg;

if((Status_reg&0x007)!=0){
SHTStart();
SHTWrite(SHT_STATUS_REG_W);
SHTWrite(0x00);
}

delay_ms(12);

    while(1){
        SHTStart();                             //start transmission
        ER = SHTWrite(SHT_MEASURE_TEMP);        //measure temperature
            if(ER==1){
                lcd_write_command(0x01);
                lcd_gotoxy(0,0);
                lcd_print_string("-----[ SHT-11 ]-----");
                lcd_gotoxy(1,0);
                lcd_print_string("Sensor Error!");
                delay_ms(1000);
                continue;
            }
        lValue_temp = SHTRead();
        fTemp_true = D1+(D2*lValue_temp);     //temperature calculation

        //delay 11ms before next command
        delay_ms(12);
      
        SHTStart();                             //start transmission
        SHTWrite(SHT_MEASURE_HUMI);             //measure relative humidity
        lValue_rh = SHTRead();

        //relative humidity calculation
        fRh_lin = C1+(C2*lValue_rh)+(C3*lValue_rh*lValue_rh);
        fRh_true = (fTemp_true-25)*(T1+(T2*lValue_rh))+fRh_lin;
        if(fRh_true>100.0){fRh_true = 100.0;}
        if(fRh_true<0.1){fRh_true = 0.1;}

        //dewpoint calculation
        fLogEW = ((log10(fRh_true)-2)/0.4343)+(17.62*fTemp_true)/(243.12+fTemp_true);
        fDew_point = (243.12*fLogEW)/(17.62-fLogEW);

        lcd_gotoxy(0,0);
        lcd_print_string("-----[ SHT-11 ]-----");

        lcd_gotoxy(1,0);
        clr_buffer();
        sprintf(buffer,"Temperature :%3.1f C",fTemp_true);
        lcd_print_string(buffer);

        lcd_gotoxy(2,0);
        clr_buffer();
        sprintf(buffer,"Humidity    :%3.1f %%",fRh_true);
        lcd_print_string(buffer);

        lcd_gotoxy(3,0);
        clr_buffer();
        sprintf(buffer,"Dewpoint    :%3.1f C",fDew_point);
        lcd_print_string(buffer);

        delay_ms(1000);
    }
}