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