AVR INTERRUPT PROGRAMMING

INTRODUCTION-

In this section, we learn the concept of interrupts and their programming. What is an Interrupt?

Definition-An event that requires the CPU to stop the current program execution and perform some service related to the event. Suppose a person named “Ram” is sleeping on his bed. Suddenly his phone ringed he wake up and receive his call from his mother. Ram talked to his mother who asking him whether he takes dinner or not? Ram replied to his mother that he takes dinner and he is sleeping. Then, Ram return to sleep. Now the phone call is an interrupt and talking of ram with his mother is an Interrupt Service routine (ISR) or an interrupt handler. Let we have connected two LED with microcontroller and written a program which blink an LED connected to PINB3. Another LED is connected to PINB4. Assume we have written a program code of 20 lines and at line number 18 an interrupt occurs. When CPU is executing program, it executes it line by line. We have written a program to blink LED connected to PINB3 and when an interrupt occur the LED connected at PIN3 stops blinking an LED connected to PINB4 start blinking. Before CPU executing line number 18, the LED connected to PINB3 starts blinking. And when CPU is at line number 18, current program execution stops and it moved to Interrupt Service Routine. Now at this ISR we have written another program which stops the blinking of LED connected to PINB3 and starts blinking of LED connected to PINB4.    In the same way, suppose CPU is executing some lines of code and an interrupt occurs then, CPU goes to ISR and give service to this interrupt. At ISR we have written another program which is executed by the CPU when interrupt occurs. Then, it resumes that line of code where it moves to ISR.

INTERRUPT VS POLLING-

Consider we have connected several devices with microcontroller. We can give service to each device by any of these two methods:

  1. Interrupt
  2. Polling

In interrupt method, whenever device needs the microcontroller’s service, the device notifies it by sending an interrupt signal. Upon receiving an interrupt signal, microcontroller stops whatever it is doing and serves the device. The program associated with interrupt is called Interrupt Service Routine (ISR) or interrupt handler.

In polling method, microcontroller continuously monitors the status of a given device; when certain condition is met, it gives service to that device. After that it moves to another device an continuously monitors its state. So, in polling method we continuously monitor the state of device and we can serve each of devices connected to microcontroller but it is not an efficient use of microcontroller. As every time CPU is busy in monitoring the state of device and we cannot do another work. Suppose at same time two devices wants the service of microcontroller so, in polling method we cannot provide service to two devices at same time. But in case of interrupt method, we have priority of each device connected to microcontroller. So the device having higher priority is served first. But polling method cannot give priority to devices. Also in interrupt method, microcontroller can ignore (mask) the device request. But it is not possible in case of polling method. The most important reason that preferred interrupt method over polling is that, in case of polling method CPU waste much of its time by checking the status condition of devices which not needed service. We have studied TIMERS IN AVR ,so we are familiar with TOV0 flag. When this flag is set, then TCNT0 register will be clear. In polling method, we have to continuously check whether TOV0 flag is set or not. When this flag set then, timer0 overflows. But in case of interrupt method, we don’t check status of TOV0 flag. When this flag set an interrupt is generated and that interrupt clears TCNT0 flag. We just have to enable that interrupt in our program code that clears TCNT0 flag.

 

INTERRUPT SERVICE ROUTINE-

For every interrupt there must be interrupt service routine (ISR), or interrupt handler. When an interrupt is invoked, the microcontroller runs the ISR. Generally, in most microprocessors, for every interrupt there is a fixed location in memory that holds the address of its ISR. The group of memory locations set aside to hold the memory location for ISRs is called INTERRUPT VECTOR TABLE.

STEPS IN EXECUTING AN INTERRUPT-

Upon activation of an interrupt microcontroller goes to following steps-

  1. It finishes the instruction it is currently executing and saves the address of next instruction (program counter) to the stack.
  2. It jumps to the fixed location of a memory called the interrupt vector table. In this interrupt vector table, microcontroller gets the address of ISR.
  3. The microcontroller starts executing ISR, until it reaches the last instruction of ISR, which is called RETI (return from interrupt).
  4. Upon execution of RETI, microcontroller returns to that place where it was interrupted. First it gets the program counter address from stack by popping the top bytes of the stack into program counter. Then, it starts executing from that address.

 

                        INTERRUPT VECTOR TABLE FOR AVR ATmega 32

