Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

24
voti

Iniziare con AVR ATmega

Indice

Introduzione

Quando si vuole iniziare a lavorare con un microcontrollore la parte più difficile è l' inizio. In questo breve (e anche banale) articolo descriverò il modo in cui mi sono avvicinato agli ATmega della Atmel. Per iniziare a lavorare con un micro ci sono diversi approcci, io ho utilizzato quello che, secondo la mia esperienza, mi sembra il più semplice, lineare e che presente il minor numero di problemi.
Parlando di ATmega non può non venire in mente Arduino. Soluzione sicuramente interessante ma, a mio modesto avviso, non "pura". Ho intrapreso la sperimentazione su ATmega in modo tradizionale almeno secondo i miei canoni.
Per motivi di lavoro ho avuto la necessità di utilizzare questa famiglia di micro, ho quindi ordinato l' emulatore JTAG ed un paio di evaluation kit specifici per la mia applicazione. Devono ancora arrivarmi dagli USA e, per non stare con le mani in mano ed incominciare a destreggiarmi con il sistema di sviluppo ed i micro, ho colto l' occasione di infilare dentro un ordine di materiali un paio di oggetti che mi hanno permesso di iniziare la sperimentazione in tempi brevissimi.

Scelta del microcontrollore

Per sperimentare su un micro che non conosco ho consultato il sito della Atmel per rendermi conto di quello che sono le varie famiglie. Una famiglia interessantissima è l' AVR 32 (che sarà molto probabilmente il micro che utilizzerò per il mio lavoro) ma, visto che i kit di valutazione/sviluppo su cui sperimenterò inizialmente la mia applicazione utilizzano gli Atmega, ho voluto iniziare con questa famiglia.
Il criterio che ho utilizzato è semplice: trovare un micro in un contenitore DIL (possibilmente a 40 pin) con sufficiente memoria per provare applicazioni di un certo spessore. Ho quindi individuato il micro che poteva fare più o meno al caso mio: ATmega324P. Questo micro ha una memoria FLASH da 32K, 2K di RAM che sono abbastanza per farci qualche bella cosina, un bel po' di I/O, convertitore A/D, EEPROM, UART, SPI ... insomma la versione Atmel di un PIC18F4625 o giù di lì, per intenderci. Costa poco più di un pacchetto di sigarette quindi si può comprare senza timore di diventare poveri per questo.
Il micro deve poi essere programmato. E' vero che ci sono bootloader ed artifizi vari che permettono di farlo senza comprare nulla ma un programmatore dedicato, magari della Atmel e che costi poco sarebbe sicuramente la soluzione migliore. Questo programmatore c'è ed è il AVRISP MKII. Costa 29€ e, se penso che Arduino ne costa 25 direi che vale la pena comprarlo anche perché mi permette di programmare sul serio i micro della Atmel e non devo essere legato ad un hardware specifico. Quindi ho inserito nell' ordine il micro ed il programmatore.

Il sistema di sviluppo

Per sviluppare sugli AVR l' Atmel offre AVR studio 5, un bellissimo sistema che comprende anche il compilatore C gcc. Per attrezzarmi ho seguito le istruzioni della Atmel scaricando ed installando il software. Per scaricare il software è necessaria una registrazione. Niente di che, ho messo i miei dati ed ho avuto via libera al download. La cosa bella di questo sistema di sviluppo (che ho appena iniziato ad utilizzare e che quindi conosco solo in minima parte) è la possibilità di creare nuovi progetti partendo da un progetto dimostrativo già esistente. Questo da la possibilità di avere già una base software funzionante su cui apportarci modifiche che, agli inizi, non è cosa da poco. Fa risparmiare tempo e permette di capire molto sul modo in cui i programmi devono essere scritti e su come utilizzare le periferiche. Basta impostare la sigla del micro che si vuole utilizzare e il sistema presenta tutti gli esempi che si possono utilizzare con il micro scelto. Direi che è una cosa grande!

La scheda per la sperimentazione

Che volete farci? Sono all' antica, amo il saldatore, le millefori ed i cablaggi filati. Ho montato un semplice circuito basandomi sulle informazioni del datasheet e del manuale utente del programmatore.

