Выбрать главу

Thus, TMR0L should be loaded with 100. The value to be loaded into TMR0 control register T0CON can then be found as:

 

Thus, T0CON register should be loaded with hexadecimal 0xC4. The next register to be configured is the interrupt control register INTCON, where we will disable priority based interrupts and enable the global interrupts and TMR0 interrupts:

 

Taking the don’t-care entries (X) as 0, the hexadecimal value to be loaded into register INTCON is 0xA0.

When an interrupt occurs, the program automatically jumps to the interrupt service routine. Inside this routine we have to reload register TMR0L, reenable the TMR0 interrupts, and clear the TMR0 interrupt flag bit. Setting INTCON register to 0x20 reenables the TMR0 interrupts and at the same time clears the TMR0 interrupt flag.

The operations to be performed can thus be summarized as follows:

In the main program:

• Load TMR0L with 100

• Set T0CON to 0xC4

• Set INTCON to 0xA0

• Increment the counter with 1-second delays

In the interrupt service routine:

• Re-load TMR0L to 100

• Refresh displays

• Set INTCON to 0x20 (reenable TMR0 interrupts and clear timer interrupt flag)

Project Hardware

The circuit diagram of this project is same as in Figure 6.32 where a dual 7-segment display is connected to PORTB and PORTC of a PIC18F452 microcontroller.

Project PDL

The PDL of the project is shown in Figure 6.35. The program is in two sections: the main program and the interrupt service routine. Inside the main program, TMR0 is configured to generate interrupts every 5ms and the counter is incremented with a one-second delay. Inside the interrupt service routine, the timer interrupt is reenabled and the display digits are refreshed alternately every 5ms.

MAIN PROGRAM:

 START

  Configure PORTB as outputs

  Configure PORTC as outputs

  Clear variable Cnt to 0

  Configure TMR0 to generate interrupts every 5ms

  DO FOREVER

   Increment Cnt between 0 and 99

   Delay 1 second

  ENDDO

 END

INTERRUPT SERVICE ROUTINE:

 START

  Re-configure TMR0

  IF Digit 1 updated THEN

   Update digit 2

  ELSE

   Update digit 1

  END

 END

Figure 6.35: PDL of the project

Project Program

The program is called SEVEN4.C, and the program listing is given in Figure 6.36. At the beginning of the main program PORTB and PORTC are configured as outputs. Then register T0CON is loaded with 0xC4 to enable the TMR0 and set the prescaler to 32. TMR0L register is loaded with 100 so that an interrupt is generated after 5ms. The program then enters an endless loop where the value of Cnt is incremented every second.

/*********************************************************************

                 Dual 7-SEGMENT DISPLAY COUNTER

                 ==============================

In this project two common cathode 7-segment LED displays are connected to

PORTC of a PIC18F452 microcontroller and the microcontroller is operated

from a 4MHz resonator. Digit 1 (left digit) enable pin is connected to port

pin RB0 and digit 2 (right digit) enable pin is connected to port pin RB1

of the microcontroller.

The program counts up from 0 to 99 with one second delay between each count.

The display is updated in a timer interrupt service routine at every 5ms.

Author: Dogan Ibrahim

Date:   July 2007

File:   SEVEN4.C

**********************************************************************/

#define DIGIT1 PORTB.F0

#define DIGIT2 PORTB.F1

unsigned char Cnt = 0;

unsigned char Flag = 0;

//

// This function finds the bit pattern to be sent to the port to display a

// number on the 7-segment LED. The number is passed in the argument list

// of the function.

//

unsigned char Display(unsigned char no) {

 unsigned char Pattern;

 unsigned char SEGMENT[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,

  0x7D,0x07,0x7F,0x6F};

 Pattern = SEGMENT[no]; // Pattern to return

 return (Pattern);

}

//

// TMR0 timer interrupt service routine. The program jumps to the ISR at

// every 5ms.

//

void interrupt() {

 unsigned char Msd, Lsd;

 TMR0L = 100;           // Re-load TMR0

 INTCON = 0x20;         // Set T0IE and clear T0IF

 Flag = ~Flag;          // Toggle Flag

 if (Flag == 0)         // Do digit 1

 {

  DIGIT2 = 0;

  Msd = Cnt / 10;       // MSD digit

  PORTC = Display(Msd); // Send to PORTC

  DIGIT1 = 1;           // Enable digit 1

 } else {               // Do digit 2

  DIGIT1 = 0;           // Disable digit 1

  Lsd = Cnt % 10;       // LSD digit

  PORTC = Display(Lsd); // Send to PORTC

  DIGIT2 = 1;           // Enable digit 2

 }

}

//

// Start of MAIN Program. configure PORTB and PORTC as outputs.

// In addition, configure TMR0 to interrupt at every 10ms

//

void main() {

 TRISC = 0;                // PORTC are outputs

 TRISB = 0;                // RB0, RB1 are outputs

 DIGIT1 = 0;               // Disable digit 1

 DIGIT2 = 0;               // Disable digit 2

 //

 // Configure TMR0 timer interrupt

 //

 T0CON = 0xC4;             // Prescaler = 32

 TMR0L = 100;              // Load  TMR0L with 100

 INTCON = 0xA0;            // Enable TMR0 interrupt

 Delay_ms(1000);

 for(;;)                   // Endless loop