Sommario:
- Passaggio 1: come possiamo far parlare tra loro due microcontrollori?
- Passaggio 2: subroutine di comunicazione
- Passaggio 3: conclusione
Video: Tutorial Assembler AVR 6: 3 passaggi
2024 Autore: John Day | [email protected]. Ultima modifica: 2024-01-30 09:59
Benvenuto nell'esercitazione 6!
Il tutorial di oggi sarà breve in cui svilupperemo un metodo semplice per comunicare dati tra un atmega328p e un altro utilizzando due porte che li collegano. Prenderemo quindi il rullo di dadi dal Tutorial 4 e Register Analyzer dal Tutorial 5, li collegheremo e utilizzeremo il nostro metodo per comunicare il risultato dei lanci di dadi dal rullo all'analizzatore. Quindi stamperemo il rotolo in binario usando i LED che abbiamo costruito per l'analizzatore nel Tutorial 5. Una volta che avremo funzionato, saremo in grado di costruire il prossimo pezzo del nostro progetto complessivo nel prossimo tutorial.
In questo tutorial avrai bisogno di:
- La tua scheda di prototipazione
- Il tuo rullo di dadi dal Tutorial 4
- Il tuo analizzatore di registro dal tutorial 5
- Due fili di collegamento
-
Una copia della Scheda Tecnica Completa (revisione 2014):
www.atmel.com/images/Atmel-8271-8-bit-AVR-M…
-
Una copia del manuale del set di istruzioni (revisione 2014):
www.atmel.com/images/atmel-0856-avr-instruc…
Ecco un link alla raccolta completa dei miei tutorial sull'assemblatore AVR:
Passaggio 1: come possiamo far parlare tra loro due microcontrollori?
Dal momento che stiamo iniziando ad espandere il nostro progetto in modo che il nostro singolo prodotto finale sia costituito da una raccolta di parti più piccole, avremo bisogno di più pin di quelli che un singolo Atmega328P può fornire. Quindi faremo ogni parte del progetto complessivo su un microcontrollore separato e poi faremo in modo che condividano i dati tra loro. Quindi il problema che dobbiamo risolvere è come possiamo trovare un metodo semplice per consentire ai controller di parlare tra loro e trasferire dati tra di loro? Bene, una cosa su questi controller è che ognuno esegue 16 milioni di istruzioni al secondo. Questo è un tempo molto preciso e quindi possiamo usare questo tempo per trasferire i dati. Se usiamo ritardi di millisecondi per costituire i dati, non dobbiamo essere così precisi poiché la CPU esegue 16.000 istruzioni in un singolo millisecondo. In altre parole, un millisecondo è un'eternità per la CPU. Allora proviamo con i dadi. Voglio trasmettere il risultato di un lancio di dadi dal chip del rullo di dadi al chip dell'analizzatore. Supponiamo che tu fossi dall'altra parte della strada e io volessi segnalarti il risultato del mio lancio di un paio di dadi. Una cosa che potrei fare, se entrambi avessimo un orologio, potrei accendere una torcia, poi quando sei pronto per ricevere i miei dati accendi la torcia ed entrambi avviamo i nostri orologi. Poi tengo accesa la torcia per il numero esatto di millisecondi mentre i dadi tirano e poi la spengo. Quindi se tirassi un 12 manterrei la luce accesa per 12 millisecondi. Ora il problema con quanto sopra è che, per te e me, non c'è modo di cronometrare le cose in modo abbastanza accurato da distinguere tra 5 millisecondi e 12 millisecondi. Ma che dire di questo: supponiamo di decidere di tenere accesa la mia luce per un anno per ogni numero sui dadi? Quindi se tiro un 12 ti illuminerei per 12 anni e penso che sarai d'accordo che non c'è possibilità che tu possa fare un errore nel capire il numero giusto? Potresti fare una pausa e andare a giocare a baseball, potresti anche andare a giocare a dadi a Las Vegas per 6 mesi, a patto che a un certo punto durante l'anno guardi dall'altra parte della strada per vedere se la luce era accesa non ti perdevi un conteggio. Bene, questo è esattamente quello che stiamo facendo per i microcontrollori! Un singolo millisecondo per la CPU è come un anno. Quindi, se accendo il segnale per 12 millisecondi, non c'è quasi nessuna possibilità che l'altro microcontrollore lo confonda per 10 o 11 indipendentemente da quali interruzioni e cosa non accada nel frattempo. Per i microcontrollori, un millisecondo è un'eternità. Quindi ecco cosa faremo. Per prima cosa sceglieremo due porte sul controller come porte di comunicazione. Userò PD6 per la ricezione dei dati (potremmo chiamarlo Rx se ci piace) e sceglierò PD7 per la trasmissione dei dati (potremmo chiamarlo Tx se ci piace). Il chip dell'analizzatore controllerà periodicamente il suo pin Rx e se vede un segnale passerà a una "subroutine di comunicazione" e quindi trasmetterà un segnale di ritorno al rullo di dadi dicendo che è pronto a ricevere. Entrambi inizieranno a cronometrare e il rullo dei dadi trasmetterà un segnale (cioè 5V) per un millisecondo per numero sui dadi. Quindi, se il tiro fosse un doppio sei o un 12, il rullo dei dadi imposterebbe il PD7 su 5 V per 12 millisecondi e poi lo reimposterebbe su 0 V. L'analizzatore controllerà il suo pin PD6 ogni millisecondo, contando ogni volta, e quando tornerà a 0V, emetterà il numero risultante sul display dell'analizzatore, mostrando un dodici in binario sui LED. Quindi questo è il piano. Vediamo se riusciamo a implementarlo.
Passaggio 2: subroutine di comunicazione
La prima cosa che dobbiamo fare è collegare i due controller. Quindi prendi un filo da PD6 su uno e collegalo a PD7 sull'altro e viceversa. Quindi inizializzarli impostando PD7 su OUTPUT su entrambi e PD6 su INPUT su entrambi. Infine impostali tutti su 0V. In particolare, aggiungi quanto segue alla sezione Init o Reset del codice su ciascun microcontrollore:
sbi DDRD, 7; PD7 impostato su uscita
cbi Porta D, 7; PD7 inizialmente 0V cbi DDRD, 6; PD6 impostato su ingresso cbi PortD, 6; PD6 inizialmente 0V clr totale; totale sui dadi inizialmente 0
Ora impostiamo la subroutine di comunicazione sul chip del dado. Per prima cosa definisci una nuova variabile in alto chiamata "total" che memorizzerà il numero totale lanciato sulla coppia di dadi e lo inizializzerà a zero.
Quindi scrivere una subroutine per comunicare con l'analizzatore:
comunicare:
cbi Porta D, 7 sbi Porta D, 7; Invia segnale pronto attesa: sbic PinD, 6; leggere PinD e saltare se 0V rjmp wait delay 8; ritardo per sincronizzare (trovato sperimentalmente) send: dec total delay 2; ritardo per ogni conteggio die cpi totale, 0; 0 qui significa che il numero "totale" dei ritardi è stato inviato breq PC+2 rjmp send cbi PortD, 7; PD7 a 0V clr totale; reimposta il totale dei dadi a 0 ret
Nell'analizzatore aggiungiamo una rcall dalla routine principale alla subroutine di comunicazione:
analizzatore clr; prepararsi per il nuovo numero
sbic PinD, 6; controllare PD6 per un segnale 5V rcall comunicare; se 5V vai a comunicare mov analizzatore, totale; uscita all'analizzatore display rcall analizzatore
e quindi scrivere la subroutine di comunicazione come segue:
comunicare:
clr totale; reset totale a 0 ritardo 10; ritardo per eliminare i rimbalzi sbi PortD, 7; impostare PB7 a 5V per segnalare pronta ricezione: ritardo 2; aspetta il prossimo numero inc totale; incremento totale sbic PinD, 6; se PD6 torna a 0V abbiamo finito di ricevere rjmp; altrimenti torna indietro per ulteriori dati cbi PortD, 7; ripristina PD7 quando hai finito ret
Ecco qua! Ora ogni microcontrollore è predisposto per comunicare il risultato del lancio dei dadi e poi visualizzarlo sull'analizzatore.
Implementeremo un modo molto più efficiente di comunicare in seguito quando avremo bisogno di trasferire il contenuto di un registro tra controller invece di un semplice lancio di dadi. In tal caso, utilizzeremo ancora solo due fili per collegarli ma useremo 1, 1 per indicare "inizio trasmissione"; 0, 1 significa "1"; 1, 0 significa "0"; e infine 0, 0 a significare "fine trasmissione".
Esercizio 1: Vedi se riesci a implementare il metodo migliore e usalo per trasferire il lancio dei dadi come un numero binario a 8 bit.
Allego un video che mostra il mio in funzione.
Passaggio 3: conclusione
Ho allegato il codice completo per riferimento. Non è così pulito e ordinato come vorrei, ma lo ripulirò man mano che lo espandiamo nei tutorial futuri.
D'ora in poi allegherò solo i file contenenti il codice anziché digitarlo tutto qui. Digitiamo solo le sezioni di cui siamo interessati a discutere.
Questo è stato un breve tutorial in cui abbiamo trovato un metodo semplice per dire al nostro microcontrollore analizzatore quale sia il risultato del nostro lancio di dadi dal nostro microcontrollore a rulli di dadi utilizzando solo due porte.
Esercizio 2: Invece di utilizzare un segnale di pronto per mostrare quando il rullo dei dadi è pronto per trasmettere e un altro quando l'analizzatore è pronto per ricevere, utilizzare un "interrupt esterno" chiamato "Pin Change Interrupt". I pin dell'atmega328p possono essere utilizzati in questo modo, motivo per cui hanno accanto PCINT0 tramite PCINT23 nel diagramma di pinout. Puoi implementarlo come un'interruzione in modo simile a come abbiamo fatto con l'interruzione di overflow del timer. In questo caso il "gestore" dell'interrupt sarà la subroutine che comunica con il rullo dei dadi. In questo modo non è necessario chiamare effettivamente la subroutine di comunicazione da main: andrà lì ogni volta che c'è un interrupt proveniente da un cambio di stato su quel pin.
Esercizio 3: Un modo molto migliore di comunicare e trasferire dati tra un microcontrollore a una raccolta di altri è utilizzare l'interfaccia seriale a 2 fili incorporata sul microcontrollore stesso. Prova a leggere la sezione 22 della scheda tecnica e vedi se riesci a capire come implementarla.
Utilizzeremo queste tecniche più sofisticate in futuro quando aggiungeremo ulteriori controller.
Il fatto che tutto ciò che abbiamo fatto con il nostro analizzatore sia stato prendere il totale del tiro di dadi e poi stamparlo in binario usando i LED non è ciò che è importante. Il fatto è che ora il nostro analizzatore "sa" qual è il tiro di dadi e può usarlo di conseguenza.
Nel prossimo tutorial cambieremo lo scopo del nostro "analizzatore", introducendo qualche altro elemento del circuito e usando il lancio dei dadi in un modo più interessante.
Fino alla prossima volta…
Consigliato:
Tutorial Assembler AVR 2: 4 passaggi
AVR Assembler Tutorial 2: questo tutorial è una continuazione del "AVR Assembler Tutorial 1" Se non hai seguito il Tutorial 1, dovresti fermarti ora e farlo prima. In questo tutorial continueremo il nostro studio sulla programmazione in linguaggio assembly di atmega328p u
Tutorial Assembler AVR 1: 5 passaggi
AVR Assembler Tutorial 1: Ho deciso di scrivere una serie di tutorial su come scrivere programmi in linguaggio assembly per l'Atmega328p che è il microcontrollore utilizzato nell'Arduino. Se le persone rimangono interessate, continuerò a pubblicarne una a settimana o giù di lì fino a quando non finirò
Tutorial Assembler AVR 8: 4 passaggi
Tutorial AVR Assembler 8: Benvenuto nel Tutorial 8! In questo breve tutorial faremo una piccola deviazione dall'introduzione di nuovi aspetti della programmazione in linguaggio assembly per mostrare come spostare i nostri componenti di prototipazione in un separato "stampato" scheda di circuito. Il
Tutorial Assembler AVR 7: 12 passaggi
Tutorial AVR Assembler 7: Benvenuto nel Tutorial 7! Oggi mostreremo prima come eseguire lo scavenging di una tastiera, quindi mostreremo come utilizzare le porte di ingresso analogiche per comunicare con la tastiera. Lo faremo utilizzando interruzioni e un singolo filo come ingresso. Collegheremo la tastiera in modo che
Tutorial Assembler AVR 9: 7 passaggi
AVR Assembler Tutorial 9: Benvenuti al Tutorial 9. Oggi mostreremo come controllare sia un display a 7 segmenti che un display a 4 cifre utilizzando il nostro codice in linguaggio assembly ATmega328P e AVR. Nel fare ciò dovremo prendere deviazioni su come usare lo stack