chiarimento su PORTD = B10101000;

volevo chiedere se c'è la possibilita di evitare di scrivere una porta con il comando
PORTD = B10101000;
esempio qui il pin 3 viene portato a HIGH ma se uno vuole evitare di scrivere un pin
come deve fare
questo comando IN teoria dovrebbe sceivere i pin da 0 a 7
ma prende bit da 1 a 12 senza generare errore
che cosa fa in realta se si scrive

PORTD = B1;

oppure

PORTD = B101010001010;

GINGARDU:
volevo chiedere se c'è la possibilita di evitare di scrivere una porta con il comando
PORTD = B10101000;
esempio qui il pin 3 viene portato a HIGH

Più precisamente, sono impostati su High i pin 7, 5 e 3, non solo il pin 3.

questo comando IN teoria dovrebbe sceivere i pin da 0 a 7
ma prende bit da 1 a 12 senza generare errore
che cosa fa in realta se si scrive

PORTD = B1;

Equivale a 0b00000001 per cui metti a 0 tutti i bit/pin dall'8° al 2° bit e ad 1 il 1° bit.

PORTD = B101010001010;

Qui il compilatore tronca il numero ai primi 8 bit dato che PORTD è un byte per cui hai PORTD caricato col valore 10001010. Il compilatore dovrebbe troncare i bit in eccesso rispetto all'8°, se questa è l'implementazione di avr-gcc.

Per modificare un solo bit si usano di solito le operazioni logiche AND e OR.
Ricordando che con AND si ha come risultato 1 solo se entrambi i valori sono 1, quindi 1 AND 1 = 1 ma 1 AND 0 = 0 e 0 AND 1 = 0 e con OR si ha 1 se anche uno solo dei 2 bit confrontati è ad 1, quindi 1 OR 0 = 1, 0 OR 1 = 1, 1 OR 1 = 1 e 0 OR 0 = 0, si usano le seguenti operazioni:
PORTD &= ~(1<<3)
per impostare a 0 il bit n° 3. Come funziona? L'operazione 1<<3 è un'operazione di spostamento dei bit. Nello specifico, sposti "1", che in binario è 00000001, di 3 posizioni a sinistra, ottenendo 00001000. L'operatore ~ è una forma contratta di NOT, quindi serve ad invertire il valore. Per cui 00001000 diventa 11110111. A questo punto esegui l'AND tra il valore di PORTD e 11110111. Come detto, un bit AND 1 dà come risultato 1 se era impostato ad 1 (1 AND 1 = 1) e dà 0 se era impostato a 0 (0 AND 1 = 0) per cui non modifichi il valore dei bit che non ti interessano e metti a 0 solo il bit che ti interessa.

PORTD |= (1<<3)
per impostare ad 1 il bit n° 3. Quest'operazione è più semplice da spiegare. Sposti sempre a sinistra di 3 posizioni il valore 1 ottenendo 00001000 e poi fai un OR. Ora, siccome un bit OR 0 dà il bit originale, anche qui non modifichi il valore dei bit che non ti interessano, ma imposti ad 1 il bit che ti interessa perché un qualunque valore di 0 o 1 OR 1 dà come risultato sempre 1.

Ricapitolando, in questo modo:

  1. modifichi solo il bit che ti interessa
  2. non ti importa sapere il valore corrente del bit.

x iscrizione (karma incluso) :slight_smile:

leo72:

GINGARDU:
volevo chiedere se c'è la possibilita di evitare di scrivere una porta con il comando
PORTD = B10101000;

Ricapitolando, in questo modo:

  1. modifichi solo il bit che ti interessa
  2. non ti importa sapere il valore corrente del bit.

questa cosa è interessante ma alla fine dei "conti"volevo sapere che cosa succede a i pin che non voglio che siano toccati,

esempio reale, pin 2 e 3 settati come input per interrupt, pin 0,1,4,5,6,7, settati come output nel setup

se faccioPORTD = B11111111; coa accade a i 2 e3 ?
continuano a funzionare come imput o vengono portati a HIGH

OPPURE pin A4 A5 SETTATI come pin digitali A0 A1 A2 LI ADOPERO COME ANALOGICI

se faccio PORTC = B11111111; che gli succede a A0 A1 A2 continuano a funzionare come analogici oppure vengono portati a HIGH