INTERRUPT ROM LOCATION (hex)
Reset                     0000
External Interrupt Request 0                     0002
External Interrupt Request 1                     0004
External Interrupt Request 2                     0006
Timer/Counter 2 Compare Match                     0008
Timer/Counter 2 Overflow                     000A
Timer/Counter 1 Capture Match                     000C
Timer/Counter 1 Compare Match A                     000E
Timer/Counter 1 Compare Match B                     0010
Timer/Counter 1 Overflow                     0012
Timer/Counter 0 Compare Match                     0014
Timer/Counter 0 Overflow                     0016
SPI Transfer Complete                     0018
USART, Receive Complete                     001A
USART, Data Register Empty                     001C
USART, Transfer Complete                     001E
ADC Conversion Complete                     0020
EEPROM ready                     0022
Analog Comparator                     0024
Two-Wire Serial Interface ( )                     0026
Store Program Memory Ready                     0028

 

SOURCES OF INTERRUPTS IN AVR- 

There are many sources of interrupt in AVR depending on which peripheral is incorporated into the chip. The following are the some of the most widely used sources of interrupt in AVR-

  1. There are at least two interrupt set aside for each timers, one for overflow and another for compare match.
  2. Three interrupts are set aside for external hardware interrupts. Pins PIND2, PIND3 and PINB2 are for the external hardware interrupts INT0, INT1 and INT2.
  3. Serial communication’s USART has three interrupts, one for receive and two interrupts for transmit.
  4. One interrupt is for SPI data transfer.
  5. When analog to digital conversion complete there is an interrupt for this action too.

The AVR has many more interrupts, but we will cover only timers and external interrupts in this section.

Enabling and Disabling an Interrupt-

If RESET interrupt is enabled, then all interrupts are disabled that means none of interrupt will respond to microcontroller. We want to use an interrupt then, it should be enabled. To enable interrupt we have an separate register called SREG register (status register).

Here I bit makes the job for enabling all the interrupts. In interrupt vector table, we tabulated all interrupts of AVR microcontroller. To enable these interrupt we have to enable global interrupt by setting bit ‘I’ HIGH. To set bit ‘I’ in SREG register, we have special function “sei()”. By just writing this function in our program code we can enable global interrupts. But to use this function we have to include header file in which declaration of this function is present and that header file is-

      #include<avr/interrupt.h>

We have disable global interrupt by another function – “cli()”. This function disables (or clear bit ‘I’ in SREG register) global interrupt.

INTERRUPT PROGRAMMING STEPS-

Following are the programming steps to use interrupts-

  1. Include interrupt header file- we should include interrupt header file if we want to use interrupt in our program.
  2. cli( ) and sei( )- these functions disable and enable global interrupt.
  3. Defining ISR- to write an ISR (interrupt service routine) for an interrupt we use the following structure-

   ISR ( interrupt vector name )

{

// our program

}

For interrupt vector name we use the ISR name as given in following table-

INTERRUPT            ISR NAME
External Interrupt Request 0              INT0_vect
External Interrupt Request 1              INT1_vect
External Interrupt Request 2              INT2_vect
Timer/Counter 2 Compare Match      TIMER2_COMP_vect
Timer/Counter 2 Overflow      TIMER2_OVF_vect
Timer/Counter 1 Capture Match      TIMER1_CAPT_vect
Timer/Counter 1 Compare Match A      TIMER1_COMPA_vect
Timer/Counter 1 Compare Match B      TIMER1_COMPB_vect
Timer/Counter 1 Overflow      TIMER1_OVF_vect
Timer/Counter 0 Compare Match      TIMER0_COMP_vect
Timer/Counter 0 Overflow      TIMER0_OVF_vect
SPI Transfer Complete             SPI_STC_vect
USART, Receive Complete      USART0_RX_vect
USART, Data Register Empty      USART0_UDRE_vect
USART, Transfer Complete      USART0_TX_vect
ADC Conversion Complete                ADC_vect
EEPROM ready              EE_RDY_vect
Analog Comparator      ANALOG_COMP_vect
Two-Wire Serial Interface ( )                TWI_vect
Store Program Memory Ready          SPM_RDY_vect

 

Example to define ISR- timer0 overflow interrupt.

ISR(TIMERO_OVF_VECT)

{

// our program

}

PROGRAMMING TIMERS INTERRUPTS-

In previous section, we discussed programming of timer0, 1 and 2 using polling method. In this section, we program timers using interrupt method.