C'è poco da dire sul circuito ... non ha niente! Ho collegato il connettore dell' ISP ai piedini del micro, un quarzo montato su zoccolo per poterlo eventualmente cambiare, massa e alimentazione. E poi ci ho messo il mio buon caro LED rosso sull' alimentazione per sapere quando il circuito è sotto tensione.

ATmega324P_fronte.png

ATmega324P_fronte.png

Con poche e semplici filature ho collegato il tutto

ATmega324P_retro.png

ATmega324P_retro.png

Fuoco alle polveri!

Ed ora il primo programma. Come primo programma sono solito scrivere un ciclo infinito che incrementa una variabile byte che poi metto in una porta di uscita. In questo modo posso vedere qualcosa muoversi questo perché il semplice LED acceso non garantisce che il micro stia effettivamente girando, ma un dato "sparato" su una porta di uscita che continua ad incrementarsi si. Se tutto funziona con l' oscilloscopio devo vedere un' onda quadra sui pin della porta. Non solo, ma si può valutare la velocità del micro, verificare i cambiamenti dovuti al clock e la bontà del compilatore C. Nella sezione del datasheet che descrive le porte c'è un esempio in C che usa la porta B, in pratica si tratta di caricare nel Data Direction Register della porta il valore FF esadecimale per impostare tutti i pin della porta come uscite. Una sola istruzione di assegnazione. Dopo avere installato AVR Studio 5 ho collegato il programmatore all' USB sperando che il driver fosse già presente. Se il sistema di sviluppo è fatto bene il driver deve già esserci. Il driver c'era ed il programmatore si è installato correttamente, mi è bastato dire al PC di caricarsi il driver automaticamente e lui lo ha fatto.
Ho quindi fatto partire AVR Studio, ho scelto di creare un nuovo progetto selozionando la prima voce in alto a sinistra della pagina iniziale "New Project"

AVRStudio01.jpg

AVRStudio01.jpg

Nella pagina "New Project" ho selezionato "Empty Executable Project" ed ho messo il nome "Prova324P" nella casella "name", ho spuntato la box "Create directory for solution" ed ho premuto "OK"

AVRStudio02.jpg

AVRStudio02.jpg

Poi mi è comparsa la finestra per la selezione del dispositivo, ho selezionato ATmega324P e, cosa molto bella e comoda, nella parte destra mi sono comparsi tutto quello che mi serve del micro e cioe' il link al datasheet ed i tools che supportano tale micro (ho notato con piacere che c'è il link al mio programmatore).

AVRStudio03.jpg

AVRStudio03.jpg

Dopo qualche secondo e' comparsa la scheda con l' editor per il main.

AVRStudio04.jpg

AVRStudio04.jpg

Siccome a me piacciono le tabulazione con 2 spazi mi sono andato a cercare le opzioni dell' editor ed ho messo le cose a posto. Dopo ho aggiunto 3 righe di programma ottenendo questo main:

/*
 * prova.c
 *
 * Created: 19/05/11 22:26:53
 *  Author: TardoFreak
 */ 

#include <avr/io.h>

int main(void)
{
  unsigned char i;
  
  DDRB = 0xff;
  while(1)
  {
    //TODO:: Please write your application code 
    PORTB = i;
    i++;
  }
}

Ho costruito il progetto con il comando dal menù Build->Build solution, l' ha compilato senza errori. Poi ho chiamato la voce del menù Tools -> AVR Programming, nella finestra ho impostato come Tool AVRISP mkII, come device ATmega324 e come Interface ISP. A quel punto nella sezione memories ho caricato il file .hex e programmato il micro. Non me l' ha programmato subito perché il programmatore doveva essere aggiornato. Ho seguito le istruzioni, aggiornato il programmatore e quindi, dopo avere richiamato il tool di programmazione, programmato correttamente il micro.
Fatto!
Poi ho esplorato un po' i fuses, selezionato l' oscillatore esterno e tante altre cosette giusto per prendere un po' dimestichezza chiaramente tenendo sempre a portata di mano il datasheet. Ho anche provato a vedere gli effetti delle ottimizzazioni previste dal compilatore: molto valide. Dopo ho deciso di condividere con Voi questa piccola esperienza.

Addendum: Le interrupt

