/* ; **************************************************************************************** ; * ; File: avr_C_blink.c * ; Data: 07.Gen.2005 * ; Version: 1.0 * ; * ; Autore: Giuseppe Franco - giuseppe.franco@chilab.polito.it * ; Riferimenti: Politecnico di Torino - Laboratorio Materiali e Microsistemi * ; * ; IDE: WinAVR * ; C-Compiler: gcc 3.3.1 * ; Assembler: GNU assembler v 2.14 (avr) + coff avr patch * ; Linker: == * ; * ; **************************************************************************************** ; * ; Files richiesti: * ; * ; * ; **************************************************************************************** ; * ; Descrizione: * ; Questo programma serve ad imparare come utilizzare le porte di I/O * ; del microcontrollore, in lettura ed in scrittura, in particolare: * ; * ; -> quali operazioni effettuare prima dell'inizio di un programma. * ; -> come configurare le porte per il loro utilizzo in ingresso ed in uscita. * ; -> come accedere e configurare i registri interni del microcontrollore. * ; -> come accedere ad una porta di uscita (accendere due led). * ; -> come accedere ad una porta in ingresso (lettura di un deviatore). * ; -> come generare ritardi per mezzo delle istruzioni disponibili. * ; -> l'utilizzo di alcune direttive 'C'. * ; * ; **************************************************************************************** ; * ; Annotazioni: * ; * ; * ; **************************************************************************************** */ #include #include /* come in assembler è utile utilizzare alcune direttive, che nel caso della programmazione in C iniziano con il simbolo '#'. Nel caso particolare si include un file in cui sono definiti tutti i nomi che si riferiscono ai registri interni del microcontrollore, ed ai relativi bit di controllo e/o stato. Vengono anche incluse le definizioni relativi alle funzioni per generari ritardi software. */ void RegisterInit( void ); int main( void ) { /* Il C realizza un programma completo come collezione di funzioni indipendenti, ciascuna delle quali ne può richiamarne una qualsiasi altra, anche recursivamente. Anche nel caso di una programmazione in C, analogamente come in assembler, esiste un'area del codice che deve esssere eseguita alla partenza, in questo caso la prima funzione che deve essere eseguita *** D E V E *** chiamarsi 'main()'. Il compilatore C provvede autonomamente a generare il vettore di reset in maniera che la funzione 'main()' venga eseguita ad ogni evento di reset. */ unsigned char counter; /* All'interno delle funzioni possono essere definite delle variabili locali, visibili cioè solo nel proprio contesto; in questo caso utilizziamo una variabile 'counter' su 8 bit senza segno da usarsi come contatore temporaneo. */ RegisterInit(); /* Viene chiamata la funzione che inizializza i registri interni del microcontrollore. E' utile definire alcune funzioni che contangano tutte le inizializzazioni, sia relative alla configurazione dei registri interni, che delle variabili di sistema del programma */ while( 1 ) { /* La funzione 'main()' deve essere un 'LOOP' INFINITO e MAI ritornare !!! */ PORTC |= 0x01; /* forma abbreviata di: PORTC = PORTC | 0x01; */ /* viene impostato il bit 0 della porta C ad uno con un'operazione di 'OR' sui bit */ counter = 0; while( counter != 10 ) { /* la funzione _delay_loop_2() è una funzione di libreria relativa al core ATMEL-AVR che realizza 4 cicli per loop di ritardo, in questo caso sono realizzati 120.000 cicli di ritardo */ _delay_loop_2( 30000 ); counter++; } /* il 'loop' precedente conta 10 * 120.000 = 1.200.000 cicli di ritardo (con un clock di 8MHz sono circa 150 ms)*/ PORTC &= ~0x01; /* forma abbreviata di: PORTC = PORTC & ~0x01; */ /* viene azzerato il bit 0 della porta C ad uno con un'operazione di 'AND' negata sui bit */ counter = 0; while( counter != 10 ) { _delay_loop_2( 30000 ); counter++; } } /* anche se il loop principale risulta essere infinito, viene inserito il 'return' per evitare warning del compilatore (infatti la funzione main() deve ritornare un intero ... anche se in pratica non ritorna mai! ), e per correttezza formale. */ return 0; } void RegisterInit( void ) { DDRC = 0x01; /* Anche in questo caso è indispensabile impostare i registri di controllo del microprocessore, in particolare occorre in questo caso che il registro direzione dati della porta C sia configurato in uscita, come già visto per l'assembler. */ return; }