mobashir
Newbie level 3
- Joined
- Aug 4, 2012
- Messages
- 4
- Helped
- 0
- Reputation
- 0
- Reaction score
- 0
- Trophy points
- 1,281
- Activity points
- 1,361
#include <p18f452.h>
#include <capture.h>
#include <timers.h>
#include <stdlib.h>
#include <delays.h>
#include <ctype.h>
//LCD Pins
#define LCD_RS PORTBbits.RB0
#define LCD_RW PORTBbits.RB1
#define LCD_E 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 Set To Outputs
TRISA = 0x00;
//PORTC Set To Inputs (CCP1 is on PortC)
TRISC = 0xFF;
//PORTD Set To Outputs
TRISD = 0x00; // D0~~D7
//PORTB Set To Outputs
TRISB = 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/4) * 7]
//******************************************************
//******************************************************
//A Little Explaination:
// (1) Fosc = 4MHz
// (2) [captured_time / 4] because we trigger interrupt every 4th rising edge
// (3) Multiply [captured_time / 4] by 7 because the fan has 7 blades, this yields time for 1 full rotation in seconds
//******************************************************
cur_cap_val = 60000000 /((cap_val>>2)*7);
//******************************************************
//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 Display
//******************************************************
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( 0x20,4);
LCD_WRITE( 0x20,5);
LCD_WRITE( 0x20,6);
LCD_WRITE( 0x20,7);
LCD_WRITE( (unsigned char) array_2[0],8);
}
//******************************************************
//A Small Delay, The Display Doesn't Need To Refresh 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 //interrupt pointer address (0x18 low priority)
void InterruptVectorHigh (void)
{
_asm //assembly code starts
goto InterruptHandlerHigh //interrupt control
_endasm //assembly code ends
}
#pragma code
#pragma interrupt InterruptHandlerHigh //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 Edge;
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 Capture Value
//This Is Not Used, But Would Be Necessary For Tracking Less Than 1200 RPMs
cap_val += 65535;
//Clear Timer1 Overflow Flag Bit
PIR1bits.TMR1IF = 0;
}
//Re-enable Global Interrupts
INTCONbits.GIE = 1;
}
#include <capture.h>
#include <timers.h>
#include <stdlib.h>
#include <delays.h>
#include <ctype.h>
//LCD Pins
#define LCD_RS PORTBbits.RB0
#define LCD_RW PORTBbits.RB1
#define LCD_E 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 Set To Outputs
TRISA = 0x00;
//PORTC Set To Inputs (CCP1 is on PortC)
TRISC = 0xFF;
//PORTD Set To Outputs
TRISD = 0x00; // D0~~D7
//PORTB Set To Outputs
TRISB = 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/4) * 7]
//******************************************************
//******************************************************
//A Little Explaination:
// (1) Fosc = 4MHz
// (2) [captured_time / 4] because we trigger interrupt every 4th rising edge
// (3) Multiply [captured_time / 4] by 7 because the fan has 7 blades, this yields time for 1 full rotation in seconds
//******************************************************
cur_cap_val = 60000000 /((cap_val>>2)*7);
//******************************************************
//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 Display
//******************************************************
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( 0x20,4);
LCD_WRITE( 0x20,5);
LCD_WRITE( 0x20,6);
LCD_WRITE( 0x20,7);
LCD_WRITE( (unsigned char) array_2[0],8);
}
//******************************************************
//A Small Delay, The Display Doesn't Need To Refresh 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 //interrupt pointer address (0x18 low priority)
void InterruptVectorHigh (void)
{
_asm //assembly code starts
goto InterruptHandlerHigh //interrupt control
_endasm //assembly code ends
}
#pragma code
#pragma interrupt InterruptHandlerHigh //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 Edge;
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 Capture Value
//This Is Not Used, But Would Be Necessary For Tracking Less Than 1200 RPMs
cap_val += 65535;
//Clear Timer1 Overflow Flag Bit
PIR1bits.TMR1IF = 0;
}
//Re-enable Global Interrupts
INTCONbits.GIE = 1;
}