; Assembly PIC18 - Versione 0.1 - Aprile 2018 ; Copyright (c) 2016-2018, Vincenzo Villa ; Creative Commons | Attribuzione - Condividi allo stesso modo 4.0 Internazionale (CC BY-SA 4.0) ; Creative Commons | Attribution-Share Alike 4.0 Unported ; https://www.vincenzov.net/tutorial/PIC18/assembly/uart_rx.htm ; PIC18F26K20 / MPLAB X 4.15 / MPASM v5.77 ; Ricezione e trasmissione UART, con interrupt e buffer di ricezione #include "p18f26k20.inc"; il file con la definizine dei registri specifici del PIC in uso BUFFERSIZE EQU 32 ; Dimensione del buffer di ricezione UDATA_ACS bufferRx res BUFFERSIZE ; Buffer con i dati ricevuti da UART contatoreDati res 1 ; Numero di byte ricevuti contatore res 2 ; Contatore per ciclo di ritardo ; ***************************************************************************** CODE 0x0000 ; vettore di reset, indirizzo 0. Il codice inizia qui goto main ; ***************************************************************************** ISR CODE 0x0008 ; Interrupt Service Routine (Legacy mode) btfsc PIR1, RCIF ; Se RCIF è settato, un byte è arrivato all'UART bra GestioneUART ; Esegue il codice corrispondente retfie FAST ; Nessuna interrupt riconosciuta... Indizio di un problema? GestioneUART ; Ricevuto un byte movf contatoreDati, W ; C'è ancora spazio nel buffer di ricezione? sublw BUFFERSIZE bz pieno ; Buffer pieno, il dato ricevuto non viene salvato ancora_spazio_libero movff RCREG, POSTDEC0 ; Salva il byte ricevuto nel buffer di ricezione e ; sposta il puntatore al byte successivo. ; Automaticamente azzera RCIF (se FIFO vuoto) incf contatoreDati ; Incrementa il numero dei byte nel buffer retfie FAST ; Torna ad eseguire il codice principale pieno movf RCREG, W ; Azzera il flag RCIF (WREG non viene salvato) retfie FAST ; Torna ad eseguire il codice principale ; ***************************************************************************** main call configura_IeO ; Configura le porte di Input/Output call configura_uart ; Configurazione della periferica EUSART e dei buffer bsf INTCON, PEIE ; Abilito le interruzioni dalle periferiche bsf INTCON, GIE ; Abilito la CPU a ricevere interruzioni ricomincia movf contatoreDati, W ; Ci sono dati nel buffer di ricezione? bz ricomincia ; Nessun byte nel buffer almenoUnByte ; Almeno un byte nel buffer call inviaPunto ; Trasmetto il carattere "#" call leggiByte ; Leggi il primo byte dal buffer ed accendi/spegni LED call delay100ms ; Attendi 100 ms bra ricomincia ; Attendi un altro byte ; ***************************************************************************** ; Legge il primo byte dal buffer e accende (A) o spegne (a) RC0 leggiByte bcf INTCON, GIE ; Disabilito la CPU a ricevere interruzioni movf PREINC0, W ; Aggiorna il puntatore e leggi il primo dato ricevuto sublw "A" ; Il dato ricevuto è una "A" maiuscola? bz ricevuta_A ; Esegui il codice corrispondente movf INDF0, W ; Leggi il primo dato ricevuto sublw "a" ; Il dato ricevuto è una "a" minuscola? bz ricevuta_a ; Esegui il codice corrispondente bsf LATC, RC1 ; Carattere sconosciuto -> Accendi RC1 - Errore bra torna ; Attendi un altro byte ricevuta_A bsf LATC, RC0 ; A -> Accendi RC0 bra torna ; Attendi un altro byte ricevuta_a bcf LATC, RC0 ; a -> spegni RC0 bra torna ; Attendi un altro byte torna decf contatoreDati ; Decrementa il numero dei byte nel buffer bsf INTCON, GIE ; Abilito la CPU a ricevere interruzioni return ; ***************************************************************************** ; Se il registro di trasmissione è vuoto, trasmette il carattere #, altrimenti attende ; Questa funzione è bloccante se usata più di 1000 volte al secondo (@9600 bit/s) inviaPunto attendi btfss PIR1, TXIF ; Registro di trasmissione vuoto? bra attendi ; No, attendi . movlw "#" movwf TXREG ; Scrive WREG nel regisro di trasmissione: inizia la trasmissione ; Non viene attesa la fine della trasmissione, operazione lunga return ; Trasmissione completata ; ***************************************************************************** ; Configura l'EUSART per trasmissione asincrona a 9600 bit/s ; Abilita gli interrupt ed un buffer software ; Descrizione del setup: 18.1.2.9 (Ricezione) ; 18.1.1.7 (Trasmissione) configura_uart movlw D'25' ; Inizializza il registro a 16 bit del generatore di Baud Rate movwf SPBRG ; Tabella 18.5 movlw 0 movwf SPBRGH bsf TXSTA, BRGH bsf BAUDCON, BRG16 bsf TRISC, TX ; Imposto come ingresso il pin di trasmissione (strano...) bsf TRISC, RX ; Imposto come ingresso il pin di ricezione bsf RCSTA, SPEN ; Attivo la periferica EUSART bsf RCSTA, CREN ; Attivo il ricevitore bcf TXSTA, SYNC ; Attivo la modalità asincrona bsf TXSTA, TXEN ; Attivo il trasmettitore bsf PIE1, RCIE ; Abilita EUSART a generare un interrupt quando arriva un byte ; Ricordarsi di attivare anche PEIE e GIE ; Configura il buffer di ricezione software clrf contatoreDati ; Azzera il contatore dei byte ricevuti lfsr FSR0, bufferRx+(BUFFERSIZE-1) ; Inizializza il puntatore alla fine del buffer ; NOTA: il buffer "cresce verso il basso" return ;***************************************************************************** ; Configura altre periferiche, diverse da EUSART (esempio) configura_IeO ; clrf TRISC ; Imposta PORTC come uscita clrf LATC ; Tutte le uscite di PORTC a zero (LED spenti) return ;***************************************************************************** ; Ciclo di ritardo - 100 ms (circa) @ 1 MHz delay100ms movlw 0x15 ; imposta il contatore a 0x1500 movwf contatore+1 clrf contatore ripeti decfsz contatore ; decrementa la variabile contatore (LSB) e salta ; l'istruzione seguente quanto contatore.LSB=0 bra ripeti ; ripeti decfsz contatore+1 ; decrementa la variabile contatore (MSB) e salta ; l'istruzione seguente quanto contatore.MSB=0 bra ripeti ; ripeti return END ; Fine del file