AVR/Examples/Interrupts

From OmgaV 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 \frac{1}{\frac{\frac{1}{8} \cdot CPU_{Clock}}{256}}. 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.

  1. //Include the standard input-output header
  2. #include <avr/io.h>
  3. //And include the interrupt-header. This has to be included in order to get the interrupt-routines to compile successfully
  4. #include <avr/interrupt.h>
  5.  
  6. //Declaring a variable volatile forces the avr to load the variable from the memory each time it's used
  7. volatile uint8_t currentValue = 0x00;
  8.  
  9. //Our normal main-function
  10. int main(void){
  11.  
  12. //Set PORTB as output
  13. DDRB = 0xff;
  14.  
  15. //Setup timer0, and enable its overflow-interrupt
  16. //First we set the speed of the timer which in this case is set to be (1/8) * CPU-Clock
  17. TCCR0B = (1<<CS10);
  18. //Then we enable the timer0 overflow-interrupt
  19. TIMSK0 = (1<<TOIE0);
  20.  
  21. //Enable interrupts globally. If this isn't called, not a single interrupt will go off
  22. sei();
  23.  
  24. //Go into our eternal main-loop
  25. for(;;){
  26. //Do nothing, let the interrupt handle it all
  27. }
  28. //We will never get here
  29. return 0;
  30. }
  31.  
  32. //This is the code the avr will execute when the interrupt happens
  33. ISR(TIMER0_OVERFLOW){ //TIMER0_OVERFLOW means just that; do this when timer0 overflows
  34. currentValue = 0xff - currentValue; //Invert currentValue (255=0xff=0b11111111, the largest possible value for an uint8_t)
  35. PORTB = currentValue;
  36. }
  37. //End the interrupt, go back to the main-loop and continue where it left

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


Ekstern asynkron krystall Atmega168

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

  1. #include <avr/io.h>
  2. #define F_CPU 8000000UL
  3. #include <avr/interrupt.h>
  4. #include <util/delay.h>
  5.  
  6. int main () {
  7.  
  8. //Sett at timer2 skal kobles fra intern klokke
  9. ASSR = (1<<AS2);
  10. //Nullstill timer counter register 2A
  11. TCCR2A = 0;
  12. //Sett prescaler Clock Select til å dele på 128
  13. TCCR2B = (1<<CS22) | (0<<CS21) | (1<<CS20);
  14. //Vent på at nødvendige registre er oppdatert
  15. while (ASSR & ((1<<TCN2UB) | (1<<TCR2AUB) | (1<<TCR2BUB)));
  16. //Sett timer interrupt mask til overflow enable
  17. TIMSK2 = (1<<TOIE2);
  18.  
  19. DDRC = 0xFF;
  20. PORTC |= 0x09;
  21.  
  22. sei();
  23.  
  24. while(1);
  25.  
  26. }
  27.  
  28. ISR(TIMER2_OVF_vect)
  29. {
  30. PORTC++;
  31. }
Personal tools