PIC C, RCTIME Function (CCS PCM - PIC16F84)


// RCTIME.C (CCS Info - PIC16F84)
//
// Charges capacitor in parallel with a resistor on RB0 for one second.  
// RB0 is then made an input and capacitor discharges though capacitor and
// and the time for detection of a one to zero transition is measured.
//
// Result in number of 2 usec ticks is displayed in hex on serial LCD
// on RA.0.
//
// Illustrates use of TMR0 and external interrupt.
//
// This is similar to the BASIC Stamp "rctime" command.  This is useful
// in determining the value of a resistor.  This is discussed at length
// and many typical examples are offered in Chapter 7 of my "BASIC 
// Stamp 2 Tutorial".
//
// copyright, Peter H. Anderson, Scotland Co, NC, Mar, '99

#case
#include <16f84.h>
#include <defs_f84.h>

// delay routines
void delay_ms(long t);
void delay_10us(int t);

// LCD routines
void lcd_init(void);
void out_RAM_str(int *s);
void lcd_hex_byte(int val);
void lcd_dec_byte(int val, int digits);
int num_to_char(int val);
void lcd_char(int ch);
void lcd_new_line(void);


#define TxData 0	// RA.0 - interface to serial LCD

short int overflow, ext_int_occurred;
int count_hi, count_lo;

void main(void)
{
 while(1)
 {
   lcd_init();

   trisb0=0;  	// output
   rb0=1;	// charge capacitor

   delay_ms(1000);

   overflow=FALSE;
   ext_int_occurred=FALSE;

   t0cs=0;	// clock
   psa=0;	// prescale assignment
   ps2=0;  ps1=0; ps0=0;	// prescale 1:2

   count_hi=0;


   intedg=0;  	// ext int on falling edge
   t0if = 0;
   intf=0;
   TMR0 = 0;	// fire up the timer
   trisb0=1;	// make RB0 an input, capacitor now discharging

   inte = 1;
   t0ie = 1;
   gie = 1;


   while(1)
   {
#asm
      CLRWDT
#endasm
      if (overflow || ext_int_occurred)
      {
         while(gie)
         {
            gie=0;
         }
         inte=0;
         t0ie = 0;	// housekeeping
//       lcd_char('.');
         break;
      }
   }  // end of while
   if (overflow)	// no external interrupt occurred
   {
       lcd_hex_byte(0xff);
       lcd_hex_byte(0xff);
   }

   else	// external interrupt
   {
      lcd_hex_byte(count_hi);
      lcd_hex_byte(count_lo);
   }
   delay_ms(1000);
 }
}

#int_rtcc rtcc_handler(void)
{
   ++count_hi;
   if (count_hi == 0)
   {
      overflow = TRUE;
   }
   t0if=0;
}

#int_ext ext_int_handler(void)
{
   count_lo = TMR0;	// get the low byte
   ext_int_occurred = TRUE;
   intf=0;
}

#int_default default_handler(void)
{
}

// delay routines

void delay_10us(int t)
{
#asm
      BCF STATUS, RP0
DELAY_10US_1:
      CLRWDT
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      DECFSZ t, F
      GOTO DELAY_10US_1
#endasm
}

void delay_ms(long t)	// delays t millisecs
{
   do
   {
     delay_10us(100);
   } while(--t);
}

// LCD routines

int num_to_char(int val)	// converts val to hex character
{
   int ch;
   if (val < 10)
   {
     ch=val+'0';
   }
   else
   {
     val=val-10;
     ch=val + 'A';
   }
   return(ch);
}

void lcd_char(int ch)	// serial output to PIC-n-LCD, 9600 baud
{
   int n, dly;
   		// start bit + 8 data bits

  #asm
       BCF STATUS, RP0
       MOVLW 9
       MOVWF n
       BCF STATUS, C

  LCD_CHAR_1:

       BTFSS STATUS, C
       BSF PORTA, TxData
       BTFSC STATUS, C
       BCF PORTA, TxData
       MOVLW 32
       MOVWF dly

  LCD_CHAR_2:
       DECFSZ dly, F
       GOTO LCD_CHAR_2
       RRF ch, F
       DECFSZ n, F
       GOTO LCD_CHAR_1

       BCF PORTA, TxData
       CLRWDT
       MOVLW 96
       MOVWF dly

  LCD_CHAR_3:
       DECFSZ dly, F
       GOTO LCD_CHAR_3
       CLRWDT
   #endasm
}

void lcd_init(void)	// sets TxData in idle state and resets PIC-n-LCD
{
  #asm
        BCF STATUS, RP0
        BCF PORTA, TxData
        BSF STATUS, RP0
        BCF TRISA, TxData
        BCF STATUS, RP0
   #endasm
   lcd_char(0x0c);
   delay_ms(250);
}

void lcd_new_line(void)	// outputs 0x0d, 0x0a
{
   lcd_char(0x0d);
   delay_ms(10);	// give the PIC-n-LCD time to perform the
   lcd_char(0x0a);	// new line function
   delay_ms(10);
}


void out_RAM_str(int *s)
{
   while(*s)
   {
      lcd_char(*s);
      ++s;
   }
}

void lcd_hex_byte(int val) // displays val in hex format
{
   int ch;
   ch = num_to_char((val>>4) & 0x0f);
   lcd_char(ch);
   ch = num_to_char(val&0x0f);
   lcd_char(ch);
}

void lcd_dec_byte(int val, int digits)
// displays byte in decimal as either 1, 2 or 3 digits
{
   int d;
   int ch;
   if (digits == 3)
   {
      d=val/100;
      ch=num_to_char(d);
      lcd_char(ch);
   }
   if (digits >1)	// take the two lowest digits
   {
       val=val%100;
       d=val/10;
       ch=num_to_char(d);
       lcd_char(ch);
   }
   if (digits == 1)	// take the least significant digit
   {
       val = val%100;
   }

   d=val % 10;
   ch=num_to_char(d);
   lcd_char(ch);
}