Se c'e una cosa che amo sono i timer seri, intendo quelli che hanno la possibilità di lavorare con un comparatore che, quando il conteggio raggiunge il valore del comparatore, resetti il timer e generi un interrupt. E' il sistema migliore per ottenere temporizzazioni precise. Non amo particolarmente i timers che generano l' interrupt quando vanno in overflow perché impongono un lavoro di compensazione del tempo di ricarica del valore che, se è semplice da fare quando si lavora in assembly, non lo è quando si lavora in C (bisogna andarsi a vedere il lavoro fatto dietro le quinte dal compilatore).
E' mia abitudine, quando ho a che fare con ritardi umanamente apprezzabili, di scrivere un' interrupt ciclica per la gestione di uno o più timers software e magari gestire anche il multiplexing di display se serve. E' un sistema semplice e, a mio avviso, molto pratico da utilizzare. L' idea è di avere dei timers che si decrementano fino ad arrivare a zero e dallo zero non si decrementino più. Quindi, per provare le interrupt con questo micro, ho pensato di scrivere questa semplice interrupt ciclica chiamata ogni 10ms. Ho poi collegato un LED con un resistenza al pin 1 del micro (PB0) con l' intenzione di vederlo lampeggiare con un periodo di 1s.
Il fatto è che ogni compilatore ha un modo suo (a volte bizzarro) per scrivere la routine di gestione dell' interrupt. Ad esempio con il C18 della Microchip biogna fare qualche salto mortale, in scrivere un' istruzione di salto in assembly e via dicendo, il C30 (PIC24/33) utilizza un modo diverso ed infine il C3 (che è un compilatore gcc) ne usa un altro ancora. Sappiamo bene che le interrupt ed il modo per scrivere le relative routines di servizio sono strettamente legate all' architettura della macchina. L' ATmega324P ha una lista di vettori di interrupt e non c'è la possibilità di impostarne la priorità o meglio la priorità è fissa nel senso che il vettore 1 è il RESET ed ha la massima priorità e, man mano che il numero del vettore aumenta diminuisce la priorità. Avremo così la INT0 che ha priorità massima mentre la USART1_TX quella minima . Questa caratteristica se da una parte limita le possibilità, dall' altra rende il lavoro più semplice e, quando si è agli inizi, non può che essere un bene. Per complicarsi la vita non serve impegno, è già complicata di suo e ritrovarsi dentro casini monumentali è un attimo.
GCC (non la Atmel, mi hanno fatto notare in un autorevole commento) ci ha anche messo del suo per rendere la vita più semplice scrivendo una macro che rende la dichiarazione della routine di servizio semplicissima. Basta infatti scrivere ISR(INT1_vect) per dichiarare, ad esempio, la routine di servizio dell' INT1. Io avevo bisogno dell' interrupt sul comparatore A del timer 1 e quindi ho scritto ISR(TIMER1_COMPA_vect). All' interno della routine di servizio non c'è bisogno di "riarmare" o ri-abilitare niente. Si scrive la ruotine e ... finito il chiasso.
Questo è il listato del programmino che fa lampeggiare il LED alla frequenza di 1Hz. ed utilizza un timer software.

/*
 * prova324p.c
 *
 * Created: 20/05/11 15:09:24
 *  Author: TardoFreak
 */ 

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

// Timer software.
// Nota: vanno dichiarate come "volatile" per fare in modo che il 
// valore sia sempre e comunque letto evitando che l' ottimizzazione 
// non lo faccia.
volatile unsigned short SoftTimer1;

// Routine di servizio chiamata quando il contenuto del comparatore A 
// corrisponde al valore del timer. Quando raggiunge tale valore il 
// timer viene resettato e viene invocata questa routine.
ISR(TIMER1_COMPA_vect)
{
  if(SoftTimer1) SoftTimer1--;
}

//--------------------------------------------------------------------------
int main(void)
{
	
  // Inizializza timer 1 per timeout 10ms
  // Questa istruzione assicura che l' I/O clock per il timer1 sia abilitato
  PRR0 &= ~(1<<PRTIM1);

  // Carica il registro di comparazione per ottenere 10ms
  OCR1A = 3125;
	
  // Enable output compare A match 
  TIMSK1 = (1<<OCIE1A)|(0<<TOIE1);
	
  // Avvia il timer1, prescaler 1/64 modo operativo Clear Top Count
  TCCR1B = (0<<WGM13)|(1<<WGM12)|(0<<CS12)|(1<<CS11)|(1<<CS10);
	
  // Predispone la porta B come uscita
  DDRB = 0xff;
	
  // Abilita le interrupt
  sei();
	
  while(1)
  {
    if(!SoftTimer1)
    {
      PORTB ^= 0x01;    // Commuta l' uscita PB0
      SoftTimer1 = 50;  // Carica il timer software per intervallo 500ms.
    }		
  }
}