Before moving further let revise meaning of following events-

  1. COMPARE MATCH- when value of OCRx and TCNtx registers become equal.
  2. OVERFLOW- when value if TIMER/COUNTER register reaches to its maximum value and becomes zero is called overflow condition.
  3. CAPTURE MATCH- when an external event is capture or occurred and this event is sensed by timer then, it is called capture match.

In case of interrupts, if any of these event occurs CPU stops its current program execution and jumps to give service to interrupt service routine.

 

Rollover Timer Flag and Interrupt:

We know that in timer0 when TOV0 flag is set then, timer rollover (overflow occurs). We have to wait till TOV0 flag to be set, then clears TOV0 flag. But in case of interrupts we don’t have to continuously check the status of TOV0 flag. We just have to enable TIMER0 overflow interrupt and when TOV0 flag is set then, program move to ISR. In this ISR, we write code to load the value into timer/counter register (TCNT0). The name of ISR for timer0 overflow is- TIMER0_OVF_vect.

ISR(TIMER0_OVF_vect)

{

TCNT0=35;//load the value into TCNTO when overflow occurs

}

But before defining ISR we have to enable interrupts so that microcontroller can respond it. To enable different interrupts of timers we have TIMSK register as follows-

TIMSK (TIMER INTERRUPT MASK) REGISTER-

  1. TOIE0- Timer0 overflow interrupt enable.

0=Disables Timer0 overflow interrupt

1=Enables Timer0 overflow interrupt

  1. OCIE0- Timer0 output compare match interrupt enable.

0=Disables Timer0 compare match interrupt

   1=enables Timer0 compare match interrupt

  1. TOIE1- Timer1 overflow interrupt enable.

0=Disables Timer1 overflow interrupt

1=Enables Timer1 overflow interrupt

  1. OCIE1B- Timer1 output compare B match interrupt enable.

0=Disables Timer1 compare B match interrupt

   1=enables Timer1 compare B match interrupt

  1. OCIE1A- Timer1 output compare A match interrupt enable.

0=Disables Timer1 compare A match interrupt

   1=enables Timer1 compare A match interrupt

  1. TICIE1- Timer1 input capture interrupt enable.

0=Disables Timer1 input match interrupt

1=enables Timer1 input match interrupt

  1. TOIE2- Timer2 overflow interrupt enable.

0=Disables Timer2 overflow interrupt

1=Enables Timer2 overflow interrupt

  1. OCIE2- Timer2 output compare match interrupt enable.

0=Disables Timer2 compare match interrupt

   1=enables Timer2 compare match interrupt

 

TIMER OVERFLOW PROGRAMMING-

In this section, we write program to generate square wave using timer 0, 1 and 2. We are generating square wave using interrupt method.

EXAMPLE– Suppose we have XTAL=8MHz and we want to generate square wave on PIN2 of PORTC using timer0. Write a program using interrupt method and load value in TCNT0 register 220.

ANSWER– We have to follow the following steps to complete the given task-

  1. Make PIN2 of PORTC as output pin.
  2. Load given value in TCNT0 register.
  3. Choose the mode and pre-scalar by setting the value of TCCR0 register.
  4. Enable timer0 overflow interrupt.
  5. Enable global interrupt.
  6. Define ISR with “TIMER0_OVF_vect” as vector name
  7. Inside this ISR function toggle PIN2 of PORTC.

PROGRAM CODE-

Now we will done previous example using TIMER1 and TIMER2. But now there is no need to explain program code.

USING TIMER1-

PROGRAM CODE-

USING TIMER2-

PROGRAM CODE-

TIMER COMPARE MATCH PROGRAMMING-

When we are using CTC mode in timers then, we have to load some value in OCRx register. And when value of TCNTx and OCRx register become equal (compare match occurs), OCIFx flag will be set. So, in polling method we have to check status of OCIFx flag whether it is set or not. But in case of interrupt method we don’t need to check status of OCIFx flag. When OCRx and TCNTx register becomes equal an interrupt named “TIMERx_COMP_vect” will be generated. We have to define ISR and inside this ISR we load the value inside OCRx register. We will now program timers in CTC using interrupt method.

 

EXAMPLE- Suppose we have XTAL=8MHz and we are using TIMER0 in CTC mode. We want to load value 45 inside OCR0 register and when compare match occurs between TCNT0 and OCR0 register then, PINB2 will be toggled. Use interrupt method and define appropriate interrupt service routine.

 

