Dubbio su manipolazione PORTD

Buonasera a tutti,

Stavo leggendo questo articolo

https://www.tomshw.it/altro/corso-base-di-arduino-manipolazione-delle-porte-di-i-o/

e mi è sorto un dubbio: lo sketch dove manipolo i registi, oltre ad essere più corto è anche più veloce?

Quindi se io devo portare ad high o a low due pin dello stesso gruppo risparmio tempo usando PORTD anziché digitalwrite?

Ringrazio in anticipo

certamente!!! e di molto anche
e anche se ne devi cambiare uno solo
per contro se cambi scheda.... ti può capitare di dover riscrivere tutto in quanto i pin possono cambiare nome/posizione

... più a basso livello si va, più si perde di "trasportabilità" ... spesso i nomi dei registri tra due MCU, anche della stessa famiglia, sono diversi o i bit posizionati in modo differente.

Guglielmo

Grazie infinite per i suggerimenti.
Oggi ho fatto un po’ di test e mi sono sorti due dubbi:

  1. se io dichiaro ad esempio

PORTD=B11111111
delay(1000)
PORTD=B11011111

Viene riscritto lo stato di tutti e 8 i pin o solo di quello che cambia? Nel caso venissero riscritti tutti e 8 gli stati come faccio a cambiarne solo uno specifico?

  1. in setup dichiarò DDRD=...... dove 0 sono input e 1 sono output

Ma se volessi input con pullup?

Grazie mille per le risposte

devi studiarti un po di algebra booleana :slight_smile:

consiglio di leggere e studiare questo

in pratica usando i vari and e or oppure xor riesci a modificare tutti nessuno o un solo pin per volta a seconda delle necessità

anche questo di Leo è istruttivo :wink:
questo è un piccolo passo del doc di Leo

DDRD
questo registro è di lettura/scrittura e contiene la direzione dei pin ad esso collegati. Un bit a 0 rappresenta un pin impostato come INPUT; un bit ad 1 rappresenta un pin impostato come OUTPUT;
PORTD
questo registro è di lettura/scrittura e contiene lo stato dei pin. Questo stato cambia a seconda della direzione del pin:
– se il pin è impostato come INPUT, un bit ad 1 attiva la resistenza di PULL-UP, mentre un bit a 0 la disattiva;
– se il pin è impostato come OUTPUT, un bit ad 1 indica uno stato HIGH sul relativo pin, mentre un bit a 0 indica la presenza dello stato LOW sullo stesso pin.
PIND
questo registro è di sola lettura e contiene, nel caso di un pin impostato come INPUT, la lettura del segnale collegato al pin: 1 per un segnale alto (HIGH); 0 per un segnale basso (LOW).

Infinite grazie per le dritte.. dopo circa due serata di studio ed esperimenti (mi sto prendendo bene) non mi è chiaro un passaggio.

Scrivere questo codice

....
PORTD = 0b10101010;
delay(1000);
PORTD = 0b10101011;
delay(1000);
...

oppure questo:

....
PORTD = 0b10101010;
delay(1000);
PORTD = PORTD | 0b00000001;
delay(1000);
...

è la stessa identica cosa? o il secondo, utilizzando l'operatore OR è più veloce perché tocco solo un bit?

E' il concetto che è diverso ...
... in un caso vai a modificare tutti gli 8 bit, nell'altro tocchi solo ed esclusivamente UN bit ... cosa che serve il 90% delle volte :smiley:

Guglielmo

Si si ho capito cosa intendi... quindi anche a livello di tempo e più veloce il secondo codice perché cambio solo il bit interessato anziché riscriverli tutti e 8

La scrittura di un registro a 8 bit richiede sempre lo stesso tempo, sia che modifichi un bit o tutti e 8.

Nel secondo caso però devi prima fare una lettura e un and bitwise, che sono 2 cose che portano via tempo, per cui la prima proposta è più veloce, anche se stiamo parlando di 125 ns (nanosecondi).

Quale delle due abbia più senso fare dipende dal contesto. Se tutti i bit cambiano sempre e solo nello stesso posto puoi anche direttamente scrivere il nuovo valore precalcolato. Se invece i bit possono variare in maniera indipendente, in punti diversi dello sketch, allora sei obbligato a usare la seconda forma, altrimenti rischi di cambiare bit che non dovrebbero cambiare.

Infine nota che raramente si scrivono registri con valori diretti come stai facendo tu. Solitamente si usa una combinazione di macro tipo (1 << PD3) | (1 << PD0).

SukkoPera:
Solitamente si usa una combinazione di macro tipo (1 << PD3) | (1 << PD0).

Questa dicitura (attraverso scorrimento) dice di mettere a 1 il pin PD3 e PD0 giusto?

NO, quella dicitura significa "fai shift a sinistra del valore 1 di tanti bit quanti indicati in PDx" ovvero posiziona un bit ad 1 nella posizione dove nella porta si trova il pin PDx.

PDx, PORTx, ecc. ecc. sono solo simboli associati a valori numerici che corrispondono alla posizione del bit, all'indirizzo di memoria di un port, ecc. ecc.

Guglielmo

Esatto, e sul datasheet trovi il nome e il significato di ogni singolo bit di ogni singolo registro.

Ad esempio vedrai che il registro PORTD controlla alcuni pin di uscita e che i singoli bit sono chiamati come detto sopra.

Buona sera,

dopo svariate prove ne sono venuto a capo e qualche semplice programma l'ho scritto con questo metodo.

Mi restano "solo" due dubbi:

  1. in DDRD e PORTD ho la presenza di tx e rx. Se volessi sfruttare la seriale mi basta posizionare in DDRD tx a 1 (out) e rx a 0 (input)?

  2. le porte PORTC (analogica + reset) come vengono gestite a livello di dichiarazione registri per la gestione lettura?

Grazie mille in anticipo

DDRx, PORTx e PINx sono valide SOLO per gli I/O digitali, per tutte le altre cose (Seriali, Analogiche, ecc.) ci sono tutt'altri registri da impostare, interrupt da gestire, ecc. ecc. e la cosa è parecchio più complessa.

Devi fare riferimento al datasheet della MCU.

Guglielmo

In particolare, dopo che hai inizializzato la seriale è bene non toccare più i relativi bit di DDRD e PORTD.

Il reset non c'entra niente con PORTC. PORTC, DDRC e PINC li puoi usare per accedere alle funzioni DIGITALI dei pin A0-A5, se vuoi usare le funzioni analogiche di questi pin i registri da usare sono altri, come dice gpb.

Continuo però a raccomandare che le funzioni di Wiring/Arduino sono lì apposta per semplificare la vita. A meno di necessità particolari e/o didattiche, lavorare sui registri è tedioso e controproducente (si perde la portabilità).