Escolar Documentos
Profissional Documentos
Cultura Documentos
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
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);
}
//**********************************************
********
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;
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;
}