/*
* adapted from Microchip
* C:/MCC18/example/users_guide/example1/leds.c
* The following sample application will flash the Junebug's LEDs connected to PORTA
* PIC18F1320 microcontroller.
*
*
* This sample covers the following items:
*
* 1. Interrupt handling (#pragma interruptlow, interrupt vectors,
* interrupt service routines)
* 2. System header files
* 3. Processor-specific header files
* 4. #pragma sectiontype
* 5. Inline assembly
* 6. Display multiplexing using timer0.
*/
/*
* Build in the MPLAB IDE using C18 and device type 181320.
* Project requires linker file 18f1320i.lkr
*/
#include <p18cxxx.h>
#include <timers.h>
#include <delays.h>
#define byte unsigned char
#define delay1 100
void timer_isr (void);
static unsigned char s_count = 0;
byte ledBits; // LEDs one per bit, 0 is off, 1 is on
byte ledScan; // used to select one LED at a time, shifting bit
// Delay of 1ms calculation
// Cycles = (TimeDelay * Fosc) / 4
// Cycles = (1ms * 32MHz) / 4
// Cycles = 8,000
void delay_ms(long t) // delays t millisecs
{
do
{
Delay1KTCYx(8); // time will be a small bit over because of overhead, close % wise
} while(--t);
}
/*
* For PIC18xxxx devices, the low interrupt vector is found at 000000018h.
* Change the default code section to the absolute code section named
* low_vector located at address 0x18.
*/
#pragma code low_vector=0x18
void low_interrupt (void)
{
/*
* Inline assembly that will jump to the ISR.
*/
_asm GOTO timer_isr _endasm
}
/*
* Returns the compiler to the default code section.
*/
#pragma code
/*
* Specifies the function timer_isr as a low-priority interrupt service
* routine. This is required in order for the compiler to generate a
* RETFIE instruction instead of a RETURN instruction for the timer_isr
* function.
*/
#pragma interruptlow timer_isr
/*
* Define the timer_isr function. Notice that it does not take any
* parameters, and does not return anything (as required by ISRs).
*/
void
timer_isr (void)
{
/*
* Clears the TMR0 interrupt flag to stop the program from processing the
* same interrupt multiple times.
*/
INTCONbits.TMR0IF = 0;
/*
* Turn on a single LED each time we visit this ISR
*/
if (ledBits == 0) // just turn all LEDs off
{
ledScan = 1;
LATA = 0x00;
TRISA = 0xFF;
return;
}
// skip to next active LED
while ( (ledScan & ledBits) == 0)
{
ledScan = ledScan<<1;
if (ledScan > 0x20)
ledScan = 1;
}
// We could store the LATA and TRISA values using 2 arrays but we will save
// that for another example.
switch (ledBits&ledScan)
{
case 0x01:
LATAbits.LATA0 = 1; // muliplexing hardware dependant code
LATAbits.LATA6 = 0;
TRISA = 0b10000000;
break;
case 0x02:
LATAbits.LATA0 = 0;
LATAbits.LATA6 = 1;
TRISA = 0b10000000;
break;
case 0x04:
LATAbits.LATA6 = 1;
LATAbits.LATA7 = 0;
TRISA = 0b00000001;
break;
case 0x08:
LATAbits.LATA6 = 0;
LATAbits.LATA7 = 1;
TRISA = 0b00000001;
break;
case 0x10:
LATAbits.LATA0 = 0;
LATAbits.LATA7 = 1;
TRISA = 0b01000000;
break;
case 0x20:
LATAbits.LATA0 = 1;
LATAbits.LATA7 = 0;
TRISA = 0b01000000;
break;
}
ledScan = ledScan<<1;
if (ledScan > 0x20)
{
ledScan = 1; // warp back to LED1
}
}
void main (void)
{
// speed up the clock to 8MHz, 18F1320
OSCCONbits.IRCF0=1;
OSCCONbits.IRCF1=1;
OSCCONbits.IRCF2=1;
/*
* Initialize the special function registers TRISA and PORTA.
*/
TRISA = 0;
PORTA = 0;
/*
* Enable the TMR0 interrupt, setting up the timer as an internal
* 8-bit clock. Not picky about value just let it overflow
*/
OpenTimer0 (TIMER_INT_ON & T0_SOURCE_INT & T0_8BIT);
/*
* Enable global interrupts.
*/
INTCONbits.GIE = 1;
ledScan = 1;
while (1)
{
int idx;
for (idx=0; idx<5; idx++)
{
ledBits = 0b00101010; // turn on LEDs 1, 3 and 5
delay_ms(delay1);
ledBits = 0b00010101; // turn on LEDs 2, 4 and 6
delay_ms(delay1);
}
ledBits = 0;
delay_ms(delay1);
for (ledBits=3; ledBits<0x20; ledBits=ledBits<<1)
{
delay_ms(delay1);
}
for (; ledBits>0x01; ledBits=ledBits>>1)
{
delay_ms(delay1);
}
ledBits = 0;
delay_ms(delay1);
}
}