Arduino UNO Assembly introduzione
Confronto tra Arduino UNO e altre versioni
Architettura ATmega48A/PA/88A/PA/168A/PA/328/P Dallo schema si vede che sono presenti 32 registri GPW (General Purpose Working) connessi alla ALU
Funzioni speciali dei pin I pin PB7 e PB6 sono utilizzati per l’applicazione di un oscillatore a quarzo esterno XTAL2 o per l’applicazione di una timer asincrono TOSC2; I pin PD2 e PD3 possono anche essere utilizzati anche come sorgente esterna di interrupt, in corrispondenza della variazione dello stato di tali pin.
Perché programmare in assembly Per avere accesso diretto e più semplice ai registri Meno possibilità di sbagliare evitando conflitti tra hardware e software Si bypassa il codice del compilatore che può introdurre righe di codice ridondanti Si produce un codice più veloce
Porte INPUT/OUTPUT Per poter programmare in Assembly bisogna conoscere sempre la struttura hardware interna del microcontrollore. Si parte dalle porte Input/output I registri di interfaccia INPUT/OUTPUT di arduino sono denominati B,C,D B per il controllo dei pin digitali da 8 a 13 C per il controllo dei pin di ingresso analogico D per il controllo dei pin digitali da 0 a 7 I registri che controllano i pin di INPUT/OUTPUT sono denominati DDR, PORT, PIN. Il registro DDR, determina se il pin è un INPUT o OUTPUT. Il registro PORT controlla se il pin è HIGH o LOW. l registro PIN legge lo stato dei pin INPUT impostati in ingresso con pinMode().
DDR PIN e PORT bit pin bit pin I bit 7 e 6 sono per il quarzo esterno I registri DDR e PORT possono essere sia scritti che letti. I registri PIN controllano lo stato degli ingressi e quindi, possono essere solo letti. PORTD, DDRD, PIND riguardano i pin da 0 a 7; DDRD è il registro di direzione INPUT/OUTPUT , un bit è zero se il relativo pin è di INPUT altrimenti è uno; PIND legge lo stato delle porte se sono di ingresso; PORTD controlla se le porte sono HIGH o LOW Struttura del registro PORTD e DDRD PORTB, DDRB, PINB riguardano i pin da 8 a 13; DDRB è il registro di direzione INPUT/OUTPUT, un bit è zero se il relativo pin è di INPUT altrimenti è uno; PINB legge lo stato delle porte se sono di ingresso; PORTB controlla se le porte sono HIGH o LOW. Struttura del registro DDRB e PORTB bit 7 6 5 4 3 2 1 D7 D6 D5 D4 D3 D2 D1 D0 pin bit 7 6 5 4 3 2 1 D13 D12 D11 D10 D9 D8 pin I bit 7 e 6 sono per il quarzo esterno
Porte analogiche PORTC, DDRC, PINC riguardano i pin analogici DDRC è il registro di direzione INPUT/OUTPUT; PINC legge lo stato delle porte se sono di ingresso; PORTC controlla se le porte sono HIGH o LOW Struttura del registro PORTC pin 7 6 5 4 3 2 1 A5 A4 A3 A2 A1 A0 I bit 7 e 6 sono accessibili solo ad arduino mini bit
Schema circuitale
Esempi con IDE Arduino blink #define F_CPU 16000000UL //definisce la frequenza del clock esterno #include <avr/io.h> #include <util/delay.h> int main (void) { DDRB =0b00100000; //il terzo bit è a 1, quindi, il pin corrispondente (13) è OUTPUT PORTB=0b00000000; //tutti i pin sono a 0V while(1) //fino a che il dispositivo è alimentato _delay_ms(1000); PORTB=0b00100000; //dopo 1 s il pin 13 è a 5V _delay_ms(1000);//lo stato HIGH dura 1 s e poi si ritorna daccapo }
Osservazioni La costante F_CPU definisce la frequenza di clock alla quale lavorerà la CPU del microcontrollore grazie all' oscillatore esterno, ed è obbligatorio dichiararla al principio del codice in caso di utilizzare la funzione _delay_ms o qualsiasi altra funzione dichiarata in utils/delay.h. I valori della costante F_CPU devono essere corretti altrimenti, i ritardi potrebbero essere errati. Nel caso di arduino UNO ragioniamo a 16 MHz _delay_ms appartiene alla libreria utill/delay La funzione I/O è dichiarata nella libreria AVR Un pin digitale è di INPUT se il bit corrispondente del registro DDR è posto a 0 Un pin digitale è di OUTPUT se il bit corrispondente del registro DDR è posto a 1 Se un pin è a livello logico alto, il bit corrispondente di PORT sarà 1 Se un pin è a livello logico basso, il bit corrispondente di PORT sarà 0
Esempi con IDE Arduino comandare il led 13 con un interruttore sul pin 8 #define F_CPU 16000000UL //definisce la frequenza del clock esterno #include <avr/io.h> #include <util/delay.h> int main (void) { DDRB =0b00100000; //il sesto bit è a 1, quindi, il pin corrispondente (13) è OUTPUT PORTB=0b00000000; //tutti i pin sono a 0V while(1) //fino a che il dispositivo è alimentato {if(PORTB=0b00000000)//se tutti i pin sono a 0V PORTB=0b00000000; if(PORTB=0b00000001)//se il primo bit è 1, cioè il pin 8 di INPUT è a livello logico alto PORTB=0b00100000 //il led 13 è acceso _delay_ms(1000);//lo stato HIGH dura 1 s e poi si ritorna daccapo }
Display a 7 segmenti a catodo comune Ad ogni led del display si associa un pin di arduino Supponiamo di voler fare le seguenti associazioni: led a b c d e f g h 2 3 4 5 6 7 8 9 pin Bit del registro D f e d c b a 7 6 5 4 3 2 1 h g 7 6 5 4 3 2 1
Es scrivere 0 e 1 con un ritardo di 1 secondo #define F_CPU 16000000UL //definisce la frequenza del clock esterno #include <avr/io.h> #include <util/delay.h> int main (void){ DDRB =0b00000011; //primo e secondo bit OUTPUT DDRD=0b11111100; //tutti i pin sono OUTPUT tranne il primo e secondo while(1) //fino a che il dispositivo è alimentato {PORTB=0b11111100)// tutti i pin sono a 1 tranne il primo e secondo PORTD=0b00000000; tutti i pin sono a zero _delay_ms(1000);// PORTB=0b000011000)// il 3 e il 4 sono a 1 e corrispondono a b e c PORTD=0b00000000 //tutti i pin sono a zero _delay_ms(1000); }