Circuito:


Codigo:
#include <p24fj128ga010.h>
#include "main.h"
_CONFIG2( FNOSC_FRCPLL & OSCIOFNC_OFF ); // Internal oscillator - 4xPLL giving 16 MIPS
// pin RC15 has the oscillator
//Function prototypes
extern void update_display(const unsigned int min, const unsigned int tens, const unsigned int units, const unsigned int tenths);
extern unsigned int poll_switch_SW3();
//Global variables
unsigned int minutes; //Minutes - For display 0
unsigned int units; //Seconds (tens) - For display 1
unsigned int tens; //Seconds (units) - For display 2
unsigned int tenths; //Tenths of a second - For display 3
unsigned int displayOn=0; //Switch for Display ON or OFF - shared by two ISR routines
unsigned int IC1BUFFERVAL; //Used to read IC1 timer buffer
io_port_A *display = (io_port_A*)&LATA; // Address of Output latch (that connects to PORTA) - it is SAFER to write to the LATCH
io_port_A *inputs = (io_port_A*)&PORTA; // PORTA Address (you cannot read from LATA)
//Main code
int main()
{
//Configure the device to use the internal oscillator
OSCCONbits.COSC = 1u; // Internal oscillator with PLL
CLKDIVbits.RCDIV = 0u; // Internal oscillator not divided (8MHz)
CLKDIVbits.DOZEN =0; // No post scaling
CLKDIVbits.DOZE =0; //
//set up ports
TRISA = 0x00F0; //Least-significant 4 and most significant 8 bits are digital outputs
LATA = 0x0000; //Write zero to PORTA via the latch
//Initialisation of variables and display
minutes = 0;
units = 0;
tens = 0;
tenths = 0;
update_display(1,2,3,4);
update_display(minutes, tens, units, tenths);
//TIMER1 Configuration Register
T1CON = 0;
T1CONbits.TCKPS = 0b11; //Prescale = 256
T1CONbits.TON = 1; //Timer on
TMR1 = 0; //Reset Timer Counter
//Configure TIMER1 interrupt
_T1IP = 4; //Interrupt priority = 4
PR1 = 6250-1; //Period Register - set for 0.1s
_T1IF = 0; //Clear timer interrupt flag
//Configure the input capture (IC1)
_IC1IP = 4; //Set interrupt priority for the Input Capture
_TRISD9 = 1; //Set RD8 to be an input
IC1CON = 0x0002; //InputCaptureCONfiguration register - falling edge
_IC1IF = 0; //Reset the Input Capture 1 Interrupt Flag
//ENABLE INTERRUPTS
_IC1IE = 1; //Set the Input Capture 1 Interrupt Enable
_T1IE = 1; //Switch on timer 1 interrupt enable
//Main Loop
while (1)
{
Idle(); //Switch off main core - peripherals continue
asm("nop"); //Woken by interrupt (TIMER 1 or INPUT CAPTURE 1)
update_display(minutes, tens, units, tenths);
} //end while
return 0;
}
//************************************************************************
//********************* INTERRUPT SERVICE ROUTINES ***********************
//************************************************************************
//ISR FOR THE TIMER
void __attribute__((interrupt, no_auto_psv)) _T1Interrupt()
{
//Increment the counter on every interrupt
tenths++;
//Update minutes, tens, units and tenths for the display (BCD)
//Check for an overflow - ripple to the next digit
if (tenths == 10) {
tenths = 0;
units++;
}
if (units == 10) {
units = 0;
tens++;
}
if (tens == 6) {
tens = 0;
minutes++;
}
if (minutes == 10) {
minutes=0;
}
//Reset interrrupt flag before returning
_T1IF = 0;
}
//ISR FOR THE INPUT CAPTURE
void __attribute__((interrupt, no_auto_psv)) _IC1Interrupt()
{
IC1CON = 0x0002;
T1CON = poll_switch_SW3;
//Read the IC1 buffer (we are not using this yet)
IC1BUFFERVAL = IC1BUF; //This is needed to prevent buffer overflow
_IC1IF = 0; //Reset the interrupt flag
}//