Posts Tagged ‘AVR’

AVR

februari 18, 2010

Jag har startat upp ett par elektronikprojekt jag haft i startgroparna ett tag nu. Jag kommer basera dessa projekt kring Atmels AVR-mikrokontrollers* och det första steget har varit att sätta upp och testa utvecklingsmiljön, verktygskedjan samt att programmering av kretsarna fungerar. Verktygskedjan är jag rätt bekant med sedan tidigare experiment. (Jag dokumenterade till och med installationsproceduren på elektronikforumets wiki ifall någon är intresserad)

Testuppkoppling för "hello LED"

Testuppkoppling för "hello LED"

Mitt första testprojekt var det klassiska Hello LED** (motsvarigheten till Hello World för mikrokontrollers) som enligt konvention blinkar med en lysdiod. Mitt program har gått igenom följande steg:

  1. Enkel blinkfunktion med fördröjningsloopar
  2. Avbrottsbaserade fördröjningar mha Watchdog-timern***
  3. Punkt två + Power down-mode för att göra det hela strömsnålt

Det första problemet var att koppla in min programmerare och få över programmet till kretsen. Efter att ha dubbelkollat alla kopplingar och hittat/rättat till ett par dumheter fungerar det fortfarande inte att programmera chipet. Lyckligtvis kom Google till undsättning, i ett forum någonstans fiskas viktig information fram:

Saknas matningsspänning kan programmering misslyckas lite beroende på utrustning och lite beroende på månens gravitationsinverkan eller andra slumpmässiga effekter.

Lite ström och det går som en dans! Punkt 1 (ovan) påbörjades raskt och efter lite problem med att dioden blinkade 1000 ggr/s (4 * 10^6/1000 är inte ungefär 0.1… ibland undrar man…)

Efter detta begav jag mig genast vidare mot nya djärva mål, dvs punkt 2 och 3. När jag funderat, läst, tänkt, skrivit, skrivit om, funderat, skjutit upp, och sedan läst och skrivit mig ner till punkt tre hade jag följande kod:


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>

uint8_t toggle = 0;
uint8_t cnt = 0;

ISR(WDT_vect)
{
  if(cnt > 90)
  {
    if(toggle)
    {
      PORTB &= 0xfe;  //LED On

      toggle = 0;
      cnt = 83;
    }
    else
    {
      PORTB |= 0x01;  //LED Off

      toggle = 1;
      cnt = 40;
    }
  }
  else
    cnt++;
}

int main(void)
{
  //Interrupts
  WDTCR = 0x40; //Watch Dog Interrupt 2k Cycles

  //IO
  DDRB  = 0x01; //PB0 => Output

  PORTB = 0x01;
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  //MCUCR SM0-1 => 10 (power down)

  //Enable global interrupts
  sei();        

  while(1)
  {
    sleep_mode(); //MCUCR SE => 1 and asm sleep-command
  }

  return 0;
}

syntax highlighted by Code2HTML, v. 0.9.1

Denna övning lämnade mig en aning imponerad över de bibliotek som finns tillgängliga tillsammans med avr-gcc, de verkar göra kod ganska lätt att porta mellan olika AVRer. Jag känner mig också optimistisk inför mina framtida projekt, det jag gjort hitintills är en bra grund för minst ett av mina planerade projekt.

* Mikrokontroller är inget riktigt ord utan en försvenskning av det engelska ordet microcontroller. På svenska heter det egentligen Mikrodator men det låter inte lika bra.

** LED är en förkortning av Light Emitting Diod och kallas ofta för Lysdiod på svenska

*** Watchdog-timern är i sin originalform en räknare som startar om mikrokontrollern när den räknat upp till sitt max-värde. Detta brukar användas för att starta om en hängd processor, medan koden gör det den ska nollställer man Watchdog-timern regelbundet och när något går fel så denna nollställning inte utförs startar mikrokontrollern om. I den mikrokontroller jag använder kan den istället för att starta om generera ett periodiskt avbrott.