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);
}