Buongiorno ragazzi, sono bloccato di fronte ad un problema stupido... Vorrei sapere come fare a cambiare lo stato di un pin utilizzando PORTD. Devo inserirlo in una ISR e non voglio utilizzare ne digitalWrite ne digitalRead, vorrei un equivalente di questo tanto per spiegarmi meglio:
digitalWrite(2, !digitalRead(2))
Con PORTD = B00000100 ok lo porto alto, ma al successivo ingresso nella ISR deve diventare PORTD = B00000000. Vorrei farlo con una sola riga. Negando quel bit. Se è 0 lo metti a 1, se è 1 lo metti a 0.
Molto più sempliceme, gli AVR hanno la possibilità di "pin toggle" (se 1 lo porta a 0 e viceversa) ... occorre scrivere su PIN (che normalmente è solo per la lettura) invece che su PORT
PIND = _BV(PD2); // che corrisponde al suo bit xxxxxXxx
... attenzione è proprio =, e NON |= , mi raccomando.
Guglielmo
P.S.: La macro _BV() è definita come #define _BV(bit) (1 << (bit)) in <avr/io.h>
gpb01:
Molto più sempliceme, gli AVR hanno la possibilità di "pin toggle" (se 1 lo porta a 0 e viceversa) ... occorre scrivere su PIN (che normalmente è solo per la lettura) invece che su PORT
PIND = _BV(PD2); // che corrisponde al suo bit xxxxxXxx
Guglielmo
Grazie mille!!! Provo anche questa!!! In termini di velocità di commutazione cambia qualcosa rispetto alle due soluzioni???
Lollo82:
In termini di velocità di commutazione cambia qualcosa rispetto alle due soluzioni???
Mah ... probabilmente è più veloce la mia soluzione (... una singola scrittura) che fare un XOR (... legge il valore della porta, fa XOR, scrive nella porta) ...
gpb01:
Mah ... probabilmente è più veloce la mia soluzione (... una singola scrittura) che fare un XOR (... legge il valore della porta, fa XOR, scrive nella porta) ...
Guglielmo
Ok allora uso questa. Mi serve avere due segnali uno negato rispetto all'altro il più sincronizzato possibile.
gpb01:
Guarda, la XOR dell'esempio, scritta il più compatto possibile, viene così compilata:
// PORTD ^= (1<<2);
in r24, PORTD
ori r24, (1<<2)
out PORTD, r24
... mentre la versione cn la scrittura su PIN diventa:
// PIND = _BV(PD2);
ldi r24, (1<<2)
out PIND, r24
... quindi, alla fine, si risparmia una istruzione ad ogni "*toggle*".
Guglielmo
Grazie mille. Non mandarmi a cagare, un'ultima cosa. Con quella funzione posso negare un pin rispetto ad un altro???
Ho creato l'onda quadra che volevo sul pin 2, e vorrei la stessa ma negata sul pin 3. Utilizzando le normali istruzioni avevo scritto facendo probabilmente una porcata digitalWrite(3, !digitalRead(2)), ma funzionava (a parte un lievissimo ritardo da i due segnali).
Avevo pensato di farlo partire da HIGH nel setup ma non funziona, ho un picco alto al momento della commutazione e poi torna basso. Grazie ancora.
gpb01:
Guarda, la XOR dell'esempio, scritta il più compatto possibile, viene così compilata:
// PORTD ^= (1<<2);
in r24, PORTD
ori r24, (1<<2)
out PORTD, r24
... mentre la versione cn la scrittura su PIN diventa:
// PIND = _BV(PD2);
ldi r24, (1<<2)
out PIND, r24
... quindi, alla fine, si risparmia una istruzione ad ogni "*toggle*".
Guglielmo
Scusa lo OT, Guglielmo, ma si può programmare anche con queste istruzioni?
Sono le stesse che uso quando programmo in ladder i plc (LD LDI AND ANI OR ORI OUT RST SET ecc...)
Mi serve avere due segnali uno negato rispetto all'altro il più sincronizzato possibile.
Se vuoi che i due segnali siano perfettamente sincronizzati devi comandarli con una sola istruzione.
Inizializza i due pin uno alto e uno basso nel setup.
Nella tua routine di interrupt carica su PIND un byte con i due bit corrispondenti ai pin ad uno: in questo modo togglano contemporaneamente.
Qui sotto trovi un esempio, senza l'interrupt, con il segnale generato nel loop.
Sulimarco:
Se vuoi che i due segnali siano perfettamente sincronizzati devi comandarli con una sola istruzione.
Inizializza i due pin uno alto e uno basso nel setup .....
Grazie Marco, con questo ho ottenuto proprio quello che volevo. Non mi veniva perchè da pirla avevo sbagliato il nome della isr di overflow e quindi non mi riaggiornava TCNT a 70 una volta cambiato lo stato.
Anche se vi ci pulirete il didietro un karma a tutti voi non ve lo toglie nessuno. Grazie ancora per avermi aiutato a seguire una strada a me ancora poco chiara.
>Lollo82: Quando si quota un post, NON è necessario riportarlo (inutilmente) tutto; bastano poche righe per far capire di cosa si parla ed a cosa ci si riferisce. Gli utenti da device "mobile" ringrazieranno per la cortesia