Você está na página 1de 6

/*****************************

Decription:
This software activates the CCP1 module and tells it to interrupt on every risin
g edge that is seen.
When interrupt occurs, the time since the previous interrupt is recorded and use
d to calculate and display
on an LCD the instantaneous RPMs detected.
******************************/
#include
#include
#include
#include
#include
#include

<p16f877a.h>
<capture.h>
<timers.h>
<stdlib.h>
<delays.h>
<ctype.h>

//LCD Pins
#define LCD_RS
#define LCD_RW
#define LCD_E

PORTBbits.RB0
PORTBbits.RB1
PORTBbits.RB2

#define LCD_DATA

PORTD

//LCD Functions
void LCD_INIT(void);
void LCD_WRITE(unsigned char,unsigned int);
void InterruptHandlerHigh (void);
char array_2[8] = {'\0','\0','\0','\0','\0','\0','\0','\0'};
unsigned long int cap_val = 0;
unsigned long int cur_cap_val = 0;
void main(void)
{
//PORTA
TRISA =
//PORTC
TRISC =

Set To Outputs
0x00;
Set To Inputs (CCP1 is on PortC)
0xFF;

//PORTD
TRISD =
//PORTB
TRISB =

Set To Outputs
0x00; // D0~~D7
Set To Outputs
0x00; //RS, R/W*, E

//Initialize Port Values


PORTA = 0x00;
PORTB = 0x00;
PORTC = 0x00;
PORTD = 0x00;
//Short Delay Before Starting
Delay10KTCYx(250);
//Initialize LCD and write 'RPM: ' on the Display
LCD_INIT();
LCD_WRITE('R',0);

LCD_WRITE('P',1);
LCD_WRITE('M',2);
LCD_WRITE(':',3);
LCD_WRITE(0x200,4);
//Turn On CCP1
OpenCapture1( C1_EVERY_4_RISE_EDGE & CAPTURE_INT_OFF );
//Turn On Timer1
OpenTimer1( TIMER_INT_ON & T1_SOURCE_INT & T1_PS_1_1 & T1_16BIT_RW );
WriteTimer1( 0x0000 );
//Setup Interrupts
RCON = 0b000000000;
INTCON = 0b11000000;
PIE1 = 0b00000101;
while(1)
{
//**********************************************
********
//Formula For Calculating RPMs -> Rotations Per
Minute:
// [60 sec * (Fosc / 4)] / [(captured_time)]
//**********************************************
********
//**********************************************
********
//A Little Explaination:
// (1) Fosc = 4MHz
// (2) [captured_time] because we trigger interr
upt every rising edge
//**********************************************
********
cur_cap_val = 60000000 /((cap_val>>2));
//**********************************************
********
//Don't Show Junk Data
//RPMs Should Always Be between 1200 -> 3200
//**********************************************
********
if( cur_cap_val > 4000 || cur_cap_val < 1000)
{
array_2[4] = '\0';
array_2[3] = '\0';
array_2[2] = '\0';
array_2[1] = '\0';
array_2[0] = '0';
}
else
{
ultoa(cur_cap_val,array_2);
}
//**********************************************
********

//Convert The RPM Number To A String (Character


Array)
//**********************************************
********
//**********************************************
********
//Output The RPM Character String To The LCD Dis
play
//**********************************************
********
if( isdigit( (unsigned char) array_2[4] ))
{
LCD_WRITE( (unsigned char) array_2[4],8)
;
LCD_WRITE( (unsigned char) array_2[3],7)
;
LCD_WRITE( (unsigned char) array_2[2],6)
;
LCD_WRITE( (unsigned char) array_2[1],5)
;
LCD_WRITE( (unsigned char) array_2[0],4)
;
}
else if( isdigit( (unsigned char) array_2[3] ))
{
LCD_WRITE( 0x20,4);
LCD_WRITE( (unsigned char) array_2[3],8)
;
LCD_WRITE( (unsigned char) array_2[2],7)
;
LCD_WRITE( (unsigned char) array_2[1],6)
;
LCD_WRITE( (unsigned char) array_2[0],5)
;
}
else if( isdigit( (unsigned char) array_2[2] ))
{
LCD_WRITE( 0x20,4);
LCD_WRITE( 0x20,5);
LCD_WRITE( (unsigned char) array_2[2],8)
;
LCD_WRITE( (unsigned char) array_2[1],7)
;
LCD_WRITE( (unsigned char) array_2[0],6)
;
}
else if( isdigit( (unsigned char) array_2[1] ) )
{
LCD_WRITE( 0x20,4);
LCD_WRITE( 0x20,5);
LCD_WRITE( 0x20,6);
LCD_WRITE( (unsigned char) array_2[1],8)
;
LCD_WRITE( (unsigned char) array_2[0],7)
;
}
else if( isdigit( (unsigned char) array_2[0] ) )
{

LCD_WRITE(
LCD_WRITE(
LCD_WRITE(
LCD_WRITE(
LCD_WRITE(

0x20,4);
0x20,5);
0x20,6);
0x20,7);
(unsigned char) array_2[0],8)

;
}
//**********************************************
********
//A Small Delay, The Display Doesn't Need To Ref
resh Too Often....
//**********************************************
********
Delay1KTCYx(100);
}
}
//******************************************************
//
Function: void LCD_INIT(void)
//
//
Description:
//
The 16x2 LCD Display requires a specific startup sequence
// to initialize itself. This sequence (1) clears the display,
//
(2) moves the cursor to home, (3) resets the function code
// (4) turns the display on, and (5) sets the entry mode
//******************************************************
void LCD_INIT(void)
{
//Clear Display
LCD_DATA = 0b00000001;
LCD_RS = 0;
LCD_RW = 0;
LCD_E = 1;
Delay100TCYx(1);
LCD_E = 0;
//Return Home
LCD_DATA = 0b00000010;
LCD_RS = 0;
LCD_RW = 0;
LCD_E = 1;
Delay100TCYx(1);
LCD_E = 0;
Delay1KTCYx(2);
//Function Set
LCD_DATA = 0b00110000;
LCD_RS = 0;
LCD_RW = 0;
LCD_E = 1;
Delay100TCYx(1);
LCD_E = 0;

//Display On, Cursor Off, No Blinking Cursor


LCD_DATA = 0b00001100;
LCD_RS = 0;
LCD_RW = 0;
LCD_E = 1;
Delay100TCYx(1);
LCD_E = 0;
//Entry Mode Set
LCD_DATA = 0b00000110;
LCD_RS = 0;
LCD_RW = 0;
LCD_E = 1;
Delay100TCYx(1);
LCD_E = 0;
}
//******************************************************
//
Function: void LCD_WRITE(unsigned char, unsigned int);
//
//
Description:
//
This functions writes an alpha-numeric character to
// the LCD at a specified location (0 to 15). Since the
// LCD is initialized for one 16 character line, a maximum
// of 16 characters can fit on the display.
//******************************************************
void LCD_WRITE(unsigned char letter, unsigned int location)
{
//Move Cursor To Location
//If Location is larger than 15, ignore
if(location < 16)
{
//Set Cursor Position
LCD_DATA = location ^ 0b10000000;
LCD_RS = 0;
LCD_RW = 0;
LCD_E = 1;
Delay100TCYx(1);
LCD_E = 0;
}
//Print Letter
LCD_DATA = letter;
LCD_RS = 1;
LCD_RW = 0;
LCD_E = 1;
Delay100TCYx(1);
LCD_E = 0;
}
//INTERRUPT CONTROL
#pragma code InterruptVectorHigh = 0x08
8 low priority)
void InterruptVectorHigh (void)
{
_asm

//interrupt pointer address (0x1

//assembly code starts

goto InterruptHandlerHigh
_endasm
}
#pragma code
#pragma interrupt InterruptHandlerHigh