Per sapere velocemente come fare per scrivere ed utilizzare il timer ho aperto un progetto di esempio (che si richiama direttamente dall' IDE) ed in poco tempo ho implementato la cosa.

Conclusioni

Questo articoletto è stato scritto velocemente come velocemente sono riuscito a fare la prima prova con l' ATmega. Devo dire che la Atmel ha veramente fatto le cose per bene ed è necessario dirlo a chiare lettere. Oggi pomeriggio mi è arrivato il materiale, dopo mezz' ora avevo il circuito montato, dopo un' altra ora il micro programmato e funzionante. Ci tenevo a pubblicare questa mia semplice e banale esperienza proprio perché Atmel si è meritata i miei complimenti. Niente da dire, i mcro sono molto belli, il sistema di sviluppo è ottimo, da quello che ho potuto leggere nei giorni precedenti le librerie dovrebbero essere ricche ma sono ancora cose che devo scoprire. Quello che mi ha impressionato è la semplicità d' uso e la velocità con cui sono riuscito a fare la prima prova. E questo per me è importante. Se devo essere sincero l' idea di avvicinarmi ad una nuova famiglia di micro mi mette l' ansia (per non dire che mi fa venire l' orticaria). Solo l' idea di dovermi leggere manuali da 400 pagine, linker, direttive specifiche della macchina e del compilatore, settaggi ed opzioni a destra e a manca per fare un programmino del pettine che modula un uscita del micro mi distrugge. Sarà forse perché non ho più vent' anni ma la cosa mi pesa un po'. Con Atmel ho trovato qualcosa che mi ha evitato tutti questi mal di pancia.
Mi dispiace solo di non poter dire altrettanto della Microchip. Il suo sistema è buono però dovrebbe prendere esempio dalla Atmel di come si realizza un sistema di sviluppo semplice e potente. I PIC si meriterebbero un qualcosa del genere poiché sono dei micro veramente belli e poco costosi ... ma tant' è.

18

Commenti e note

Inserisci un commento

di ,

Ricordo di aver letto da qualche parte, che l'architettura degli AVR fu progettata per essere ottimizzata con il linguaggio C, cioè qualcosa che sui PIC è arrivata solo con i 18F (correggetemi se dico sciocchezze). Vi segnalo questa AN di Atmel per produrre con avr-gcc codice ottimizzato: http://www.atmel.com/Images/doc8453.pdf

Rispondi

di ,

AVR for ever....con buona pace dei PICisti ;-)

Rispondi

di ,

Ciao! Ottimo spunto per iniziare! ;) Se serve, ho trovato altri tutorial a riguardo: http://hekilledmywire.wordpress.com/ Ma altri non ne trovo. C'è per caso qualche esperto che sa linkare qualche altro tutorial di programmazione AVR?

Rispondi

di ,

Salve!!cercando in rete mi sono imbattuta su questo post di un anno fa e mi ha colpito tantissimo...ho però un dubbio e mi scuserete se è davvero un dubbio da incompetenti:)..il circuito che viene mostrato come scheda di sperimentazione mi sostituisce il programmatore?!!?e poi altro dubbio...questa scheda va connessa direttamente al pc poi??ma come???ho visto che si utilizza la porta usb..ma non riesco a capire!:) chiedo scusa per le domande terra-terra..

Rispondi

di ,

Grazie, ottimo articolo! E' da un po' che uso Arduino per fare qualche semplice progetto, ma ora penso comincerò a mettermi qualche ATmega su breadboard e a programmarlo con il mio Arduino usato come ISP.

Rispondi

di ,

ottimo articolo... :-)

Rispondi

di ,

Innanzitutto complimenti, bel articolo. Anch'io è da un po' che sono passato ad Atmel e mi trovo bene, anche se è un po' più scarna come documentazione rispetto a Microchip, ma comunque finora sono riuscito sempre a sviluppare quello che volevo.

Rispondi

di ,

Ho dovuto chiedere assistenza tecnica ad Atmel. Sono stati tempestivi rispondendo nel giro di un' ora, e mi hanno risolto il problema.

