Go Down

Topic: Dubbio su manipolazione PORTD (Read 427 times) previous topic - next topic

max95

Nov 05, 2018, 11:21 pm Last Edit: Nov 05, 2018, 11:22 pm by max95
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

Patrick_M

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
per inserire (lo sketch) il programma, dall'IDE clicca modifica, clicca copia per il forum poi vieni qui e incolla nel tuo post (ctrl+v) ;)

gpb01

#2
Nov 06, 2018, 08:51 am Last Edit: Nov 06, 2018, 08:52 am by gpb01
... 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
Search is Your friend ... or I am Your enemy !

max95

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?

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

Ma se volessi input con pullup?

Grazie mille per le risposte

Patrick_M

#4
Nov 06, 2018, 11:20 pm Last Edit: Nov 06, 2018, 11:22 pm by Patrick_M
devi studiarti un po di algebra booleana :)

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 ;)
questo è un piccolo passo del doc di Leo
Quote
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).
per inserire (lo sketch) il programma, dall'IDE clicca modifica, clicca copia per il forum poi vieni qui e incolla nel tuo post (ctrl+v) ;)

max95

#5
Nov 09, 2018, 09:47 pm Last Edit: Nov 09, 2018, 09:48 pm by max95
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

Code: [Select]

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


oppure questo:
Code: [Select]

....
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?

gpb01

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 :D

Guglielmo

Search is Your friend ... or I am Your enemy !

max95

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

SukkoPera

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).
"Code is read much more often than it is written, so plan accordingly. Design for readability."

Guida rapida a ESP8266: https://goo.gl/kzh62E

max95

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?

gpb01

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
Search is Your friend ... or I am Your enemy !

SukkoPera

#11
Nov 11, 2018, 09:55 am Last Edit: Nov 11, 2018, 09:57 am by SukkoPera
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.
"Code is read much more often than it is written, so plan accordingly. Design for readability."

Guida rapida a ESP8266: https://goo.gl/kzh62E

max95

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

gpb01

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
Search is Your friend ... or I am Your enemy !

SukkoPera

#14
Jan 21, 2019, 11:24 am Last Edit: Jan 21, 2019, 11:27 am by SukkoPera
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à).
"Code is read much more often than it is written, so plan accordingly. Design for readability."

Guida rapida a ESP8266: https://goo.gl/kzh62E

Go Up