ANSWER-  We have to follow the following steps to complete the given task-

  1. Make PIN2 of PORTB as output pin.
  2. Load given value in OCR0 register.
  3. Choose the mode and pre-scalar by setting the value of TCCR0 register.
  4. Enable timer0 overflow interrupt.
  5. Enable global interrupt.
  6. Define ISR with “TIMER0_OVF_vect” as vector name
  7. Inside this ISR function toggle PIN2 of PORTB.

  

PROGRAM CODE-

Now we will done previous example using TIMER1 and TIMER2. But now there is no need to explain program code.

USING TIMER1-

PROGRAM CODE-

USING TIMER2-

PROGRAM CODE-

PROGRAMMING EXTERNAL HARDWARE INTERRUPT-

In this section, we learn what is external hardware interrupts? and then, learn how to program them using some examples. Suppose we have connected an switch to PINB2 which is at logic ‘1’ when switch is not pressed. When we press switch then, logic ‘0’ is given at PINB2. Now we have connected four LEDs to PORTC which are in ON state. Our task is – when switch is pressed then LEDs blink, but when switch is not pressed LEDs keeps on lightning.  In this case, switch is an external hardware interrupt. When this switch is pressed then, program moved to ISR which we have defined to blink four LEDs connected to PORTC.

The number of external hardware interrupts varies in different AVRs. In atmega  16/32 has three external hardware interrupts: pins PD2, PD3 and PB2, designed as INT0, INT1 and INT2 respectively. Upon activation of these pins, AVR is interrupted in whatever it is doing and jumps to the vector table to perform INTERRUPT SERVICE ROUTINE.

EXTERNAL INTERRUPT INT0, INT1 AND INT2-

Before using any interrupts we have to enable that interrupt by setting bit INTx in GICR register.

REGISTERS USED AND THEIR DESCRIPTION-

GICR REGISTER (General Interrupt Control Register)-

MCUCR (MCU Control Register) and MCUCSR (MCU Control and Status Register)-

In previous example, we connected switch at PINB2 and when switch is pressed logic ‘0’ is given at PINB2 and interrupt is activated. So when PINB2 is given logic ‘0’ then, only interrupt is activated. In the same way we can define on which state on interrupt pin interrupt is activated. Suppose we want to define when falling edge is given at PINB2 then, interrupt is activated so we can define this condition using MCUCR register. We have an interrupt INT2, it has only two conditions in which this interrupt is activated i.e. falling and rising edge. So now we are defining these register which define the state of interrupt in which it is activated.

MCUCR REGISTER-

ISC01 AND ISC00 (Interrupt Sense Control Bits)- These bits define the level or edge on the external INT0 pin that activates the interrupt,

ISC11 AND ISC10 (Interrupt Sense Control Bits)- These bits define the level or edge that activates the INT1 pin.

EDGE-TRIGGERRED vs LEVEL-TRIGGERRED INTERRUPTS-

There are two types of activation for external hardware interrupts: level and edge triggered. INT2 is only edge triggered interrupt while INT0 and INT1 are both level and edge triggered.

MCUCR REGISTER-

When external interrupt is in an edge-triggered mode upon, triggering an interrupt request, the related INTFx flag becomes set. If the interrupt is active, the AVR jump to corresponding interrupt vector location and the INTFx flag will be cleared automatically, otherwise, flag remains set.

Now we will see some examples to understand the concept of external hardware interrupts.

EXAMPLE- Assume INT0 pin is connected to a switch which is normally high. Write a program that blink four LEDs connected to PORTC, whenever INT0 goes low. When interrupt is not activated then, LEDs is ON. Use the external interrupt in level-triggering mode.

 ANSWER- We have to follow the following steps to completed given task-

  1. Make PORTC as output as LED is connected to it.
  2. Then, pull up high PIN2 of PORTD i.e. INT0 which remain high normally.
  3. Inside While(1) loop switch ON LEDs by logic ‘1’ writing to its PORTC register.
  4. Enable INT0 interrupt in GICR register.
  5. Define ISR named “INT0_vect” to toggle PIN3 of PORTC.
  6. Inside this ISR blink LEDs connected to PORTC by using “_delay_ms()’ function

PROGRAM CODE-

CIRCUIT DIAGRAM-