/* THIS THERMOMETER USE THE MCD2 DEMO BOARD TO DISPLAY THE temprature degree. USING 16F877 READ MAXIM DS18b20 AND DISPLAY ON LCD1602 *//* ver1.1 May 2006 by Freeman(自由人) On the demo board, original DQ pin of DS18B20 is connected to PORTA.2 through a switch, have some conflict with LCD which also use PORTA.2 so I just keep the switch OFF, and fly a wire from pin DQ to PORTA.0 directly. the program of ver 1.0 only display a integer degree, ver 1.1 can display float point. with 1 decimal fraction. the difference as follow : int dsread() ---> float dsread() int temperature ---> float temperature some change in itoa10(char, int );*/ #include <pic.h>/* PIN define */#define LCDRS RA1#define LCDRWRA2#define LCDERA3#define LCDDATAPORTC#define DSDQ RA0 /* ds18b20 */#define TRISDQ TRISA0/* function define */void lcdinit(); /* two line mode */void wcmd (char cmd);void wdata (char data);void poscursor(char line, char col);void print(char *s);void lcdbusy();void delay ( int t);void itoa10(unsigned char *buf, int i);int strlen (const char *s);void dsinit();void wdscmd(char cmd);float dsread ();/* constant define */char bank1 title[]= "Temperature is";char dsfound[]="DS1820 FOUND";char dsnotfound[]="DS1820 NOT FOUND";char bank1 blank[]= " ";/* LCD command define */#define CLRLCD 0X01#define LCDMOD 0X38 /* 8 BIT, TWO LINE, 5X7 DOT MATRIX */#define TURNON 0X0F /* turn on LCD, CURSOR, BLINKING */#define CURMODE 0X06 /* character don't MOVe, cursor move right automaticall *//* DS1820 command */#define SKIPROM 0XCC#define READSCRACHPAD 0XBE#define TCONVERT 0X44/* ORIGINAL CURSOR POSITION */#define ORG1 0X80#define ORG2 0XC0/* TMR0 */static intcount;#define PRETMR0 210 /* aproximately 50us INT interval, 256-210 PLUS some headcost,*/float temperature;#define DSRESET 10#define DSRECOVER 1char bank1 atemperature[10]; /* used for store ascii code of digital temperature */void main(){ int len; ADCON1=0X07; /* SET PORTA AS DIGITAL I/O */ lcdinit(); print(title); LCDE=0; /* when LCDE=0, MCU will not affect LCD, and we can operate DS1820 */ /* INIT TIMER0 */ OPTION=0B11001111; /* bit5=0, using internal instruciton cycle clock */ TMR0IE=1; /* enable timer0 */ PEIE=0; /* disables all peripheral interrupts */ GIE=1;poscursor(1,0);while (1) { dsinit(); wdscmd(SKIPROM); wdscmd(TCONVERT); TRISDQ=0; DSDQ=0; TRISDQ=1; while(1) { //test if the conversion finished if (DSDQ) break; else continue; } dsinit(); wdscmd(SKIPROM); wdscmd(READSCRACHPAD); temperature=dsread(); /* read temperature */ itoa10(atemperature, (int) (temperature * 10)); /* because the itoa10 only works with integer */ // so use temperature * 10 to enlarge the temperature // and then add a decimal point in the function /* the following put a decimal dot '.' before the last digit of the atemperature */ len=strlen(atemperature); atemperature[len]=atemperature[len-1]; atemperature[len-1]='.'; atemperature[len+1]=0; poscursor(0,0); print (title); poscursor(1,0); print (blank); poscursor(1,2); print (atemperature); print (blank); delay(10000); /* wait for 10000*50 us=0.5 s before get new temperature */} }void delay (int t){ count=0; /* reset timer 0 */ TMR0=PRETMR0; while (count<t);}static void interrupt isr(void)// Here be interrupt function - the name is // unimportant.{if(TMR0IF)// Was this a timer overflow?count++;// Add 1 to count - insert idle commentTMR0IF = 0;// Clear interrupt flag, ready for next TMR0=PRETMR0;}int strlen(const char * s){const char *cp;cp = s;while(*cp++)continue;return cp-s-1;}void print(char *s){ int len; int atmp; len=strlen(s); for (atmp=0; atmp<len; atmp++) wdata(s[atmp]);}/* before we write to LCD , must check if the LCD IS busy */void lcdbusy(){ // char tmpbusy; TRISA &= 0xF1; TRISC=0XFF; LCDRS=0; LCDRW=1; LCDE=1; /* SET the LCD read/writing operation IN TO IDLE */ while(LCDDATA & 0X80);}/* position cursor, line= 0 for first line, or 1 for second line, col=0 - 15 ; */void poscursor(char line, char col){ char pos; lcdbusy(); pos = line * 0X40 + 0X80 + col; wcmd(pos);}void wdata(char data) { lcdbusy(); TRISA & =0XF1; TRISC=0; LCDDATA=data; LCDRS=1; LCDRW=0; LCDE=0; asm("NOP"); asm("NOP"); LCDE=1;}void wcmd(char cmd){ lcdbusy(); TRISA & =0XF1; TRISC=0; LCDDATA=cmd; LCDRS=0; LCDRW=0; LCDE=0; asm("NOP"); asm("NOP"); LCDE=1;} void lcdinit() { lcdbusy(); TRISA &= 0XF1; TRISC=0; wcmd(CLRLCD); wcmd(LCDMOD); wcmd(TURNON); wcmd(CURMODE); poscursor(0,0); /* set cursor to first position of first line */}/* DS1820 This file working with 16F877 using RA0 pin to communate *//* INIT */void dsinit(){ TRISDQ=0; DSDQ=0; delay(20); /* keep DSDQ low for 10*50 us, to reset the DS1820 */ TRISDQ=1; delay(1); /* here we can only use delay(1), more then one may go out of the sample window */ // if (!DSDQ) /* sample window between min end:15+60, max begin,60 */ /* garrente sample window is between 60 to 75 us */// print(dsfound);// else // print(dsnotfound);delay(10); /* wait for more then 480us, as required by the DS18B20 */ }/* write command to DS1820*/void wdscmd(char cmd){ char tmp; char i; TRISDQ=0; for(tmp=8;tmp>0;tmp--) { TRISDQ=0; DSDQ= 0; asm ("NOP"); asm ("NOP"); asm ("NOP"); asm ("NOP"); asm ("NOP"); if (cmd & 0x01) { TRISDQ=1; /* release the bus */ delay(1); /* wait for more than 60 us */ for (i=5;i>0;i--); } else { DSDQ=0 ; delay(1); for (i=5;i>0;i--); TRISDQ=1; } cmd=cmd/2; }} /* READ temperature */float dsread () { char tmp=0x01; float t; union{ char c[2]; int x; }temp;temp.x=0; while (tmp){ // read first 8 bits TRISDQ=0; DSDQ=0; asm("NOP"); TRISDQ=1; // release the bus if (DSDQ) // "1" presented temp.c[0] |= tmp; tmp=tmp<<1; delay(2); }tmp=1; while (tmp){ // read first 8 bits TRISDQ=0; DSDQ=0; asm("NOP"); TRISDQ=1; // release the bus asm("NOP"); if (DSDQ) // "1" presented temp.c[1] |= tmp; tmp=tmp<<1; delay(2); }t=((float) temp.x)/16.0 ;return t;} /* Convert integer 'i', radix 10 to a string */void itoa10(unsigned char *buf, int i) {unsigned int rem;unsigned char *s,length=0;s = buf;if (i == 0) *s++ = '0'; else {if (i < 0) {*buf++ = '-';s = buf;i = -i;}while (i) {++length;rem = i % 10;*s++ = rem + '0';i /= 10;}for(rem=0; ((unsigned char)rem)<length/2; rem++) {*(buf+length) = *(buf+((unsigned char)rem));*(buf+((unsigned char)rem)) = *(buf+(length-((unsigned char)rem)-1));*(buf+(length-((unsigned char)rem)-1)) = *(buf+length);}} *s=0;} |