/*
* SIMPLE SERIAL FREQUENCY METER
*
* this program writes one time per second to the RS232 communication line,
* the frequency of the input signal on the RB0 pin
*
* PIC16F84A
* 16 Mhz crystal, HS clock
*
* PORTB.0, in : counter input
* PORTB.1, out : RS232 tx
* PORTB.2, in : RS232 rx
*
* Author : Bruno Gavand, november 2005
* see more details on [url]www.micro-examples.com[/url]
*
*/
/*
* RAM variables
*/
unsigned long cntr ; // number of RB0 transition
unsigned int ovrflw ; // number of timer0 overflows
unsigned char str[10] ; // display result string
/*
* constant strings
*/
const unsigned char welcome[] = "\r\rRS232 Frequency Meter Ready\rGo to [url]www.micro-examples.com[/url] for details\r" ;
const unsigned char unit[] = " Hz\r" ;
/*
* write the s ram string to RS232
*/
void Comm_Write(unsigned char *s)
{
while(*s)
{
Soft_Uart_Write(*s) ;
s++ ;
}
}
/*
* write the s constant string to RS232
*/
void Comm_WriteConst(const unsigned char *s)
{
while(*s)
{
Soft_Uart_Write(*s) ;
s++ ;
}
}
/*
* convert the cnrt long value to string
*/
void Long2str(void)
{
unsigned char i, j ;
if(cntr == 0)
{
str[0] = '0' ;
str[1] = 0 ;
}
else
{
str[0] = 0 ;
i = 0 ;
while(cntr > 0)
{
for(j = i + 1 ; j > 0 ; j--)
{
str[j] = str[j - 1] ;
}
str[0] = cntr % 10 ;
str[0] += '0' ;
i++ ;
cntr /= 10 ;
}
}
}
/*
* interrupt routine called 4000000/256 times by seconds :
* the timer TMR0 is increased each 4 clock cycles (quartz frequency is 16 Mhz),
* and overflows when reseting from 255 to 0,
* calling the interrupt procedure with bit T0IF set
*
* also called on each RBO transition, with bit INTF set
*/
void interrupt(void)
{
if(INTCON.INTF)
{
/*
* RB0 interrupt
*/
cntr++ ; // inc. transition counter
INTCON.INTF = 0 ; // clear interrupt flag to enable next call
}
else if(INTCON.T0IF)
{
/*
* TIMER 0 overflow
*/
ovrflw++ ; // inc. overflow counter
INTCON.T0IF = 0 ; // clear interrupt flag to enable next call on overflow
}
}
/*
* entry point
*/
main()
{
Soft_Uart_Init(PORTB, 1, 2, 38400, 0) ; // RS232 on PORTB, bits 1 & 2, 38400 bauds
Comm_WriteConst(welcome) ; // write welcome message
TRISB.F0 = 1 ; // RB0 interrupt pin as input
OPTION_REG = 0b11011000 ; // no prescaler
/*
* main loop
*/
for(;;)
{
cntr = 0 ; // clear counters
ovrflw = 0 ;
INTCON = 0b10110000 ; // T0IF, INTF and GIE enabled
while(ovrflw < 15626) ; // wait 1 second : 15626 = 16 000 000 / 4 / 256, rounded up
INTCON.GIE = 0 ; // stop all interrupts
Long2Str() ; // convert counter to string
Comm_Write(str) ; // write string
Comm_WriteConst(unit) ; // write unit
}
}
//