Datman:
SukkoPera: se il 5° bit di PINB è 0, imposta a 1 il 4° bit di PORTB; altrimenti imposta a 0 il 4° bit di PORTB. E' sbagliato?...
Ecco, ti rendi conto che guardando il codice non è immediatamente chiaro su quali pin lavori? Non sarebbe meglio usare un metodo che renda il tutto più esplicito e che riduce al minimo il rischio di errori, senza dovere fare calcoli, quando possiamo risparmiarceli?
Datman:
ISR(PCINT0_vect)
{
if(!digitalRead(4)) digitalWrite(3, HIGH);
else digitalWrite(3, LOW);
}
Questo è giusto e chiaramente più leggibile, senza contare che permette al tuo codice di girare su un sacco di schiede, senza vincolarti ad un microcontrollore AVR. Ma si può migliorare ancora:
if (!digitalRead(4)) {
digitalWrite(3, HIGH);
} else {
digitalWrite(3, LOW);
}
Ovvero usando l'indentazione, che rende subito chiaro - anche visivamente - quali istruzioni sono subordinate a quali altre, e le parentesi graffe, facoltative in questo caso, ma che evitano errori qualora si decida di aggiungere ulteriori istruzioni in un secondo tempo senza troppa attenzione.
C'è anche una possibile miglioria "semantica" sul fatto che digitalRead() non ritorna un valore logico, per cui andrebbe testata esplicitamente con HIGH o LOW, ma questo è troppo anche per me :D, lasciamo stare.
Questa è quindi la forma che dovresti usare SEMPRE. L'unico caso in cui vale la pena di complicare le cose è quando servono performance. In questo caso è bene avvicinarsi all'hardware per velocizzare il tutto, arrivando eventualmente a scrivere direttamente codice in assembly, nella consapevolezza di perdere la portabilità e complicare leggibilità e manutenibilità.
Datman:
Nell'altra forma verrebbe:
ISR(PCINT0_vect)
{
if(PINB&&1<<4==0) PORTB|=1<<3;
else PORTB&=0xFF-1<<3;
}
Esatto?
No, perché le precedenze tra gli operatori non danno il risultato giusto in questo modo, devi fare:
if (!(PINB & (1 << PB4)))
PORTB |= (1 << PB3);
else
PORTB &= ~(1 << PB3);
Nota l'uso delle macro PBx e non dei singoli numeri e l'uso necessario delle parentesi, per forzare che lo shift avvenga prima dell'AND bitwise. Nota inoltre la negazione bitwise nell'ultima riga.
... E soprattutto nota l'uso della singola & nell'if, che è l'errore presente nel tuo codice originale, che avresti evitato usando digitalRead(). Capisci che ti complichi solo le cose, scrivendo codice come fai tu?
Infine, nota che nonostante siamo andati a basso livello, è subito chiaro su quale bit stiamo lavorando, senza possibilità di errore e senza alcuna penalizzazione in performance, dato che tutte queste costanti vengono calcolate a compile time.
(Modalità "Maestrina" OFF :D)