GINGARDU:
questa cosa è interessante ma alla fine dei "conti"volevo sapere che cosa succede a i pin che non voglio che siano toccati,

Tu non leggi ciò che ti scrivo :stuck_out_tongue:

leo72:

GINGARDU:
volevo chiedere se c'è la possibilita di evitare di scrivere una porta con il comando
PORTD = B10101000;
esempio qui il pin 3 viene portato a HIGH

Più precisamente, sono impostati su High i pin 7, 5 e 3, non solo il pin 3.

[/quote]

esempio reale, pin 2 e 3 settati come input per interrupt, pin 0,1,4,5,6,7, settati come output nel setup

se faccioPORTD = B11111111; coa accade a i 2 e3 ?
continuano a funzionare come imput o vengono portati a HIGH

Con questo comando metti tutti i bit ad 1 (come detto sopra).

OPPURE pin A4 A5 SETTATI come pin digitali A0 A1 A2 LI ADOPERO COME ANALOGICI

se faccio PORTC = B11111111; che gli succede a A0 A1 A2 continuano a funzionare come analogici oppure vengono portati a HIGH

La seconda che hai detto.

La manipolazione per come la vuoi fare te, ossia scrivere l'intero ottetto di bit in un registro, comporta che cambi di stato anche ai bit che non vuoi toccare.

Esempio. Vuoi impostare ad 1 solo i bit 3 e 5 lasciando inalterati gli altri bit.
Hai 2 strade:

  1. la via facile, usare le funzioni del core. Fai
bitSet(PORTD, 3);
bitSet(PORTD, 5);
  1. la via difficile (ma non troppo). Fai:
PORTD |= ((1<<3) | (1<<5));

La differenza sta nel fatto che usando le funzioni del core, nel caso bitSet, devi scrivere 1 istruzione per bit, mentre manipolando direttamente i bit puoi compattare tutto in 1 sola istruzione.
L'ultimo esempio si trasforma in PORTD = PORTD OR (8 OR 32), cambi ad 1 quindi il bit 3 (2^3=8) ed il bit 5 (2^5=32).
Ricordati sempre che:
bit 0 -> 1° bit
bit 1 -> 2° bit
....
bit 7 -> 8° bit
Cioè che la loro posizione (1°..8°) è differente dal loro indice (0..7).

vediamo se ho afferrato :~

"fare"
PORTC = B11111111;
PORTD = B11111111;
PORTB = B11111111;

come risultato si ha che si settano tutti i pin come autput e si mettono tutti HIGH
anche mettendo prima es: nel setup
DDRD = B11111110;
DDRD = DDRD | B11111100;
le porte verranno "sovrascritte" tutte uguamente come autput e si mettono tutti HIGH

confermi?

poi
facedo cosi invece
PORTD |= ((1<<3) | (1<<5));

si portano ad 1 i bit alla posizione 3 e alla 5 do per scontanto che mettendo 0 al posto di 1 portano i bit a zero
confermi ?,

per ultimo

bitSet(PORTD, 3);
bitSet(PORTD, 5);

se queste 2 righe settano settano il 3 e il 5 a uno per settarli a a zero come si fa?

GINGARDU:
vediamo se ho afferrato :~

"fare"
PORTC = B11111111;
PORTD = B11111111;
PORTB = B11111111;

come risultato si ha che si settano tutti i pin come autput e si mettono tutti HIGH
anche mettendo prima es: nel setup
DDRD = B11111110;
DDRD = DDRD | B11111100;
le porte verranno "sovrascritte" tutte uguamente come autput e si mettono tutti HIGH

confermi?

Confermo.

poi
facedo cosi invece
PORTD |= ((1<<3) | (1<<5));

si portano ad 1 i bit alla posizione 3 e alla 5 do per scontanto che mettendo 0 al posto di 1 portano i bit a zero
confermi ?,

No. Devi usare l'AND per mettere a 0 i bit. Leggi post sopra.
Se fai 1 OR 0 ottieni sempre 1.

per ultimo

bitSet(PORTD, 3);
bitSet(PORTD, 5);

se queste 2 righe settano settano il 3 e il 5 a uno per settarli a a zero come si fa?

