290 likes | 302 Views
This C program implements a Digital Thermometer using DS18S20 1-Wire Bus Sensor for temperature sensing in a microcontroller environment. The code reads and displays the temperature values on an LCD panel.
E N D
C Program that implements Digital Thermometer using DS18S20 1-Wire Bus Sensor
#include <hidef.h> /* common defines and macros */ #include <mc9s12c128.h> /* derivative information */ #include "lcd_subroutines.h" #pragma LINK_INFO DERIVATIVE "mc9s12c128" //DS18S20 (Dallas Semiconductor 1-wire Bus Temperature Sensor) //Pins Used: LCD Panel PTT7:2, Temp Sensor: PTM0. //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: 9S12C128 //Bus Clock Frequency: 24 MHz //Written by KEH
#define DQ PTM_PTM3 //Use PTM3 as the one-wire bus line, define it as "DQ" #define DQDDR DDRM_DDRM3 //Define "DQDDR" as DDRM bit #3, //which controls state of DQ. //Throughout this program, we shall keep DQ set to 0, // and thus if DQDDR = 0 => DQ line float. // (The DQ line is quickly pulled high through a // 4.7kohm pullup resistor.) // But if DQDDR = 1, => DQ line is quickly pulled LOW. void INIT_PLL(void); unsigned char one_wire_reset(void); void delay6us(unsigned int); void write_byte_one_wire(char); unsigned char read_byte_one_wire(void); void write_bit_one_wire(char); unsigned char read_bit_one_wire(void); char lschar,middlechar,mschar,fractchar; int temp; char scratchdat[10],msbtemp,lsbtemp;
void main(void) { unsigned char j; INIT_PLL(); LCD_INIT(); for(;;) { DQDDR = 0; //DQ is pulled high through 4.7 kilohm external pullup resistor. while(one_wire_reset()); //Hang here if 1-wire sensor not present write_byte_one_wire(0xcc); //skip ROM Command //(Only allowed when there is only 1 device on bus) write_byte_one_wire(0x44); //Start Conversion delay6us(18); while(one_wire_reset()); //Hang here if 1-wire sensor not present write_byte_one_wire(0xcc); //Skip ROM Command write_byte_one_wire(0xBE); //Read Scratch Pad inside Temp Sensor lsbtemp = read_byte_one_wire(); //First two bytes from scratchpad //hold Centigrade Temp. msbtemp = read_byte_one_wire();
for(j=0;j<7;j++) //Read the rest of the scratchpad, even though we scratchdat[j] = read_byte_one_wire(); //will do nothing with it. temp = lsbtemp + (msbtemp<<8); //Variable "temp" holds temperature //in 0.5 deg C units if (temp & 1 == 1) { fractchar = '5'; } //Look at LSB of "temp" to determine fractional part else { //(this fractional part is either 0.5 deg C or 0.0 deg C.) fractchar = '0'; } temp = temp>>1; //Now the integer in "temp" is the Centigrade degrees lschar = temp%10 + 0x30; //Decompose "temp" into three decimal ASCII digits temp = temp/10; middlechar = temp%10 + 0x30; temp = temp/10; mschar = temp%10 + 0x30;
LCD_ADDRESS(0); //Home the LCD panel display. LCD_DTA(mschar); //Display integer part of temp LCD_DTA(middlechar); LCD_DTA(lschar); LCD_DTA('.'); //Insert decimal point LCD_DTA(fractchar); //Display fractional part (0.0 or 0.5 deg C) delay6us(30000); //Wait about 0.2 seconds between temperature samples } }
void delay6us(unsigned int nr6us) //Wait for nr of 6us intervals in argument { unsigned int i,j; for (i = 0; i < nr6us; i++) { for(j=0;j<22;j++); } }
unsigned char one_wire_reset(void) //Begin each transfer sequence with // one_wire_reset by calling this rtn. { unsigned char presence; DQ = 0; DQDDR = 1; //Pull DQ line low delay6us(80); //Wait for 480 US DQDDR = 0; //Allow DQ to be pulled high delay6us(12); //Wait for 70 US presence = DQ; //Read state of DQ //(hopefully presence pulse being sent by temp sensor!) delay6us(68); //Wait 410 US for presence pulse to finish. return(presence); }
unsigned char read_bit_one_wire(void) //Read one bit { unsigned char i; DQ = 0; DQDDR = 1; //Pull DQ low to start timeslot DQDDR = 0; //Then let DQ line be pulled high. delay6us(2); //delay 12 us from start of timeslot i = DQ; return(i); //return value of DQ line (as set by temp sens) }
void write_bit_one_wire(char bitval) //Write one bit { DQ = 0; DQDDR = 1; //Pull DQ low to start timeslot if(bitval == 1) DQDDR = 0; //Let DQ go high to write a 1 delay6us(18); //delay 108 us DQDDR = 0; //Let DQ line go high to end cycle }
unsigned char read_byte_one_wire(void) //Read a byte from 1-wire device { unsigned char i; unsigned char value = 0; for(i=0;i<8;i++) { if(read_bit_one_wire()) value=value | 1<<i; //Read byte in one bit at a time delay6us(18); //Wait for rest of timeslot } return(value); }
void write_byte_one_wire(char val) //Write a byte to the 1-wire device { unsigned char i; unsigned char temp; for(i=0;i<8;i++) //Write byte, one bit at a time { temp = val>>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); }
How a single bit of an 8-bit port may be accessed (read or written) in C Let us focus on PTM0, as an example Then “PTM_PTM0 = 1;” will set just bit #0 of Port M, or “while(PTM_PTM0);” will hang up until bit #0 of Port M goes low. Look at the MC9S12C128.h header file (under Libraries in the Project View). Note the following excerpts from this file:
At very top of this header file…….. /* Types definition */ typedef unsigned char byte; typedef unsigned int word; typedef unsigned long dword; typedef unsigned long dlong[2]; #define REG_BASE 0x0000 /* Base address for the I/O register block */
/*** PTM - Port M I/O Register; 0x00000250 ***/ typedef union { byte Byte; struct { byte PTM0 :1; /* Port M Bit 0 */ byte PTM1 :1; /* Port M Bit 1 */ byte PTM2 :1; /* Port M Bit 2 */ byte PTM3 :1; /* Port M Bit 3 */ byte PTM4 :1; /* Port M Bit 4 */ byte PTM5 :1; /* Port M Bit 5 */ byte :1; byte :1; } Bits; struct { byte grpPTM :6; byte :1; byte :1; } MergedBits; } PTMSTR;
extern volatile PTMSTR _PTM @(REG_BASE + 0x00000250); #define PTM _PTM.Byte #define PTM_PTM0 _PTM.Bits.PTM0 #define PTM_PTM1 _PTM.Bits.PTM1 #define PTM_PTM2 _PTM.Bits.PTM2 #define PTM_PTM3 _PTM.Bits.PTM3 #define PTM_PTM4 _PTM.Bits.PTM4 #define PTM_PTM5 _PTM.Bits.PTM5 #define PTM_PTM _PTM.MergedBits.grpPTM