9.2 Bare Metal Code
The first step will be to configure the microcontroller to disable the Watchdog Timer (WDT) and to enable Low-Voltage Programming (LVP).
#pragma config WDTE = OFF /*disable Watchdog*/
#pragma config LVP = ON /* Low voltage programming enabled, RE3 pin is MCLR */
The following constants need to be defined:
#define Timer2Period 0x2F /* TMR2 Period is 100ms */ #define Timer4Period 0xF1 /* TMR4 Period is 500ms */
The CLK_Initialize
function initializes the HFINTOSC
internal oscillator:
static void CLK_Initialize(void)
{
/* set HFINTOSC Oscillator */
OSCCON1 = 0x60;
/* set HFFRQ to 1 MHz */
OSCFRQ = 0x00;
}
The PPS_Initialize
function has the role to configure the
RC7 peripheral select as input for TMR4:
static void PPS_Initialize(void) { /* Set RC7 as input for TMR4 (T4IN) */ T4INPPS = 0x17; }
PORT_Initialize
has the role to configure the RC7, input
channel, and RE0 output for LED0 pins:
static PORT_Initialize(void)
{
/* Set RC7 pin as digital */
ANSELC = 0x7F;
/* Set RE0 pin as output */
TRISE = 0x06;
/* Enable weak pull-up on pin RC7 */
WPUC = 0x80;
}
The TMR2_Initialize
function sets the clock source and the
registers needed to generate an 100 ms period:
static void TMR2_Initialize(void)
{
/* TMR2 Clock source, LFINTOSC (00100) has 31 kHz */
T2CLKCON = 0x04;
/* T2PSYNC Not Synchronized; T2MODE Starts at T2ON = 1 and TMR2_ers = 0; T2CKPOL Rising Edge */
T2HLT = 0x02;
/* TMR2 external reset is TMR4_postscaled */
T2RST = 0x02;
/* TMR2 ON on; T2 CKPS Prescaler 1:64; T2 OUTPS Postscaler 1:1
Minimum timer period is 31 kHz/64 = 2.064516 ms */
T2CON = 0xE0;
/* Set TMR2 period, PR2 to 100ms */
T2PR = Timer2Period;
/* Clear the TMR2 interrupt flag */
PIR4bits.TMR2IF = 0;
/* Enabling TMR2 interrupt */
PIE4bits.TMR2IE = 1;
}
The TMR4_Initialize
function sets the clock source and the
registers needed to generate an 500 ms period:
static void TMR4_Initialize(void)
{
/* TMR4 Clock source, LFINTOSC (00100) has 31 kHz */
T4CLKCON = 0x04;
/* TMR4 in OneShot mode, Starts at TMR4_ers=0 and resets on TMR4_ers=1 */
T4HLT = 0x17;
/* TMR4 External reset signal selected by T4INPPS pin */
T4RST = 0;
/* TMR4 ON on; T4 CKPS Prescaler 1:64; T4 OUTPS Postscaler 1:1
Minimum timer period is 31 kHz/64 = 2.064516 ms */
T4CON = 0xE0;
/* Set TMR4 period, PR4 to 500ms */
T4PR = Timer4Period;
/* Clear the TMR4 interrupt flag */
PIR4bits.TMR4IF = 0;
}
The following initialization function will safely enable the Global and Peripherals interrupts, after all modules have been initialized with proper settings:
static void INTERRUPT_Initialize(void)
{
INTCONbits.GIE = 1; /* Enable Global Interrupts */
INTCONbits.PEIE = 1; /* Enable Peripheral Interrupts */
}
The next function handles the interrupts (in this case there is only one
interrupt), checks the status of the TMR2 Interrupt flag, and then calls the
TMR2_Interrupt
function.
static void __interrupt() INTERRUPT_InterruptManager(void)
{
if (INTCONbits.PEIE == 1)
{
if (PIE4bits.TMR2IE == 1 && PIR4bits.TMR2IF == 1)
{
TMR2_Interrupt();
}
}
}
The TMR2_Interrupt
clears the Interrupt flag and toggles the
LED0 (this will happen with Timer2 Period frequency).
static void TMR2_Interrupt(void)
{
/* Clear the TMR2 interrupt flag */
PIR4bits.TMR2IF = 0;
/* Toggle LED0 at the Timer2Period frequency */
LATEbits.LATE0 = ~LATEbits.LATE0;
}
The void main
function contains only the initialization
functions:
void main(void)
{
/* Initialize the device */
CLK_Initialize(); /* Oscillator Initialize function */
PPS_Initialize(); /* Peripheral select Initialize function */
PORT_Initialize(); /* Port Initialize function */
TMR2_Initialize(); /* TMR2 Initialize function */
TMR4_Initialize(); /* TMR4 Initialize function */
INTERRUPT_Initialize(); /* Interrupt Initialize function */
while (1)
{
;/* Add your application code */
}
}
If the RC7 pin is pulled to GND for more than the Timer4 Period (500 ms), TMR4 will trigger TMR2 to stop and act as a one-shot Reset.