The back light of the LCD will blink on and off every second, while the counter on the LCD will increase until it reaches 199 then reset back to 0. The counting of second is implemented using an interrupt service routine. The guide will be divided in to 2 parts, 1st part dealing with the setting on Timer0 and the second on the interrupt service routine. TimerThe first part would be setting up the timer to overflow every 1s. Timer overflow occurs when TMR0 go froms 0xFFFF to 0x0000. Since the PIC is running at 8Mhz, the reload needed for the timer can be calculated. To achieve overflow 1s the timer will be set in 16 bit mode. Prescaler of timer0 is set to 64 and the reload value to 34286 or 0x85EE. With this value 1s overflow can be achieved. The calculation below give the time taken for the overflow with TMR0 set to 34286. (1 / (8 000 000 / 4)) * 64 is the time for each count of timer0. (65 536 - 34 286) * (1 / (8 000 000 / 4)) * 64 = 1 Code below is used to set the timer in to the required reload value and mode. T0CON = 0x85; TMR0H = 0x85; TMR0L = 0xEE; InterruptThere are 2 interrupt vector in PIC18, the high and low priority interrupt. Interrupt is settings are configured with INTCON register. IPEN bit in RCON need to be set to enable the interrupt priority levels. INTCON = 0x20; INTCON2 = 0x04; //TMR0 high priority RCONbits.IPEN = 1; //enable priority levels Since that C18 does not create ISR automatically, a goto instruction must be created at the vector to redirect the interrupt to the appropriate ISR. In this example only the high priority ISR is used, the code below shows the setting for the ISR. A code section is created at 0x08 which is the high interrupt vector to redirect the interrupt to the ISR. Inside the ISR the timer period is reloaded back to 34286 so that 1s interrupt can be achieved. check is set in the ISR to tell the main program to update the LCD. void high_isr(void); /*****************High priority interrupt vector **************************/ #pragma code high_vector=0x08 void interrupt_at_high_vector(void) { _asm GOTO high_isr _endasm } #pragma code /*****************High priority ISR **************************/ #pragma interrupt high_isr void high_isr (void) { if (INTCONbits.TMR0IF){ // Interrupt Check INTCONbits.TMR0IF = 0; TMR0H = 0x85; //Timer Reload to count 1s TMR0L = 0xEE; second++; if (second == 200) second = 0; check = 1; } } If low priority ISR is needed the below code show the declaration for it. The ISR vector for low priority is at 0x18. void low_isr(void); void high_isr(void);#pragma code low_vector=0x18 void interrupt_at_low_vector(void) { _asm GOTO low_isr _endasm } #pragma code /* return to the default code section */ #pragma interruptlow low_isr void low_isr (void) { /* ISR code goes here */ } Overall ProgramThe overall program is attached together in this guide. Output as shown in the picture above can be observed when the code is compiled and downloaded into the PIC. Code Generation ToolThere is a Google gadget developed to generate the needed reload value for the register at software page. |
Guides >