2.2 Bare Metal Code
First, the Watchdog Timer has to be disabled and Low-Voltage Programming (LVP) has to be enabled using the following pragma code:
#pragma config WDTE = OFF /* WDT operating mode->WDT Disabled */ #pragma config LVP = ON /* Low voltage programming enabled, RE3 pin is MCLR */
The following function initializes the system clock to have the HFINTOSC oscillator as input clock and to run at 1 MHz:
static void CLK_Initialize(void) { OSCCON1 = 0x60; /* set HFINTOSC as new oscillator source */ OSCFRQ = 0x00; /* set HFFRQ to 1 MHz */ }
The following function initializes the RE0 pin (corresponding to the on-board LED0) as output pin:
static void PORT_Initialize(void) { TRISEbits.TRISE0 = 0; /* configure RE0 as output */ }
The following function initializes Timer0 in 8-bit mode, sets the prescaler to 1:16, loads TMR0H and TMR0L registers, clears the Interrupt flag, and enables the interrupt and Timer0:
static void TMR0_Initialize(void)
{
T0CON1 = 0x94; /* Select LFINTOSC, set the prescaler to 1:16, Disable TMR0 sync */
TMR0H = 0xC1; /* Load the compare value to TMR0H */
TMR0L = 0x00; /* Load the reset value to TMR0L */
PIR0bits.TMR0IF = 0; /* clear the interrupt flag */
PIE0bits.TMR0IE = 1; /* enable TMR0 interrupt */
T0CON0 = 0x80; /* Configure TMR0 in 8-bit mode and enable TMR0 */
}
The following function enables the global and peripheral interrupts:
static void INTERRUPT_Initialize(void) { INTCONbits.GIE = 1; /* Enable the Global Interrupts */ INTCONbits.PEIE = 1; /* Enable the Peripheral Interrupts */ }
static void TMR0_ISR(void)
{
PIR0bits.TMR0IF = 0; /* clear the TMR0 interrupt flag */
LATEbits.LATE0 = ~LATEbits.LATE0; /* toggle LED0 */
}
void __interrupt() INTERRUPT_InterruptManager (void)
{
/* Check if TMR0 interrupt is enabled and if the interrupt flag is set */
if(PIE0bits.TMR0IE == 1 && PIR0bits.TMR0IF == 1)
{
TMR0_ISR();
}
}
void main(void)
{
CLK_Initialize();
PORT_Initialize();
TMR0_Initialize();
INTERRUPT_Initialize();
while(1)
{
;
}
}