bitClear.
Leggi qui:
http://arduino.cc/en/Reference/BitClear
http://arduino.cc/en/Reference/BitRead
http://arduino.cc/en/Reference/BitSet

x iscrizione

leo72:

GINGARDU:
vediamo se ho afferrato :~

"fare"
PORTC = B11111111;
PORTD = B11111111;
PORTB = B11111111;

come risultato si ha che si settano tutti i pin come autput e si mettono tutti HIGH
anche mettendo prima es: nel setup
DDRD = B11111110;
DDRD = DDRD | B11111100;
le porte verranno "sovrascritte" tutte uguamente come autput e si mettono tutti HIGH

confermi?

Confermo.

poi
facedo cosi invece
PORTD |= ((1<<3) | (1<<5));

si portano ad 1 i bit alla posizione 3 e alla 5 do per scontanto che mettendo 0 al posto di 1 portano i bit a zero
confermi ?,

No. Devi usare l'AND per mettere a 0 i bit. Leggi post sopra.
Se fai 1 OR 0 ottieni sempre 1.

per ultimo

bitSet(PORTD, 3);
bitSet(PORTD, 5);

se queste 2 righe settano settano il 3 e il 5 a uno per settarli a a zero come si fa?

bitClear.
Leggi qui:
http://arduino.cc/en/Reference/BitClear
http://arduino.cc/en/Reference/BitRead
http://arduino.cc/en/Reference/BitSet

allora mettiamo le cose in pratica,prendiamo ad esmpio un pezzo di codice che modifichero

if (CFR2 >= 80000 && CFR2 < 90000)

{
digitalWrite (11, HIGH);
digitalWrite (5, HIGH);
digitalWrite (6, HIGH);
digitalWrite (7, HIGH);
digitalWrite (8, HIGH);
digitalWrite (9, HIGH);
digitalWrite (10,HIGH);
digitalWrite (16, LOW);
}

posso trasformarlo in

if (CFR2 >= 80000 && CFR2 < 90000)

{

PORTD |= ((1<<6) | (1<<7) |(1<<5)); //metto HIGH pin 5,6,7,
PORTB |= ((1<<1) | (1<<2) | (1<<3)| (1<<4) ); //metto HIGH pin 8,9,10,11
PORTC &= ( (1<<3) ); //metto LOW pin 16
}

e in questo caso risparmio qualcosa in tempi di esecuzione e piu o meno quanto rispetto a gli 8 digitalWrite

Tutto quello che ti passa per la mente di chiedere prendi il forum e scrivi, quando potresti con un po' di impegno e ricerca risponderti da solo.

si 10us forse li hai risparmiati :roll_eyes:
il fatto che questo sistema ti obbliga a scrivere 2 righe differenti per un high o low non so quanto sia conveniente.
Un digitalWrite (a, b); ti permette di sostituire le variabili per il cambio H/L in modo fast dando direttamente il num del pin (anche se in modo dispersivo), dipende sempre da cosa devi fare.
Se vuoi veramente risparmare tempo sull'esecuzione non usare l' ide e programmatelo in assembler per la generazione del codice macchina, quando a qualcuno esperto in programmazione di microcontrllori dici che usi arduino non so perchè gli si rizzano i capelli con arricciamenti di naso inclusi dato il suo sistema di programmazione :smiley: $)

pablos:
il fatto che questo sistema ti obbliga a scrivere 2 righe differenti per un high o low non so quanto sia conveniente.

Quoto.
L'alternativa è studiare un modo per usare gli 8 pin contigui di una stessa porta, in modo da poter assegnare un byte unico alla porta e modificare così tutti i pin di quella porta.
Ad esempio, PORTD è mappata sui pin D0..D7.

eh eh c'ero quasi arrivato annch'io,
solo che PORTD contiene i pin interrupt e mi servono
se ci fosse un modo per spostarli su 2 pin analogici
userei i pin da 0 a 13 per far tutto

Usa i PCINT invece degli INT.
http://arduino.cc/playground/Main/PinChangeInt
Li puoi agganciare a qualunque pin dell'Arduino.

ma si potrebbe spostare i 2 pin interrupt su A4 A5 senza caricare la libreria
o scrivento pochissimo codice?

Certamente. Ti prendi il datasheet e piloti i registri per attivare i PCINT sui pin che ti interessano. Poi crei una ISR per intercettare gli interrupt.