- Schema elettrico:
- Microcontrollore PIC PIC16F877A LED lampeggiante Codice sequenza e spiegazione di lavoro:
Nel nostro precedente tutorial, abbiamo imparato a lampeggiare un LED usando il microcontrollore PIC e abbiamo costruito lo stesso circuito sulla scheda Perf. Quindi abbiamo utilizzato PICkit 3, ICSP e MPLAB IPE per scaricare il programma sulla nostra scheda Perf. Ora, in questo tutorial, avanzeremo da soli fino a utilizzare più pin sul microcontrollore PIC. Useremo 7 uscite (LED) e un ingresso. Per questo tutorial useremo la vecchia scheda Perf (mostrata sotto) e aggiungeremo berg stick per estrarre i pin richiesti sulla seconda scheda LED. Alla fine di questo tutorial genereremo una sequenza di LED lampeggianti utilizzando il microcontrollore PIC PIC16F877A e impareremo come utilizzare più ingressi e uscite, alcune nozioni di base sul loop "for" e sulla chiamata di funzioni.
La scheda LED non è altro che un'altra scheda di prestazioni, sulla quale salderemo i LED con un resistore limitatore di corrente (mostrato sotto). Aggiungeremo anche un pulsante per avviare la sequenza di lampeggiamento del LED.
Schema elettrico:
Microcontrollore PIC PIC16F877A LED lampeggiante Codice sequenza e spiegazione di lavoro:
Il codice completo è stato fornito di seguito (controllare alla fine), qui lo otterremo riga per riga. Questo codice inizierà a illuminare i LED in modo sequenziale quando si preme il pulsante. Per capire le sequenze guarda il video alla fine del tutorial. Ti consiglierei di confrontare l'output mostrato nel video con il codice sottostante e cercare di capire il programma.
Diamo un'occhiata al codice riga per riga. Le prime righe sono per impostare i bit di configurazione che sono stati spiegati nel tutorial precedente, quindi per ora li sto saltando. Il modo migliore per capire qualsiasi programma è iniziare dalla funzione main ( void main () ), quindi facciamolo
TRISB0 = 1; // Indica all'MCU che il pin 0 di PORTB viene utilizzato come ingresso per il pulsante. TRISD = 0x00; // Indica all'MCU che tutti i pin sono in uscita PORTD = 0x00; // Inizializza tutti i pin su 0
La parola TRIS viene utilizzata per definire se il pin viene utilizzato come input / output e la parola PORT viene utilizzata per creare un pin High / Low. La linea TRISB0 = 1 renderà lo 0 ° pin di PORT B come input. Questo sarà il nostro pulsante. Le linee TRISD = 0x00; PORTD = 0x00; renderà tutti i pin della porta D come Output e assegnerà un valore iniziale di LOW a quei pin.
Poiché abbiamo detto che B0 è usato come ingresso, collegheremo un'estremità del pulsante al pin B0 e l'altra estremità a terra. A quel punto, ogni volta che premiamo il pulsante, il pin verrà tenuto a terra come mostrato nello schema di collegamento sopra. Ma per far sì che ciò accada, dobbiamo utilizzare una resistenza di pull up in modo che il pin venga tenuto alto quando il pulsante non viene premuto. Un resistore di pull up è qualcosa del genere.
Ma il nostro MCU PIC ha un debole resistore pull up interno che può essere attivato dal software in questo modo risparmiando un sacco di problemi (quando devono essere collegati più pulsanti).
Cos'è un debole resistore di pull up?
Esistono due tipi di resistori di pull up, uno è il pull up debole e l'altro è il pull up forte. Le resistenze di pull up deboli sono di valore elevato e quindi consentono a una corrente debole di fluire e le resistenze di pull up forti sono di valore basso consentendo così il flusso di una corrente forte. Tutti gli MCU utilizzano principalmente resistori pull up deboli. Per attivarlo nel nostro MCU PIC, dobbiamo esaminare la nostra scheda tecnica per OPTION_REG (registro delle opzioni) come mostrato nell'istantanea qui sotto.
Come mostrato, il bit 7 si occupa del debole resistore di pull up. Dovrebbe essere impostato a zero per attivarlo. Questo viene fatto da OPTION_REG <7> = 0 . Questo riguarda specificamente il bit 7 lasciando gli altri bit ai suoi valori predefiniti. Con questo entriamo nel nostro ciclo while, dove controlla se il pulsante è premuto usando if (RB0 == 0). Se la condizione è soddisfatta chiamiamo la nostra funzione con i parametri 1, 3, 7 e 15.
sblink (1); // FUNCTION CALL 1 con parametro 1 sblink (3); // FUNCTION CALL 3 con parametro 3 sblink (7); // FUNCTION CALL 7 con parametro 7 sblink (15); // FUNCTION CALL 4 con parametro 15
Perché usiamo le funzioni?
Le funzioni vengono utilizzate per ridurre il numero di righe nel nostro codice. Questo è ciò che la maggior parte di noi avrebbe saputo. Ma perché dobbiamo ridurre il numero di righe, soprattutto quando si tratta di programmazione MCU. Il motivo è lo spazio limitato nella memoria del nostro programma. Se non ottimizziamo il codice correttamente, potremmo esaurire lo spazio di memoria. Questo tornerà utile quando scriviamo lunghe pagine di codici.
Qualsiasi funzione avrà una funzione Definition ( sblink (int get) nel nostro caso) e una funzione Call ( sblink (1) nel nostro caso). È facoltativo avere una dichiarazione di funzione, per evitarlo ho inserito la mia definizione di funzione prima di chiamare la funzione nella mia funzione principale.
I parametri della funzione sono il valore che verrà passato dalla chiamata alla definizione della funzione. Nel nostro caso i valori interi (1, 3, 7, 15) sono i parametri che vengono passati dalla chiamata di funzione e la variabile "get" ottiene il valore dei parametri nella definizione della funzione per elaborarli. Una funzione può avere più di un parametro.
Una volta chiamata la funzione, verranno eseguite le seguenti righe nella definizione della funzione.
for (int i = 0; i <= 7 && RB0 == 0; i ++) {PORTD = get << i; // Il LED sposta la sequenza a sinistra __delay_ms (50); } for (int i = 7; i> = 0 && RB0 == 0; i--) {PORTD = get << i; // Il LED sposta la sequenza a sinistra __delay_ms (50); }
Ora questa riga sembra essere strana: PORTD = get << i . Spiegherò cosa sta realmente accadendo qui.
"<<" è un operatore di spostamento a sinistra che sposta tutti i bit nella posizione sinistra. Ora, quando chiamiamo la funzione sblink (int get) con il parametro '1' come sblink (1), renderà il valore di 'get' come 1, che in binario è 0b00000001. Quindi questa riga sarà come PORTD = 0b00000001 << i .
Il valore di "i" varierà da 0 a 7 poiché abbiamo utilizzato un ciclo " for " per (int i = 0; i <= 7 && RB0 == 0; i ++). Il valore di 'i' compreso tra 0 e 7 cambierà il risultato come segue:
Come puoi vedere abbiamo acceso un LED alla volta (da sinistra a destra) tenendo il resto spento. Anche il successivo 'ciclo for' for (int i = 7; i> = 0 && RB0 == 0; i--) farà lo stesso ma questa volta il LED si accenderà da destra a sinistra in sequenza, partendo da 7 e scendendo a 0. Abbiamo utilizzato un ritardo di 200ms in modo da poter visualizzare l'accensione e lo spegnimento del LED.
Ora quando passiamo il valore 3 nella funzione sblink (int get) , verrà eseguita la funzione sblink (3) che rende il valore di 'get' come 0b00000011, quindi il risultato su PORTD sarà:
Quindi ora questa volta due LED saranno accesi in un dato momento usando sblink (3). Allo stesso modo per sblink (7) e sblink (15), tre e quattro LED saranno accesi in sequenza. Una volta completato, faremo accendere tutti i LED utilizzando la riga PORTD = 0xFF . Guarda il video qui sotto per una dimostrazione completa.
Spero che tu abbia capito il codice e quindi abbia imparato a usare le funzioni, i cicli "for" e "while" per ottenere gli output desiderati. Ora puoi modificare il codice per far lampeggiare la tua diversa sequenza di LED. Vai avanti compila il tuo codice e scaricalo sul tuo MCU e goditi l'output. Puoi usare la sezione commenti se rimani bloccato da qualche parte. Ho anche allegato la simulazione e i file di programma qui.
Per ora è tutto nel nostro prossimo tutorial impareremo come utilizzare i timer PIC16F877A invece di utilizzare le funzioni di ritardo. Puoi sfogliare tutti i tutorial del microcontrollore PIC qui.