Rispondi

di ,

Bravo Tardo Freak, come sempre chiaro, preciso ed esaustivo. Complimenti.

Rispondi

di ,

Non sono preparato in materia (microcontrollori),ma ritengo che l'impegno che ha richiesto questa realizzazione ha dato dei bei frutti, Complimenti TradoFreak..:-)

Rispondi

di ,

Io programmo gli AVR da molti anni quindi ben venga una semplice e chiara guida in Italiano. Quello che molto spesso indichi come lavoro dell'Atmel è in realtà una caratteristica del compilatore GCC. Le macro per l'interrupt sono della libreria AVR-libc, il compilatore riconosce e genera il codice per l'interrupt traverso l'uso di opportuni attributi. Consiglio di utilizzare la macro "_BV(name)" al posto di "(1<

Rispondi

di ,

L' AVR è sicuramente un prodotto interessante. L'ho valutato tempo fa per una applicazione. Poi però per via della potenza di calcolo ho optato per un STM32 dopo aver valutato attentamente anche il PIC32. Anche a livello di canali di comunicazione ho trovato l'STM32 eccellente. Il costo del sistema di sviluppo è come al solito un problema da non sottovalutare, soprattutto se si devono produrre pochi pezzi. In un progetto industriale invece è un costo mediamente trascurabile rispetto a quello relativo allo sviluppo software. L'AVR è molto user-friendly ed il sistema di sviluppo piu' che decoroso. Non ho provato ad installare FreeRTOS su un AVR32 ma sarei curioso di provare questa soluzione. Avere un sistema operativo realtime su un microcontrollore con discreta velocità di elaborazione fa sempre comodo. Complimenti per l'introduzione all'argomento.

Rispondi

di ,

Ciò che fai è sempre interessante ed è sempre presentato con il brio e la freschezza di un ventenne, ma con la maturità e la consapevolezza di un quarantenne ;-)

Rispondi

di ,

Visto che la cosa interessa ho pensato di aggiungere paragrafi man mano che sperimento. Oggi ho sperimentato il timer a 16 bit con il comparatore. Direi che varrebbe la pena inserirlo nell' articolo. Forse potrebbe essere utile a qualcuno.

Rispondi

di ,

Benvenuto nel mondo AVR... per il poco che faccio sto' usando sempre loro...

Rispondi

di ,

Argomento sempre molto interessante.Un saluto,Orlando

Rispondi

di ,

Secondo me i PIC vanno utilizzati perchè sono ottimi micro, costano poco e si trovano ovunque. Il supporto lascia a desiderare, molto a desiderare, quindi sono eccellenti quando non ti devi appoggiare ai loro framework che, oltre ad avere tante lacune, sono incasinatissimi ed adattarli alla propria applicazione è un' impresa. Nella fattispecie devo progettare un' applicazione wireless e con i PIC non si va da nessuna parte, purtroppo. Inoltre, se si vuole lavorare bene bisogna comprarsi la versione full del compilatore e il framework per Zigbee (che insieme fanno una bella cifra, da comprarsi quasi uno scooter). Atmel ti fornisce tutto gratis e ti fa lavorare in modo semplice. Questa dovrebbe essere la politica alla base dei micro: vendere i micro e dare il miglior supporto per svilupparli. Mi pare, ma è ancora presto per dare giudizi definitivi, che Atmel ci sia riuscita. Poi sai, un micro vale l' altro, ma è il lavoro dietro che fa la differenza.

Rispondi

di ,

Bravo Tardo! Io son passato agli AVR dopo essere stato un assiduo utilizzatore di PIC (ora ho provato anche i micro della TI e della ST), ero passato per un problema di USB diciamo... molto più semplice la gestione "AVR made". Io ho iniziato con un piccolo programmatore USBasp, che usavo tranquillamente sia su Ubuntu che su Windows 7. Come piattaforma uso di solito Eclipse (http://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops/R-3.6.2-201102101200/eclipse-SDK-3.6.2-win32.zip) con il plugin (http://avr-eclipse.sourceforge.net/wiki/index.php/Plugin_Download) e mi trovo molto bene. Complimenti per l'articolo, piccolo ma incisivo ;)

Rispondi

Inserisci un commento

Per inserire commenti è necessario iscriversi ad ElectroYou. Se sei già iscritto, effettua il login.