//******************************************************************************** // Project : Final Project(Receiver for remote controller) // Start Date : 11/4/2004 // Finish Date : 11/13/2004 // Author : Xing Wang & Sunghwa Jung // Company : Rose-Hulman Institute of Technology // Purpose : 1. Decode demodulated IR singal by measuring pulse width with TMR0 every external interrupt. // 2. When receive IR data, flash trigger temprature 5 times on 7-segments and turn on red LED during flash. // 3. When periperal temp exceeds trigger temp, turn on green LED. // Input : TFM5360 & temperature from DS18B20 // Outputs : red LED, green LED & two digit temperature on two 7-segment displays // Chip type : PIC16F877 // Clock frequency : 13.5 MHz //******************************************************************************** #include //******************************************************************************** // I/O Definitions //******************************************************************************** #define DQ_DIRECTION TRISB1 // DQ wire direction bit #define DQ_DS18B20 RB1 #define SegA RD0 // pin 17, Segment A #define SegB RD1 // pin 18, Segment B #define SegC RD2 // pin 1, Segment C #define SegD RD3 // pin 2, Segment D #define SegE RD4 // pin 7, Segment E #define SegF RD5 // pin 8, Segment F #define SegG RD6 // pin 9, Segment G #define TensDigit RA0 // pin 10, tens digit control pin (on==1; off==0) #define OnesDigit RA1 // pin 11, ones digit control pin (on==1; off==0) #define LED RB7 #define IR_LED RB6 //******************************************************************************** // Constant Definitions //******************************************************************************** #define PORTA_DIRECTION 0B11100000 #define PORTB_DIRECTION 0B11000000 #define Input 1 #define Output 0 #define SkipCommand 0XCC #define ConvertTCommand 0X44 #define ReadScratchpad 0XBE #define WriteScratchpad 0X4E #define TH 0X00 #define TL 0X00 #define DS18B20_Config 0X1F //9bit resolution #define enable 1 #define disable 0 #define timer0 0.07585 // 1/13.5e6*4*256*1000=0.07585 #define T 0.6667 // 1/36kHz*24periods*1000=0.6667 //******************************************************************************** // Subroutine Definitions //******************************************************************************** void Initialize_Ports_INT(); int Initialize_DS18B20(); void SendCommand(char command); void Write_DS1820(char Bit); void ReadByte(char *digit); char Read_DS18B20(); void Wait_for_15useconds(); void Display_Byte(char, char); char Decimal_To_SevenSegment(char); char Get_Decimal(char *); void interrupt External_TMR0(); void reset_IR_module(); void save_data(char Bit); void Display_TriggerTemp(); //******************************************************************************** // Global Variable Definitions //******************************************************************************** char TriggerTemp = 24; // trigger temperature char ActualTemp; // peripheral temperature char tens,ones; // tens and ones digit of temperature int i = 0; // loop number for display char Head=0, Data_pulse=0, Stop_pulse=0; char Data=0,not_Data=0,Bit=0,bit_no=0,DisplayTrigger=0; char Trigger_tens,Trigger_ones,j=0,k=0; //******************************************************************************** // Main Program //******************************************************************************** void main() { unsigned int y; char STATUS, digit, temperature[2]; Initialize_Ports_INT(); Head = enable; do { STATUS = Initialize_DS18B20(); //Send reset pulse to and get presence pulse from DS18B20 }while(STATUS==1); //If DS18B20 is ready, STATUS will be "0". SendCommand(SkipCommand); //Skip the ROM command SendCommand(WriteScratchpad); //Send function command SendCommand(TH); //In this case, TH and TL register of scratchpad are not important. SendCommand(TL); //We just follow the write order of scratchpad to set configuration of DS18B20. SendCommand(DS18B20_Config); //R1R0 = 00 => 9bit resolution while(1) { INTE = disable; do { STATUS = Initialize_DS18B20(); //Send reset pulse to and get presence pulse from DS18B20 }while(STATUS==1); //If DS18B20 is ready, STATUS will be "0". SendCommand(SkipCommand); //Skip the ROM command SendCommand(ConvertTCommand); //Send function command do { ReadByte(&digit); //If conversion is done, DS18B20 transmits "1". }while(digit!=0xff); //If 8bits of digit are all "1", conversion is done. do { STATUS = Initialize_DS18B20(); //Send reset pulse to and get presence pulse from DS18B20 }while(STATUS==1); //If DS18B20 is ready, STATUS will be "0". SendCommand(SkipCommand); //Skip the ROM command SendCommand(ReadScratchpad); //Send function command ReadByte(&digit); // Read temperature LSByte, Byte 0 of scartchpad temperature[0] = digit; ReadByte(&digit); // Read temperature MSByte, Byte 1 of scartchpad temperature[1] = digit; ActualTemp = Get_Decimal(temperature); tens = ActualTemp/10; ones = ActualTemp - tens*10; INTE = enable; while(DisplayTrigger==enable) { Display_TriggerTemp(); DisplayTrigger = disable; } if (ActualTemp>=TriggerTemp) LED = 1; else LED = 0; while(i<250*2) { Display_Byte(1, tens); for(y=0;y<450;y++); Display_Byte(0, ones); for(y=0;y<450;y++); OnesDigit = 0; i++; } i = 0; } } //******************************************************************************** // Initialize_Ports() //******************************************************************************** void Initialize_Ports_INT() { // DS18B20 signal line, DQ TRISA = 0X00; TRISB = 0X0f; //PORTB6,7 are input, the others are output. TRISD = 0x00; DQ_DIRECTION=Output; // DQ on DS18B20 is output RBPU = 1; // Enable internal resister of PORTB PORTD=0x00; TensDigit=1; //Turn TensDigit 7-segment. OnesDigit=1; //Turn OnesDigit 7-segment. TMR2ON=1; T0CS = 0; //Timer mode PSA = 0; //Prescaler is assigned to Timer0 PS2 = 1; //Prescaler=1:128 PS1 = 0; PS0 = 1; T0IF = 0; INTF = 0; INTEDG = 0; //External interrupt is triggered at falling edge. GIE = enable; INTE = enable; } //******************************************************************************** // Reset_DS18B20() //******************************************************************************** // Send a reset pulse of 0 volt to DS1820 and wait for presence pulse // (1) Drop DQ line to send a reset low pulse of between 480 microseconds and 960 microseconds. // (2) Raise DQ line and wait for 15 to 60 microseconds // (3) Check presence of lower pulse from DS1820 from 60 to 240 microseconds in lenghth // (4) Return 0 for success and 1 for error int Initialize_DS18B20() // DQ_DS1820 is the signal pin of DS1820 // DQ_DIRECTION is the pin direction configuration bit { char i, presence; DQ_DIRECTION = Output; // DQ is output from PIC to DS1820 DQ_DS18B20 = 0; for(i=0;i<32;i++) Wait_for_15useconds(); // wait for 691 useconds at 13MHz DQ_DS18B20 = 1; for(i=0;i<2;i++) Wait_for_15useconds(); // wait for 45 useconds at 13MHz DQ_DIRECTION = Input; // DQ is input from DS18B20 to PIC presence = 1; for(i=0;i<13;i++) // read DQ for 311 useconds and check for zero { if(presence==1) presence = DQ_DS18B20; // check if DS18B20 is ready Wait_for_15useconds(); }; DQ_DIRECTION = Output; for(i=0;i<11;i++) Wait_for_15useconds(); // wait for 263 microseconds at 13MHz return(presence); // return presence pulse status }// end of Reset_DS18B20() //******************************************************************************** // SendCommand() -- send one-byte command in command to DS1820 // with least significant bit first //******************************************************************************** void SendCommand(char command) { char i; // loop count DQ_DIRECTION = Output; // DQ is output from PIC to DS18B20 for(i=0;i<8;i++) { if((command&0B00000001)==0) Write_DS1820(0);// bit-wise AND to pick out Bit 0 else Write_DS1820(1); command = command>>1; // right shift by one bit } return; } //******************************************************************************** // Write_DS18B20() //******************************************************************************** void Write_DS1820(char Bit) // write one bit in Bit to DS18B20 { char i; DQ_DIRECTION = Output; // DQ is output from PIC to DS18B20 Wait_for_15useconds(); DQ_DS18B20 = 0; // pull DQ down to start writing DQ_DS18B20 = 0; // at least 1 us long if(Bit==0) // write "0" { for(i=0;i<4;i++) Wait_for_15useconds(); // wait for 100.3us at 13MHz DQ_DIRECTION = Input; // release data line to write "0" Wait_for_15useconds(); } else // write "1" { DQ_DIRECTION = Input; // release data line to write "1" for(i=0;i<5;i++) Wait_for_15useconds(); // wait for 124.3us at 13MHz } return; }// end Write_DS1820() //******************************************************************************** // ReadByte() -- read one byte from DS1820 // with least significant bit first //******************************************************************************** void ReadByte(char *digit) { char i, byte; // loop count byte = 0; // clear digit for(i=0;i<7;i++) { if(Read_DS18B20()==1) byte = byte|0B10000000; // Receiving a "1", set the bit. byte = byte>>1; // left shift by one bit with "0" in LSB } if(Read_DS18B20()==1) // receive a "1" for Bit 7 byte = byte|0B10000000; // set the bit *digit = byte; return; } //end of ReadByte() //******************************************************************************** // Read_DS1820() -- read one bit from DS1820 //******************************************************************************** // mimimum duration is 60 microseconds. char Read_DS18B20() { char i, sample; // bit sampled from DS1820 DQ_DIRECTION = Output; // pull low for >1us to start reading cycle DQ_DS18B20=0; DQ_DS18B20=0; DQ_DIRECTION = Input; // release DQ line for(i=0;i<3;i++);// wait for us at 13MHz sample = DQ_DS18B20; for(i=0;i<2;i++) Wait_for_15useconds(); // wait for 52.3us at 13MHz DQ_DIRECTION = Output; return (sample); // sample and return either "0" or "1" from DS1820 }// end Read_DS1820() //******************************************************************************** // Display_Byte() - send a byte to 7-segment display //******************************************************************************** void Display_Byte(char choice, char word) // display word on 7 segment display, as XGFEDCBA // choice=0 for ones digit, choice=1 for tens digit { char code; code = Decimal_To_SevenSegment(word); SegA = code; code = code>>1; // shift one bit to right SegB = code; code = code>>1; // shift one bit to right SegC = code; code = code>>1; // shift one bit to right SegD = code; code = code>>1; // shift one bit to right SegE = code; code = code>>1; // shift one bit to right SegF = code; code = code>>1; // shift one bit to right SegG = code; if(choice==0) { TensDigit = 0; // turn off tens digit segment OnesDigit = 1; // turn on ones digit segment } else { OnesDigit = 0; // turn off ones digit segment TensDigit = 1; // turn on tens digit segment } } //******************************************************************************** // Decimal_To_SevenSegment() - send a byte to 7-segment display //******************************************************************************** char Decimal_To_SevenSegment(char digit) { char BinaryString; switch (digit) { case 0: BinaryString = 0B01000000; break; case 1: BinaryString = 0B01111001; break; case 2: BinaryString = 0B00100100; break; case 3: BinaryString = 0B00110000; break; case 4: BinaryString = 0B00011001; break; case 5: BinaryString = 0B00010010; break; case 6: BinaryString = 0B00000010; break; case 7: BinaryString = 0B01111000; break; case 8: BinaryString = 0B00000000; break; case 9: BinaryString = 0B00010000; break; } return BinaryString; } //******************************************************************************** // Get_Decimal() //******************************************************************************** char Get_Decimal(char *string) { char digit; char sum = 0; digit = string[1]; digit = digit>>4; if((digit&0x0F) == 0) // positive { digit = string[0]; digit = digit>>3; if((digit&0x01) ==1) sum = sum + 1; digit = digit>>1; if((digit&0x01) ==1) sum = sum + 2; digit = digit>>1; if((digit&0x01) ==1) sum = sum + 4; digit = digit>>1; if((digit&0x01) ==1) sum = sum + 8; digit = digit>>1; if((digit&0x01) ==1) sum = sum + 16; digit = string[1]; if((digit&0x01) ==1) sum = sum + 32; digit = digit>>1; if((digit&0x01) ==1) sum = sum + 64; digit = digit>>1; if((digit&0x01) ==1) sum = sum + 128; } sum = sum/2; // "1" stands for 0.5 centigrade return sum; } //******************************************************************************** // interrupt RB_Change() //******************************************************************************** void interrupt External_TMR0() { // static char Trigger_tens,Trigger_ones,i,j; if(T0IF) { reset_IR_module(); T0IF = 0; } else if(INTF) { if(Head==enable) //Head=start bit of IR signal { if(INTEDG==0) //at falling edge { TMR0=0; T0IE=enable; INTEDG=1; //triggered at rising edge }//end if(INTEDG==0) else if(INTEDG==1) //at rising edge { if(TMR0>127) //1/13.5e6*4*64*127=2.41 ms > 3.6*T = 2.4 ms { TMR0 = 0; Data_pulse=enable; Head=disable; } //end if(Time_intaval*timer0>3.6*T) else reset_IR_module(); } //end if(INTEDG==1) } //end if(Head==enable) else if(Data_pulse==enable) { if(TMR0>57 && TMR0<84)//1.6*T < TMR0 < 2.4*T { TMR0 = 0; Bit = 0x00; save_data(Bit); } else if(TMR0>94 && TMR0<119 ) //2.6*T < TMR0 < 3.4*T { TMR0 = 0; Bit = 0x01; save_data(Bit); } else reset_IR_module(); } //end if(Data=enable) else if(Stop_pulse==enable) { if(TMR0>57 && TMR0<84)//1.6*T < TMR0 < 2.4*T { TMR0 = 0; if(Data^not_Data==0x0F) { switch(Data) { case 0B00001100: TriggerTemp++; DisplayTrigger=enable; break; case 0B00000011: TriggerTemp--; DisplayTrigger=enable; break; case 0B00001010: TensDigit=0; OnesDigit=0; SLEEP(); break; } //end switch(Data) } //end if(Data^not_Data==0) } //end if(Time_intaval*timer0>1.8*T && Time_intaval*timer0<2.2*T) reset_IR_module(); } //end if(Stop_pulse==enable) INTF=0; } //end if(INTF) } //end void interrupt External_TMR0() //******************************************************************************** // Wait_for_15useconds() //******************************************************************************** void Wait_for_15useconds() // use Timer0 to generate 14.80 microsecond delay each time this routine is called // at 13 MHz { TMR2IF = 0; TMR2 = 256-42; while(TMR2IF==0); return; } // end Wait_for_15useconds() //******************************************************************************** // reset_IR_module() //******************************************************************************** void reset_IR_module() { T0IE = disable; TMR0 = 0; INTEDG = 0; //triggered at falling edge Data = 0; not_Data = 0; Head = enable; Data_pulse = disable; Stop_pulse = disable; } //******************************************************************************** // save_data(char bit) //******************************************************************************** void save_data(char Bit) { if(bit_no<=3) { Data = Data<<1; Data = Data | Bit; } //end if(bit_no<=3) else if(bit_no>3) { not_Data = not_Data<<1; not_Data = not_Data | Bit; } //end if(bit_no>3) bit_no++; if(bit_no>=8) { Stop_pulse=enable; Data_pulse=disable; bit_no=0; } //end if(bit_no>=8) } //******************************************************************************** // void Display_TriggerTemp() //******************************************************************************** void Display_TriggerTemp() { IR_LED = 1; Trigger_tens = TriggerTemp / 10; Trigger_ones = TriggerTemp - Trigger_tens*10; for(k=0;k<5;k++) { for(j=0;j<100;j++) { Display_Byte(1, Trigger_tens); for(i=0;i<450;i++); Display_Byte(0, Trigger_ones); for(i=0;i<450;i++); } TensDigit = 0; OnesDigit = 0; for(i=0;i<450*15;i++); } IR_LED = 0; }