//DS18S20 (Dallas Semiconductor 1-wire Bus Temperature Sensor) Interfacing Example in PICCLITE. //PIC pins used: LCD Display: RB5 - RB0, Temp Sensor: RD0. //This example works for any LCD Module made by Optrex, Hitachi, etc. //This example is based on information in the DS18S20 datasheet //and Dallas Semiconductor App Note #162 "Interfacing the DS18x20 1-wire temp //sensor in a microcontroller environment //Chip Type: PIC16F877 //Clock Frequency: 13.5 MHz //Written by KEH on 11/01/2003 //LCD Display Type: 20 char X 2 line //*********************************************************************** //LCD Display Module connections to the PIC // LCD Pin LCD Pin # PIC Sig PIC Pin # // 1 GND --- --- // 2 Vcc --- --- // 3 Vee (Gnded for full contrast) // 4 RS RB5 P38 // 5 R/W* (Gnded, since we will only write to LCD module) // 6 E RB4 P37 // 7-10 DB0-DB3 (Not used) --- // 11 DB4 RB0 P33 // 12 DB5 RB1 P34 // 13 DB6 RB2 P35 // 14 DB7 RB3 P36 //*********************************************************************** #include #define RS RB5 #define RSCMD 0 #define RSDTA 1 #define E RB4 void initialize_lcd(void); void delayms(unsigned char); void lcdsendnyb(unsigned char); void lcdsendbyte(unsigned char); unsigned char one_wire_reset(void); void delay6us(unsigned int); void write_byte_one_wire(char); unsigned char read_byte_one_wire(void); unsigned char write_bit_one_wire(char); unsigned char read_bit_one_wire(void); unsigned char presence; void main(void) { unsigned char j; char scratchdat[10],msbtemp,lsbtemp; int temp,quot,lschar,middlechar,mschar,fractchar; PORTB = 0; TRISB = 0xC0; // Make RB5-0 all outputs TRISD0 = 1; //RD0 is pulled high through 4.7 kilohm external pullup resistor. initialize_lcd(); for(;;) { one_wire_reset(); write_byte_one_wire(0xcc); //skip ROM write_byte_one_wire(0x44); //Start Conversion delay6us(18); one_wire_reset(); write_byte_one_wire(0xcc); //Skip ROM write_byte_one_wire(0xBE); //Read Scratch Pad inside Temp Sensor lsbtemp = read_byte_one_wire(); msbtemp = read_byte_one_wire(); for(j=0;j<7;j++) scratchdat[j] = read_byte_one_wire(); temp = lsbtemp + (msbtemp<<8); if (temp & 1 == 1) fractchar = '5'; else fractchar = '0'; temp = temp>>1; //Get the temperature in degrees C instead of half degrees quot = temp/10; lschar = (temp - 10*quot) + 0x30; temp = quot; quot = temp/10; middlechar = (temp - 10*quot) + 0x30; temp = quot; quot = temp/10; mschar = (temp - 10*quot) + 0x30; RS=RSDTA; lcdsendbyte(mschar); lcdsendbyte(middlechar); lcdsendbyte(lschar); lcdsendbyte('.'); lcdsendbyte(fractchar); RS=RSCMD; lcdsendbyte(2); //Position Cursor at "Home Position" } } void initialize_lcd(void) { //initializes LCD Display delayms(20); RS=RSCMD; E=0; lcdsendnyb(0x3); // Function Set Command, Gen'l format: 0 0 1 DL N F * * delayms(0x5); // Note that DL = 1 => 8-bit interface mode (Display must be started in 8-bit mode) // Note that the N F * * (low order 4 bits) are not connected, and may be any value. lcdsendnyb(0x3); // Repeat a second time. delayms(0x1); lcdsendnyb(0x3); // Repeat a 3rd time lcdsendnyb(0x2); // Function Set Command - Now we can set interface to 4-bit (nybble) mode // Now that we are in nybble mode, we can send all 8 bits of each command via // two back-to-back calls to lcdsendnyb( ). lcdsendbyte(0x28); // Function Set Command Format: 0 0 1 DL N F * * // We just sent: 0 0 1 0 1 0 0 0 // DL=0 => 4-bit mode, // N=1 => 1/8 duty cycle // F=0 => 5 X 7 dot font lcdsendbyte(0x08); // Display OFF command lcdsendbyte(0x01); // Clear Display command lcdsendbyte(0x06); // Entry mode set command format: 0 0 0 0 0 1 I/D S // I/D = 1 => Increment display addr ptr. // S = 0 => Do not shift (scroll) display lcdsendbyte(0x0C); // Display ON command } void delayms(unsigned char nrms) { // Uses Timer #2 to delay the nr of ms specified assuming clock freq = 13.5 MHz unsigned char i; T2CON=0b0000111; //Timer 2 tick time = (4/13.5 Mhz)*16 = 0.474E-5 s //Nr Ticks in 1 ms = 1E-3 / 0.474E-5 = 210.94 ticks. for (i = 0; i < nrms; i++) { TMR2=256-211; //Schedule TMR2IF flag to be set in 1 ms TMR2IF = 0; //Clear TMR2IF timeout flag while(TMR2IF == 0) continue; //Wait here for 1 ms, until TMR2IF flag is set } } void delay6us(unsigned int nr6us) { unsigned int i; for (i = 0; i < nr6us; i++) { continue; } } void lcdsendnyb(unsigned char sendval) { unsigned char portbval; portbval = PORTB; PORTB = (portbval & 0xF0) + (sendval & 0x0F); //Send out most sig 4 bits of sendval on RB3:0 delayms(1); E=1; delayms(1); E=0; delayms(1); } void lcdsendbyte(unsigned char sendval) { lcdsendnyb(sendval >> 4); lcdsendnyb(sendval & 0x0f); } unsigned char one_wire_reset(void) { RD0 = 0; TRISD0 = 0; //Pull DQ line low delay6us(80); //Wait for 480 US TRISD0 = 1; //Allow DQ to e pulled high delay6us(12); //Wait for 70 US presence = RD0; //Read state of DQ (hopefully presence pulse is being sent by temp sens) delay6us(68); //Wait 410 US for presence pulse to finish return(presence); } unsigned char read_bit_one_wire(void) { unsigned char i; RD0 = 0; TRISD0 = 0; //Pull DQ low to start timeslot TRISD0 = 1; //Then let DQ line be pulled high. delay6us(1); //delay 15 us from start of timeslot return(RD0); //return value of DQ line (as set by temp sens) } unsigned char write_bit_one_wire(char bitval) { RD0 = 0; TRISD = 0; //Pull DQ low to start timeslot if(bitval == 1) TRISD = 1; //Let DQ go high to write a 1 delay6us(18); //delay 108 us TRISD0 = 1; //Let DQ line go high to end cycle } unsigned char read_byte_one_wire(void) { unsigned char i; unsigned char value = 0; for(i=0;i<8;i++) { if(read_bit_one_wire()) value=value | 1<>i; //Shift ith bit into LSB position temp = temp & 1; //Mask out LSB bit value write_bit_one_wire(temp); //Write it to temp sensor } delay6us(18); }