AVR/Examples/Interrupts

From OmegaV-wiki
Jump to: navigation, search

>= Interrupt Examples =

Theory

There are quite a few things you can do without interrupts, however most things doable on a microcontroller, such as the AVR, is best done with interrupts. Interrupts also often leads to shorter code, than without. So, lets take a quick overview at these things before we dive into some examples. To understand the concept of interrupts, lets take an example from the real world: If a person is walking down a street, concentrating on nothing other than walking suddenly gets a ball in his head, he will stop, wonder where the ball came from and then continue with the walking. In other words, the person was 'interrupted' in his walking procedure. It's the same thing with microcontrollers(and many other kinds of CPUs as well). If we have a main-procedure, could be one of the above, running it's eternal main-loop and somebody suddenly pulls one of its pins high, then it will also be interrupted if we have initialized it to be that way. Simple, huh? So what kind of interrupts are there on the AVR?

  • Timer-interrupts: There are timers/counters running in parallel with the cpu which can generate various interrupts.
    • Overflow-interrupt: The timer overflows and thereby generating an interrupt
    • Compare match-interrupt: If the timer reaches a given value, it will generate an interrupt
  • AD-interrupts: If an analog to digital conversion is done, that could generate an interrupt
  • Various communication-interrupts
    • UART-interrupt: If we have received a new char at the UART, or is done sending one
    • SPI-interrupt: Same thing as the UART, basically
    • And many more...
  • External-interrupts: Interrupts triggered by external sources, for example if you suddenly changes the voltage applied at a pin from Vss to Vcc

Enough of the theory lets get to the code!


Timer-overflow Example

This will toggle PORTB on and off in an interval given by <math>\frac{1}{\frac{\frac{1}{8} \cdot CPU_{Clock}}{256}}</math>. This is becuase the timer0 in most modern AVRs, like the Mega48/88/168 for example, only is an 8-bit timer. In other words, it cannot count any further than 255 and will therefore overflow at 256. <source lang=c n> //Include the standard input-output header

  1. include <avr/io.h>

//And include the interrupt-header. This has to be included in order to get the interrupt-routines to compile successfully

  1. include <avr/interrupt.h>

//Declaring a variable volatile forces the avr to load the variable from the memory each time it's used volatile uint8_t currentValue = 0x00;

//Our normal main-function int main(void){

   //Set PORTB as output
   DDRB = 0xff;
   
   //Setup timer0, and enable its overflow-interrupt
   //First we set the speed of the timer which in this case is set to be (1/8) * CPU-Clock 
   TCCR0B = (1<<CS10);
   //Then we enable the timer0 overflow-interrupt
   TIMSK0 = (1<<TOIE0);
   //Enable interrupts globally. If this isn't called, not a single interrupt will go off
   sei();
   //Go into our eternal main-loop
   for(;;){
       //Do nothing, let the interrupt handle it all
   }
   //We will never get here
   return 0;

}

//This is the code the avr will execute when the interrupt happens ISR(TIMER0_OVERFLOW){ //TIMER0_OVERFLOW means just that; do this when timer0 overflows

   currentValue = 0xff - currentValue; //Invert currentValue (255=0xff=0b11111111, the largest possible value for an uint8_t)
   PORTB = currentValue;

} //End the interrupt, go back to the main-loop and continue where it left

</source>

--Oybo 06:06, 31 October 2007 (CET)


Ekstern asynkron krystall Atmega168

Med 32768Hz klokkekrystall koblet på PB6-7 funker denne koden:

<source lang=c n>

  1. include <avr/io.h>
  2. define F_CPU 8000000UL
  3. include <avr/interrupt.h>
  4. include <util/delay.h>

int main () {

//Sett at timer2 skal kobles fra intern klokke ASSR = (1<<AS2); //Nullstill timer counter register 2A TCCR2A = 0; //Sett prescaler Clock Select til å dele på 128 TCCR2B = (1<<CS22) | (0<<CS21) | (1<<CS20); //Vent på at nødvendige registre er oppdatert while (ASSR & ((1<<TCN2UB) | (1<<TCR2AUB) | (1<<TCR2BUB))); //Sett timer interrupt mask til overflow enable TIMSK2 = (1<<TOIE2);

DDRC = 0xFF; PORTC |= 0x09;

sei();

while(1);

}

ISR(TIMER2_OVF_vect) { PORTC++; } </source>

Personal tools