; **************************************************************************************** ; ; File: AVR_UART2.ASM * ; Data: 31.Mar.2004 * ; Version: 1.0 * ; IDE: AVR-Studio 4.0 * ; * ; Autore: Giuseppe Franco - giuseppe.franco@chilab.polito.it * ; Riferimenti: Politecnico di Torino - Laboratorio Materiali e Microsistemi * ; ; **************************************************************************************** ; Questo programma serve ad imparare come utilizzare la periferica ; integrata della seriale asincrona (UART), in particolare: ; ; --> come configurare i registri della periferica seriale. ; --> come inviare e ricevere caratteri con l'utilizzo dei flags di stato. ; --> come leggere dei dati costanti memorizzati nella memoria programma (FLASH). ; --> utilizzo dell'indirizzamento indiretto in program memory con il ; registro 'Z' e l'istruzione 'lpm' . ; ; **************************************************************************************** .NOLIST ;.INCLUDE "C:\programmi\atmel\avr tools\avrassembler\appnotes\8515def.inc" .INCLUDE "C:\usr\develop\atmel\avr tools\avrassembler\appnotes\8535def.inc" .LIST ; Definizione dei registri utilizzati .DEF mp = R16 .DEF char = R17 .DEF n1 = R18 .DEF n2 = R19 .EQU RED_LED = PC0 .EQU YELLOW_LED = PC1 .EQU GREEN_LED = PC2 .EQU XTAL_FREQ = 4000 ; frequenza del quarzo esterno in KHz .EQU BAUD = 9600 ; baud rate main: ; Viene impostato lo stack-pointer ed azzerato il registro di stato (tutti gli interrupt sono mascherati) ldi mp,HIGH(RAMEND) out SPH,mp ldi mp,LOW(RAMEND) out SPL,mp ldi mp,0x00 out SREG,mp ldi mp,0b00000111 out DDRC,mp ; Abilito la porta C in uscita sul bit 0,1 e 2 per pilotare tre led con ; il metodo di scrittura diretta sul pin della porta. ldi mp,0b00000010 out DDRD,mp ; Abilito la porta D sul bit 1 in uscita per avere la trasmissione ; sul pin quando avviene la scrittura nel registro della seriale. ldi mp,(1 << RXEN) | (1 << TXEN) out UCR,mp ldi mp,( (XTAL_FREQ *1000 ) / ( 16 * BAUD ) - 1 ) out UBRR,mp ; Vengono impostati i registri di controllo della UART: in particolare ; sono abilitati il ricevitore ed il trasmettitore, e viene ; selezionato il baud-rate, che dipende dalla frequenza del quarzo esterno. ldi ZH, HIGH(hello_str << 1) ldi ZL, LOW(hello_str << 1) rcall PutString ; stampa una stringa, che è stata memorizzata all'indirizzo passato come ; argomento nel registro Z. Tale registro è composto da due registri dedicati ; che formano un valore esteso su 16bit, utile ad indirizzare lo spazio di ; memoria programma. main_loop: ldi ZH, HIGH(choice_str << 1) ldi ZL, LOW(choice_str << 1) rcall PutString rcall GetChar andi char, 0b11011111 ; Si verifica se un carattere è stato ricevuto, e si genera la codifica ; dei soli caratteri ascii maiuscoli. rcall PutChar ; Si genera l'echo del carattere ricevuto. cpi char, 'R' brne not_red rcall RedOn rjmp main_loop not_red: cpi char, 'G' brne not_yellow rcall YellowOn rjmp main_loop not_yellow: cpi char, 'V' brne not_green rcall GreenOn rjmp main_loop not_green: ldi ZH, HIGH(error_str << 1) ldi ZL, LOW(error_str << 1) rcall PutString rjmp main_loop ; Si esegue la routine corrispondente al tasto premuto. La pressione dei ; tre diversi tasti comporta l'accensione dei tre led relativi; altri tasti ; generano un messaggio di errore. ; Accende il led ROSSO e stampa un messaggio sulla seriale. RedOn: cbi PORTC, RED_LED sbi PORTC, YELLOW_LED sbi PORTC, GREEN_LED ldi ZH, HIGH(prompt_str << 1) ldi ZL, LOW(prompt_str << 1) rcall PutString ldi ZH, HIGH(red_str << 1) ldi ZL, LOW(red_str << 1) rcall PutString ret ; Accende il led GIALLO e stampa un messaggio sulla seriale. YellowOn: sbi PORTC, RED_LED cbi PORTC, YELLOW_LED sbi PORTC, GREEN_LED ldi ZH, HIGH(prompt_str << 1) ldi ZL, LOW(prompt_str << 1) rcall PutString ldi ZH, HIGH(yellow_str << 1) ldi ZL, LOW(yellow_str << 1) rcall PutString ret ; Accende il led VERDE e stampa un messaggio sulla seriale. GreenOn: sbi PORTC, RED_LED sbi PORTC, YELLOW_LED cbi PORTC, GREEN_LED ldi ZH, HIGH(prompt_str << 1) ldi ZL, LOW(prompt_str << 1) rcall PutString ldi ZH, HIGH(green_str << 1) ldi ZL, LOW(green_str << 1) rcall PutString ret ; Attende un carattere dalla seriale in polling: se nessun carattere arriva ; viene generato un loop infinito. In genere per evitare questo incoveniente ; si utilizza una routine sotto la gestione dell'interrupt, in modo da gestire ; gli arrivi dei caratteri in maniera asincrona, solo quando sono disponibili ; nel buffer di ricezione. GetChar: in mp, USR sbrs mp, RXC rjmp GetChar in char, UDR ret ; Invia un carattere, quando il buffer di trasmissione è vuoto; in caso contrario ; si attende in un loop infinito. PutChar: in mp, USR sbrs mp, UDRE rjmp PutChar out UDR, char ret ; Invia una stringa di byte terminata con un carattere 'NULL' uguale a '0'. PutString: ; lpm char, Z+ ; I micro AT90S8515-AT90S8535 utilizzano solo il registro 'R0' ; e non gestiscono la funzione di 'autoincrement' di 'Z'. lpm adiw ZL, 1 mov char, R0 cpi char, 0 breq put_str_exit rcall PutChar rjmp PutString put_str_exit: ret ; Di seguito sono memorizzate nella FLASH le varie stringhe utilizzate per la ; stampa sul terminale. .CSEG prompt_str: .DB ' ','-','-','>',' ',0 red_str: .DB 'r','e','d',' ','O','N', 13,10,0 yellow_str: .DB 'y','e','l','l','o','w',' ','O','N', 13,10,0 green_str: .DB 'g','r','e','e','n',' ','O','N', 13,10,0 error_str: .DB 'e','r','r','o','r','!', 13,10,0 hello_str: .DB 'h','e','l','l','o',' ',':','-',')', 13,10,0 choice_str: .DB 'p','r','e','s','s',' ','R',' ','G',' ','V', 13,10,0