1: //DS18S20 (Dallas Semiconductor 1-wire Bus Temperature Sensor) Interfacing Example in PICCLITE.

     2: //PIC pins used: LCD Display: RB5 - RB0, Temp Sensor: RD0.

     3: //This example works for any LCD Module made by Optrex, Hitachi, etc.

     4: //This example is based on information in the DS18S20 datasheet 

     5: //and Dallas Semiconductor App Note #162 "Interfacing the DS18x20 1-wire temp

     6: //sensor in a microcontroller environment

     7: //Chip Type: PIC16F877

     8: //Clock Frequency: 13.5 MHz

     9: //Written by KEH on 11/01/2003

    10: //LCD Display Type: 20 char X 2 line

    11: //***********************************************************************

    12: //LCD Display Module connections to the PIC 

    13: //      LCD Pin  LCD Pin #   PIC Sig  PIC Pin #

    14: //              1               GND                     ---             ---

    15: //              2       Vcc                     ---             ---

    16: //                      3               Vee (Gnded for full contrast)

    17: //                      4               RS                      RB5             P38

    18: //                      5               R/W* (Gnded, since we will only write to LCD module)

    19: //                      6               E                       RB4             P37

    20: //                      7-10    DB0-DB3 (Not used)      ---

    21: //                      11              DB4                     RB0             P33

    22: //                      12              DB5                     RB1             P34

    23: //                      13              DB6                     RB2             P35

    24: //                      14              DB7                     RB3             P36

    25: //***********************************************************************

    26:         #include <pic.h>

    27:         #define RS                      RB5

    28:         #define RSCMD           0

    29:         #define RSDTA           1

    30:         #define E                       RB4

    31: 

    32:         void initialize_lcd(void);

    33:         void delayms(unsigned char);

    34:         void lcdsendnyb(unsigned char);

    35:         void lcdsendbyte(unsigned char);

    36: 

    37:         unsigned char one_wire_reset(void);

    38:         void delay6us(unsigned int);

    39:         void write_byte_one_wire(char);

    40:         unsigned char read_byte_one_wire(void);

    41:         unsigned char write_bit_one_wire(char);

    42:         unsigned char read_bit_one_wire(void);

    43:         unsigned char presence;

    44: 

    45:         void main(void)

    46: {               

    47:         unsigned char j;

    48:         char scratchdat[10],msbtemp,lsbtemp;

    49:         int temp,quot,lschar,middlechar,mschar,fractchar;

    50: 

    51: PORTB = 0;

    52: TRISB = 0xC0;   // Make RB5-0 all outputs       

    53: TRISD0 = 1;             //RD0 is pulled high through 4.7 kilohm external pullup resistor.

    54: initialize_lcd();

    55: for(;;)

    56:  {      

    57:         one_wire_reset();

    58:         write_byte_one_wire(0xcc);      //skip ROM

    59:         write_byte_one_wire(0x44);      //Start Conversion

    60:         delay6us(18);

    61:         one_wire_reset();

    62:         write_byte_one_wire(0xcc);      //Skip ROM

    63:         write_byte_one_wire(0xBE);      //Read Scratch Pad inside Temp Sensor

    64:         lsbtemp = read_byte_one_wire();

    65:         msbtemp = read_byte_one_wire();

    66:         for(j=0;j<7;j++)

    67:                         scratchdat[j] = read_byte_one_wire();

    68:         temp = lsbtemp + (msbtemp<<8);

    69:         if (temp & 1 == 1) fractchar = '5'; else fractchar = '0';

    70:         temp = temp>>1;  //Get the temperature in degrees C instead of half degrees

    71:         quot = temp/10;

    72:         lschar = (temp - 10*quot) + 0x30;

    73:         temp = quot;

    74:         quot = temp/10;

    75:         middlechar = (temp - 10*quot) + 0x30;

    76:         temp = quot;

    77:         quot = temp/10;

    78:         mschar = (temp - 10*quot) + 0x30;

    79:         RS=RSDTA;

    80:         lcdsendbyte(mschar);

    81:         lcdsendbyte(middlechar);

    82:         lcdsendbyte(lschar);

    83:         lcdsendbyte('.');

    84:         lcdsendbyte(fractchar);

    85:         RS=RSCMD;

    86:         lcdsendbyte(2);         //Position Cursor at "Home Position"

    87:   }

    88: }

    89: 

    90: 

    91: void initialize_lcd(void)

    92: {

    93: //initializes LCD Display

    94:         delayms(20);    

    95:         RS=RSCMD;               

    96:         E=0;

    97:         lcdsendnyb(0x3);        // Function Set Command, Gen'l format: 0 0 1 DL N F * *

    98:         delayms(0x5);   // Note that DL = 1 => 8-bit interface mode (Display must be started in 8-bit mode)

    99:                                         // Note that the N F * * (low order 4 bits) are not connected, and may be any value.

   100:         lcdsendnyb(0x3);        // Repeat a second time.

   101:         delayms(0x1);

   102:         lcdsendnyb(0x3);        // Repeat a 3rd time

   103:         lcdsendnyb(0x2);        // Function Set Command - Now we can set interface to 4-bit (nybble) mode

   104: 

   105:                                         // Now that we are in nybble mode, we can send all 8 bits of each command via

   106:                                         // two back-to-back calls to lcdsendnyb( ).

   107:         lcdsendbyte(0x28); // Function Set Command Format: 0 0 1 DL N F * *

   108:                                                                 // We just sent:                0 0 1 0  1 0 0 0 

   109:                                                                 //  DL=0 => 4-bit mode,

   110:                                                                 //      N=1 => 1/8 duty cycle

   111:                                                                 //  F=0 => 5 X 7 dot font

   112:         lcdsendbyte(0x08); // Display OFF command

   113:         lcdsendbyte(0x01); // Clear Display command

   114:         lcdsendbyte(0x06);      // Entry mode set command format: 0 0 0 0 0 1 I/D S

   115:                                                         // I/D = 1 => Increment display addr ptr.

   116:                                                         // S = 0 => Do not shift (scroll) display

   117:         lcdsendbyte(0x0C);      // Display ON command

   118: }

   119: 

   120: 

   121: void delayms(unsigned char nrms)

   122: {

   123: // Uses Timer #2 to delay the nr of ms specified assuming clock freq = 13.5 MHz

   124:         unsigned char i;

   125:         T2CON=0b0000111;        //Timer 2 tick time = (4/13.5 Mhz)*16 = 0.474E-5 s

   126:                                                 //Nr Ticks in 1 ms = 1E-3 / 0.474E-5 = 210.94 ticks.

   127:         for (i = 0; i < nrms; i++)

   128:                 {

   129:                         TMR2=256-211;           //Schedule TMR2IF flag to be set in 1 ms

   130:                         TMR2IF = 0;                     //Clear TMR2IF timeout flag

   131:                         while(TMR2IF == 0)

   132:                                 continue;               //Wait here for 1 ms, until TMR2IF flag is set

   133:                 }

   134: }

   135: 

   136: 

   137: void delay6us(unsigned int nr6us)

   138: {       unsigned int i;

   139:         for (i = 0; i < nr6us; i++)

   140:                 {

   141:                         continue;

   142:                 }

   143: }

   144: 

   145: void lcdsendnyb(unsigned char sendval)

   146: {

   147:         unsigned char portbval;

   148:         portbval = PORTB;

   149:         PORTB = (portbval & 0xF0) + (sendval & 0x0F);

   150:                                                                 //Send out most sig 4 bits of sendval on RB3:0

   151:         delayms(1);

   152:         E=1;

   153:         delayms(1);

   154:         E=0;

   155:         delayms(1);

   156: }

   157: 

   158: void lcdsendbyte(unsigned char sendval)

   159: {

   160:         lcdsendnyb(sendval >> 4);

   161:         lcdsendnyb(sendval & 0x0f);

   162: }

   163: 

   164: unsigned char one_wire_reset(void)

   165: {

   166:         RD0 = 0;

   167:         TRISD0 = 0;                     //Pull DQ line low

   168:         delay6us(80);           //Wait for 480 US

   169:         TRISD0 = 1;                     //Allow DQ to e pulled high

   170:         delay6us(12);           //Wait for 70 US

   171:         presence = RD0;         //Read state of DQ (hopefully presence pulse is being sent by temp sens)

   172:         delay6us(68);           //Wait 410 US for presence pulse to finish

   173:         return(presence);       

   174: }

   175: 

   176: unsigned char read_bit_one_wire(void)

   177: {

   178:         unsigned char i;

   179:         RD0 = 0;

   180:         TRISD0 = 0;                     //Pull DQ low to start timeslot

   181:         TRISD0 = 1;                     //Then let DQ line be pulled high.

   182:         delay6us(1);            //delay 15 us from start of timeslot

   183:         return(RD0);            //return value of DQ line (as set by temp sens)

   184: }

   185: 

   186: unsigned char write_bit_one_wire(char bitval)

   187: {       RD0 = 0;

   188:         TRISD = 0;                      //Pull DQ low to start timeslot

   189:         if(bitval == 1) TRISD = 1; //Let DQ go high to write a 1

   190:         delay6us(18);           //delay 108 us

   191:         TRISD0 = 1;                     //Let DQ line go high to end cycle

   192: }

   193: 

   194: unsigned char read_byte_one_wire(void)

   195: {

   196:         unsigned char i;

   197:         unsigned char value = 0;

   198:         

   199:         for(i=0;i<8;i++)

   200:                 {

   201:                         if(read_bit_one_wire()) value=value | 1<<i;  //Read byte in one bit at a time

   202:                         delay6us(18);                                             //Wait for rest of timeslot

   203:                 }

   204:         return(value);

   205: }

   206: 

   207: void write_byte_one_wire(char val)

   208: {

   209:         unsigned char i;

   210:         unsigned char temp;

   211: 

   212:         for(i=0;i<8;i++)                        //Write byte, one bit at a time

   213:                 {

   214:                         temp = val>>i;          //Shift ith bit into LSB position

   215:                         temp = temp & 1;        //Mask out LSB bit value

   216:                         write_bit_one_wire(temp);       //Write it to temp sensor

   217:                 }

   218:         delay6us(18);

   219: }