//interrupt control
//assembly code ends
//end interrupt control

//******************************************************
//
Function: void InterruptHandlerHigh(void)
//
//
Description:
//
The interrupt handler is triggered either (1) when the
// 4th rising edge is detected by the CCP1 module or (2)
// when Timer1 overflows 0xFFFF -> 0x000. When the CCP1
// module interrupts, the Timer1 value is read and stored.
// When the Timer1 module interrupts, the stored capture
// value is incremented by 0xFFFF (65535).
//******************************************************
void InterruptHandlerHigh(void)
// Declaration of InterruptHandler
{
//Check If TMR1 Interrupt Flag Is Set
if(PIR1bits.CCP1IF){
//Get Timer1 Value For the 4th Detected Rising E
dge;
cap_val = ReadTimer1();
//Clear Timer
WriteTimer1( 0x0000 );
//Clear CCP1 Overflow Flag Bit
PIR1bits.CCP1IF = 0;
}
//Check If CCP1 Interrupt Flag Is Set
else if(PIR1bits.TMR1IF){
//Timer Over Flowed: Add 0xFFFF To Current Captu
re Value
//This Is Not Used, But Would Be Necessa
ry For Tracking Less Than 1200 RPMs
cap_val += 65535;
//Clear Timer1 Overflow Flag Bit
PIR1bits.TMR1IF = 0;
}
//Re-enable Global Interrupts
INTCONbits.GIE = 1;
}

Você também pode gostar