Guardavo l'interessantissimo sketck di leo del "micrologio"
ed ho copiato ed imparato (spero) qualcosa.
Mi ha incuriosito particolarmente questo:
PORTC=0b00000000; //LOW on A0..A7 - so no output current to display
DDRC=0b00011111; //set pins A0..A4 as outputs
PORTD=0b11111111; //LOW on D0..D7 - pins are not shortcircuited because LEDs are like diodes
DDRD=0b11111111; //set pins D0..D7 as output
ho cercato sul datasheet ATMEL ma non ho capito bene come si fa ad attivare in blocco una serie di PIN, dopo averli impostati OUTPUT...
eppoi non capisco la corrisopndenza tra i pin così come indicati da LEO e quelli su Arduino...
per esempio su arduino A0, A1... A5 li trovo, ma A7 come dice LEO dovè?
insomma non trovo la corrispondenta tra PORTC e PORTD ed i Pin effettivamente presenti sull'arduino...
Eppoi
DDR pare che si deba usare per impostarli come OUTPUT o INPUT, poi con PORT gli dico se stare alto o basso???
qualcuno ha un po di tempo da perdere per scrivere qui due righe su quest'argomento???
i pin mancanti li trovi nelle versioni SMD, datasheet nelle prime pagine
i registri sono 3 per ogni gruppo di pin: uno per impostare input output, uno per leggere i pin, ed un'altro per scrivere il pin (nel caso di pin di input, per attivare la pull-up)
ho provato e va bene.. riesco ad impostare in un'unica istrizone uin blocco di PIN settati come output... e fin qui bene!.
ma per leggere un blocco di pin, settati come input, digitali o analogici???
per esempio
devo leggere i 4 bit ricavati come output da un decoder DTMF, cioè il decoder, dopo aver decodificato il tono audio, setta i suoi 4 bit per costruire il codice ricevuto (tra 0 e 15, cio 16 valori).
i 4 bit li rilevo con 4 pin di arduino, che tramite questa funzione:
if (digitalRead(dtmfSTD))
{
if (digitalRead(dtmf1)) { dtmf_codice = 1; } else { dtmf_codice = 0; }
if (digitalRead(dtmf2)) { dtmf_codice = dtmf_codice + 2; }
if (digitalRead(dtmf3)) { dtmf_codice = dtmf_codice + 4; }
if (digitalRead(dtmf4)) { dtmf_codice = dtmf_codice + 8; }
}
else { dtmf_codice =0;}
che funziona regolarmente.
ora io vorrei fare una cosa di questo tipo:
quando il decoder DTMF impone come alto il livello dell'enable rilevabile da questo PIN "digitalRead(dtmfSTD)"
avrei bisogno di "fotografare" in un unico istante i livelli dei 4 pin dtm1,2,3,4 e memorizzarli in un'unica variabile per analizzarne i contenuti e ricostruire il codice ivi contenuto (4 bit -> 0 - 15 in dec.)
è possibile farlo senza leggere seguenzialmente, come faccio sopra con digitalread, i 4 pin, ma estraendo, diciamo così "in blocco" i 4 bit presenti nel medesimo istante, in modo da poterli passare ad una dunzione che converte i 4 bit nel corrispondente valore decimale????
Andiamo per ordine.
Un microcontrollore contiene delle linee di I/O con le quali dialoga col mondo esterno. Tutta la circuiteria per la gestione di queste linee è accessibile alla CPU tramite dei registri, ossia delle locazioni di memoria. Queste locazioni hanno un indirizzo specifico, che il compilatore "offre" all'utente in forma semplificata con alcune costanti, le famose PORTA, PORTB, PORTC ecc...
Ogni registro è composto da 8 bit, ogni bit gestisce una porta, ossia un piedino fisico del microcontrollore. Per la corrispondenza fai riferimento all'immagine qui sotto. PB0, per esempio, significa linea 0 della porta B, che è il pin D8 dell'Arduino.
Ovviamente questo modo di gestione delle porte ha senso se, come nel tuo caso del decoder, colleghi le linee in modo logico, ossia se hai ad esempio 4 bit li colleghi alle linee 0..3 di una porta. Se usi la porta C (che è quella che gestisce i pin Axx), li collegherai a PC0..PC3.
Ah, questo modo di gestione delle porte non può essere fatto per letture analogiche. Queste richiedono l'attivazione dell'ADC interno ed un modo di gestione delle linee differente. C'è un thread dove con lesto abbiamo trattato l'argomento.
grazie.. leo... ho scaricato e stampato tutta la documentazine indicata da lesto, per poterla leggere e rileggere .. ho capito come usarla per impostare in out le relative linee ed anche come impostare i valori (alto-basso).
il problema è come leggere i valori, dopo ave impostato la linea come input. Lettura digitale, non analogica.
In particolare a chiedevo se è possibile trasferire in blocco una serie di bit,rilevati sulla stessa porta, dove ho opportunamente collegato le uscite del decoder, ...
cioè in modo da avere qualcosa tipo:
digit_letti = b0110 e convertirlo velocemente nell'equivalente valore decimale
senza dover fare questo
if (digitalRead(dtmf1)) { dtmf_codice = 1; } else { dtmf_codice = 0; }
if (digitalRead(dtmf2)) { dtmf_codice = dtmf_codice + 2; }
if (digitalRead(dtmf3)) { dtmf_codice = dtmf_codice + 4; }
if (digitalRead(dtmf4)) { dtmf_codice = dtmf_codice + 8; }
grazie dell'interessamento e di nuovo complimenti per l'interessante lavoro del micrologio...
Prima metti in input una porta, ossia metti a 0 il relativo pin della corrispondente porta tramite DDRx.
Poi legge il suo stato da PINx. Le manipolazioni vanno fatte a livello di bit.
Esempio: leggi lo stato del pin PB0, che abbiamo detto essere il pin di Arduino D8.
In particolare a chiedevo se è possibile trasferire in blocco una serie di bit,rilevati sulla stessa porta, dove ho opportunamente collegato le uscite del decoder, ...
cioè in modo da avere qualcosa tipo:
digit_letti = b0110 e convertirlo velocemente nell'equivalente valore decimale
senza dover fare questo
if (digitalRead(dtmf1)) { dtmf_codice = 1; } else { dtmf_codice = 0; }
if (digitalRead(dtmf2)) { dtmf_codice = dtmf_codice + 2; }
if (digitalRead(dtmf3)) { dtmf_codice = dtmf_codice + 4; }
if (digitalRead(dtmf4)) { dtmf_codice = dtmf_codice + 8; }
Ciao, mi intrometto per chiarire una cosa che mi sembra non si sia colta.
La risposta in ciò che chiedi è già presente nella risposta di Leo:
leo72:
...
Ovviamente questo modo di gestione delle porte ha senso se, come nel tuo caso del decoder, colleghi le linee in modo logico, ossia se hai ad esempio 4 bit li colleghi alle linee 0..3 di una porta. Se usi la porta C (che è quella che gestisce i pin Axx), li collegherai a PC0..PC3.
Significa che se colleghi il decoder alle 4 linee della STESSA porta, non hai più bisogno di fare blocchi di "if" nè tantomeno convertire nulla in decimale, ti basta solo leggere il contenuto della porta, magari isolando ("mascherando") solo i bit che ti interessano.
Seguendo l'esempio di Leo, per leggere il contenuto del decoder collegato alle linee 0...3 della porta C puoi usare direttamente:
byte valore = PORTC & B00001111;
e la variabile valore contiene già il numero decimale che cerchi.
grezie leo.. ho fatto le prove ed ho visto come funziona.
Però io ho bisogno di leggere (in un solo passaggio) 4 bit .. ma la soluzioe mi pare me la stia spiegando dalubar ....
grazie dalubar...
mi pare sia esattamente ciò che cercavo.
quindi questa operazione :
byte valore = PORTC & B00001111;
maschera il contenuto della porta C, perchè 'copre' i 4 bit più significativi? .... prendendo solo i primi 4 ???
è esattamente ciò che cercavo.
credo che dovrò studiare l'operatore '&'
trovo qualche riferimento nel reference???
vi chiedo scusa, ma il mio approccio al C è conseguente alla scoperta (recente) di arduino quindi sono cose che sto studiando adesso, come posso e quando posso ....
trovi qualche riferimento in rete cercando "bitwise manipulation", che spiega l'uso degli operatori logici and(&), or(|), xor(^), not(~) e bit shift operatore << e >>, al fine di manipolare una valore di una variabile bit per bit.
La maschera di dabular funziona anche se usi i pin di una porta a partire da 1 anziche zero, ma ovviamente la maschera sarà così byte valore = PORTC & B00011110, e poi valore deve essere "shiftato" di uno a destra così valore >> 1.