I had a 4x4 LED matrix setup using a Pic16F873A and swapped the chip to a (same pinout) Pic18F2620. I wanted to see how difficult it would be to run the matrix completely on interrupts.
I setup a 5mS interrupt using Timer 2.
And an ISR to multiplex the LED - stored in a 16 bit variable called LEDs
In the main lood I did a simple scrolling LED routine,
And this is what it looked like,
Here's the complete code for anyone wanting to know about interrupts. The config statements are longer than the actual code!!!
Mike.
A question for knowledgeable people,
The two instructions
Can't be combined into
I can't think why it isn't permitted. There must be a simple reason that I'm not seeing.
I setup a 5mS interrupt using Timer 2.
Code:
//setup 5mS interrupt = 8,000,000/16 = 500,000/10 = 50,000 set PR2=249 = 200 = 5mS
T2CON=0b01001110; //pre=16 post=10
PR2=249;
TMR2IE=1; //timer2 interrupts enable
GIE=1;
PEIE=1;
Code:
//row 0 is RC7 (to RC4) and Anode (+)
//col 0 is RC0 (to RC3) and Cathode (-)
void __interrupt(high_priority) myHighIsr(void){
if(TMR2IE && TMR2IF){
uint16_t temp=LEDs; //make copy of LED variable
col++; //increment column
col&=3; //and wrap around to zero
temp<<=(col*4); //get 4 LEDs in top bits
temp&=0xf000; //get rid of unwanted LEDs
temp>>=8; //shift to bits 4 to 7
temp|=(0x0f-(1<<col)); //turn off unwanted columns
LATC|=0x0f; //turn all columns off
LATC=(uint8_t)temp; //turn on relevant LEDs
TMR2IF=0;
}
}
Code:
while (1){
__delay_ms(50); //short delay
if(dir) LEDs>>=1; //if dir = 1 then move right
else LEDs<<=1; //else move left
if(LEDs&1) dir=0; //if we reached the right end then go left
if(LEDs&0x8000) dir=1; //if we reached the left end then go right
}
Here's the complete code for anyone wanting to know about interrupts. The config statements are longer than the actual code!!!
Code:
// CONFIG1H
#pragma config OSC = INTIO67 // Oscillator Selection bits (Internal oscillator block, port function on RA6 and RA7)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled)
#pragma config IESO = ON // Internal/External Oscillator Switchover bit (Oscillator Switchover mode enabled)
// CONFIG2L
#pragma config PWRT = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 3 // Brown Out Reset Voltage bits (Minimum setting)
// CONFIG2H
#pragma config WDT = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
// CONFIG3H
#pragma config CCP2MX = PORTC // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset)
#pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
// CONFIG4L
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
// CONFIG5L
#pragma config CP0 = OFF // Code Protection bit (Block 0 (000800-003FFFh) not code-protected)
#pragma config CP1 = OFF // Code Protection bit (Block 1 (004000-007FFFh) not code-protected)
#pragma config CP2 = OFF // Code Protection bit (Block 2 (008000-00BFFFh) not code-protected)
#pragma config CP3 = OFF // Code Protection bit (Block 3 (00C000-00FFFFh) not code-protected)
// CONFIG5H
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
// CONFIG6L
#pragma config WRT0 = OFF // Write Protection bit (Block 0 (000800-003FFFh) not write-protected)
#pragma config WRT1 = OFF // Write Protection bit (Block 1 (004000-007FFFh) not write-protected)
#pragma config WRT2 = OFF // Write Protection bit (Block 2 (008000-00BFFFh) not write-protected)
#pragma config WRT3 = OFF // Write Protection bit (Block 3 (00C000-00FFFFh) not write-protected)
// CONFIG6H
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 (000800-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 (004000-007FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF // Table Read Protection bit (Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF // Table Read Protection bit (Block 3 (00C000-00FFFFh) not protected from table reads executed in other blocks)
// CONFIG7H
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)
#include <xc.h>
#include <stdint.h>
#define _XTAL_FREQ 32000000
volatile uint8_t col=0,dir;
uint16_t LEDs;
//row 0 is RC7 (to RC4) and Anode (+)
//col 0 is RC0 (to RC3) and Cathode (-)
void __interrupt(high_priority) myHighIsr(void){
if(TMR2IE && TMR2IF){
uint16_t temp=LEDs; //make copy of LED variable
col++; //increment column
col&=3; //and wrap around to zero
temp<<=(col*4); //get 4 LEDs in top bits
temp&=0xf000; //get rid of unwanted LEDs
temp>>=8; //shift to bits 4 to 7
temp|=(0x0f-(1<<col)); //turn off unwanted columns
LATC|=0x0f; //turn all columns off
LATC=(uint8_t)temp; //turn on relevant LEDs
TMR2IF=0;
}
}
void main(void){
OSCCON=0b01110000; //8MHz
PLLEN=1; //x4=32MHz
//setup 5mS interrupt = 8,000,000/16 = 500,000/10 = 50,000 set PR2=249 = 200 = 5mS
T2CON=0b01001110; //pre=16 post=10
PR2=249;
TMR2IE=1; //timer2 interrupts enable
GIE=1;
PEIE=1;
TRISC=0; //all output
LEDs=0xf000;
dir=1;
while (1){
__delay_ms(50); //short delay
if(dir) LEDs>>=1; //if dir = 1 then move right
else LEDs<<=1; //else move left
if(LEDs&1) dir=0; //if we reached the right end then go left
if(LEDs&0x8000) dir=1; //if we reached the left end then go right
}
}
Mike.
A question for knowledgeable people,
The two instructions
Code:
col++; //increment column
col&=3; //and wrap around to zero
Code:
++col&=3;