/****************************************************************************
Precision Frequency counter
Processor: PIC 18F2550
Input Pin: RC2 / CPP1
Base frequency:
Timer1 counting Fosc/4
Count mode:
Capture Timer1 count at CPP1 falling edge
Send both values in hexadecimal by UART
****************************************************************************/
#include <p18cxxx.h>
#include <stdlib.h>
#include <stdio.h>
#include <delays.h>
#include "main.h"
/****************************************************************************
GLOBAL VARS AND DEFINITIONS
****************************************************************************/
#pragma udata
char str_buf[20];
static unsigned char sys_clk, cent_second;
static unsigned short timer1_carry; // Timer1 extended counter
// Timer1 long counter (48 bits)
union {
struct {
unsigned int _word;
unsigned long dword;
};
unsigned int word[3];
unsigned char byte[6];
} timer1_count, timer1_capture;
#define TMR0_COUNT (FOSC/((unsigned long)4*250*100)) // Number of carrys per second
#define FOSC 20000000 // clock oscillator
#define BAUD 57600 // usart baud speed
/****************************************************************************
INTERRUPT SERVICE ROUTINE
****************************************************************************/
#pragma interrupt isr_main
void isr_main(void) {
// Timer1 interrupt counter
if (PIR1bits.TMR1IF == 1) {
PIR1bits.TMR1IF = 0;
timer1_count.dword++;
}
}
#pragma code high_vector=0x08
void isr_high(void) {
_asm GOTO isr_main _endasm
}
#pragma code
/****************************************************************************
USART AND RS232 FUNCTIONS
****************************************************************************/
/*
Initialize USART for RS232 comunications
*/
void rs232_init(void) {
BAUDCONbits.BRG16 = 0; // BRG16: 16-Bit Baud Rate Register Enable bit
SPBRGH = 0;
SPBRG = (FOSC/(16*BAUD))-1; // Real Baud = FOSC/(16*(SPBRG+1))
TXSTA = (char)
(0<<7) // CSRC: 1 = Syncronous Master mode
+ (0<<6) // TX9: 1 = Selects 9-bit transmission
+ (1<<5) // TXEN: 1 = Transmit enabled
+ (0<<4) // SYNC: 1 = Synchronous mode
+ (0<<3) // SENDB: 1 = Asynchronous mode: Send Sync Break on next transmission (cleared by hardware upon completion)
+ (1<<2) // BRGH: 1 = Asynchronous mode: High speed
+ (1<<1) // TRMT: 1 = TSR empty
+ (0<<0); // TX9D: Ninth bit of Transmit Data
RCSTA = (char)
(1<<7) // SPEN: 1 = Serial port enabled
+ (0<<6) // RX9: 1 = Selects 9-bit reception
+ (0<<5) // SREN: 1 = Enables single receive in Master Synchronous mode
+ (1<<4) // CREN: 1 = Enables Continuous Receive
+ (0<<3) // ADDEN: 1 = Enables address detection (RX9 = 1)
+ (0<<2) // FERR: 1 = Framing error
+ (0<<1) // OERR: 1 = Overrun error (can be cleared by clearing bit CREN)
+ (0<<0); // RX9D: Ninth bit of Received Data
TRISCbits.TRISC6 = 0; // Enable TX output
PIE1bits.TXIE = 0; // Disable RS232 interrupts
PIR1bits.TXIF = 0;
//TXREG = 0;
}
/*
Puts rom buffer to usart
*/
void rs232_puts(char const rom *str) {
while(*str) {
if (*str == '\n')
rs232_putc('\r');
rs232_putc(*str);
str++;
}
}
/*
Send char to USART with pooling
*/
void rs232_putc(char c) {
while (PIR1bits.TXIF == 0);
TXREG = c;
}
/*
Return Hexadecimal character of a nibble
*/
char Hexdec(char nibble) {
char bin2hex[] = "0123456789ABCDEF";
return bin2hex[nibble & 0x0F];
}
/****************************************************************************
CAPTURE MODE
Timer1 counts time
Input by CCP1
****************************************************************************/
void capture_init(void) {
T1CON = (unsigned char)
(1<<7) // RD16: 1 = 16-Bit Read/Write Mode Enable bit
+(0<<6) // T1RUN: 1 = Device clock is derived from Timer1 oscillator
+(0b00<<4) // T1CKPS: Timer1 Input Clock Prescale Select bits
// 11 = 1:8 Prescale value
// 10 = 1:4 Prescale value
// 01 = 1:2 Prescale value
// 00 = 1:1 Prescale value
+(0<<3) // T1OSCEN: 0 = Timer1 oscillator is shut off
+(1<<2) // T1SYNC: 1 = Do not synchronize external clock input
+(0<<1) // TMR1CS: 1 = External clock from RC0 pin, 0 = Internal clock (FOSC/4)
+(1<<0); // TMR1ON: 1 = Enables Timer1
// Reset Timer1 counters
TMR1H = 0;
TMR1L = 0;
timer1_count.word[0] = 0;
timer1_count.word[1] = 0;
timer1_count.word[2] = 0;
// Reset Timer1 interrupts
PIR1bits.TMR1IF = 0;
PIE1bits.TMR1IE = 1;
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
// CCP1 config
TRISCbits.TRISC2 = 1; // CPP1 input
CCP1CON = 0b00000100; // Capture every falling edge. Prescaler = 1
CCPR1H = 0;
CCPR1L = 0;
PIR1bits.CCP1IF = 0;
PIE1bits.CCP1IE = 0;
T3CONbits.T3CCP1 = 0; // Timer1 is the capture clock source for both CCP modules.
T3CONbits.T3CCP1 = 0;
}
void capture_read(void) {
// Wait for falling edge
while (PIR1bits.CCP1IF == 0);
PIR1bits.CCP1IF = 0;
// Read timer1
timer1_capture.byte[0] = CCPR1L;
timer1_capture.byte[1] = CCPR1H;
// Read timer1 overflow counter
timer1_capture.dword = timer1_count.dword;
timer1_count.byte[0] = TMR1L;
timer1_count.byte[1] = TMR1H;
if (timer1_count.word[0] < timer1_capture.word[0]) {
timer1_capture.dword = timer1_count.dword-1;
}
}
/****************************************************************************
MAIN PROGRAM
****************************************************************************/
#pragma code
#define PPB_ERROR (2900)
/*
MAIN ROUTINE
*/
void main(void) {
int i;
union {
unsigned char byte[4];
unsigned long dword;
} pulses;
// Initialize subsystems
rs232_init();
capture_init();
pulses.dword = 0;
// Pulse and time counter
while(1) {
// Wait 100 pulses
for(i=100; i>0; i--) {
capture_read();
pulses.dword++;
}
// Print Time count by Timer1
rs232_puts("t=\t");
//rs232_putc(Hexdec(timer1_capture.byte[5]<<4));
//rs232_putc(Hexdec(timer1_capture.byte[5]));
rs232_putc(Hexdec(timer1_capture.byte[4]>>4));
rs232_putc(Hexdec(timer1_capture.byte[4]));
rs232_putc(Hexdec(timer1_capture.byte[3]>>4));
rs232_putc(Hexdec(timer1_capture.byte[3]));
rs232_putc(Hexdec(timer1_capture.byte[2]>>4));
rs232_putc(Hexdec(timer1_capture.byte[2]));
rs232_putc(Hexdec(timer1_capture.byte[1]>>4));
rs232_putc(Hexdec(timer1_capture.byte[1]));
rs232_putc(Hexdec(timer1_capture.byte[0]>>4));
rs232_putc(Hexdec(timer1_capture.byte[0]));
rs232_puts("\t*200ns\t");
// Print falling edges counted
rs232_puts("N=\t");
rs232_putc(Hexdec(pulses.byte[2]>>4));
rs232_putc(Hexdec(pulses.byte[2]));
rs232_putc(Hexdec(pulses.byte[1]>>4));
rs232_putc(Hexdec(pulses.byte[1]));
rs232_putc(Hexdec(pulses.byte[0]>>4));
rs232_putc(Hexdec(pulses.byte[0]));
rs232_puts("\n");
}
}