Ragazzi mi inserisco anche io nella discussione perché ho un problema con gli input utilizzando "true C". Non so se devo aprire un'altra discussione, nel dubbio posto la domanda...
In pratica devo sostituire il classico DigitalRead(pin) con PINx.
Il codice di test é questo:
int encoder0PinALast=LOW;
int countPulses=0;
int n=LOW;
void setup()
{
Serial.begin(115200);
pinMode(2,INPUT);
pinMode(3,INPUT);
digitalWrite(2,HIGH);
digitalWrite(3,HIGH);
}
void loop()
{
encoderMotor();
}
void encoderMotor(){
// n = digitalRead(2);
n=PIND & _BV(PCINT2);//<== il mio dubbio é qui. n varrá di volta in volta 1 o 0 ??
if ((encoder0PinALast == LOW) && (n == HIGH ) ) {
if (PIND & _BV(PCINT19) == LOW) {
countPulses++;
} else {
countPulses--;
}
}
encoder0PinALast = n;
}
Il fatto é che l' if non procede nel modo corretto e non ottengo ne l'incremento ne il decremento della variabile. Potreste chiarirmi il concetto su PINx ? Grazie.
Certo che l'ho letto ma se per settare a HIGH devo usare una OR e per metterla a LOW devo usare una AND come faccio a combinare la cosa su pin diversi, mantenendo lo stato degli altri pin della porta e facendo l'operazione contemporaneamente su tutta la porta.
Non mi pare di vedere ciò che mi serve in quel post.
Scomponi le operazioni in 2 righe, una per l'attivazione con OR ed una per la disattivazione con AND.
Esempio:
erpomata:
Comunque, mi pare di aver capito che è impossibile settare per una stessa porta un pin HIGH e l'altro LOW.
Devono essere 2 operazioni differenti.
erpomata:
Ok alla fine si è giunti dove dicevo io:
erpomata:
Comunque, mi pare di aver capito che è impossibile settare per una stessa porta un pin HIGH e l'altro LOW.
Devono essere 2 operazioni differenti.
Sbaglio?
Se vogliamo essere pignoli.... se in fallo
Perché puoi comporre il byte da passare alla porta PRIMA.
Riprendendo il mio esempio precedente, possiamo fare così:
erpomata:
come faccio a combinare la cosa su pin diversi, mantenendo lo stato degli altri pin della porta e facendo l'operazione contemporaneamente su tutta la porta.
Ma perché non leggi le risposte, che oltretutto sono la soluzione al tuo problema ?
secondo me non è che non legge, non ha spiegato cosa vuole di preciso spiegando in modo pratico passo-passo cosa vuole fare, è vero che le istruzioni qui sopra funzionano, ma in alcuni contesti è difficile utilizzarli, non posso sostituire lo 0 e 1 a piacimento, sono costretto a spostare a destra e sinistra i byte, eseguire delle negazioni sui bit, OR e AND, ma non vado diretto ai bit che mi servono e devo fare dei salti sul programma per attivare con |= o &= ~ per disattivare. Se non ho capito male, lui vuole ricostruire il byte e rispedirlo al PORTn Con questo metodo lo può fare ma diventa parecchio laborioso.
Vabbè, sono esempi. Il codice va scritto in base a quel che deve fare.
Vuole leggere da un pin? Ok. Si può fare.
Vuole impostare diversi pin di una stessa porta in modo diverso? Ok. Si può fare.
Poi sta a lui risolvere i problemi in base alle necessità.
@leo
Ma in quel modo sovrascrivo tutto il valore della porta.
@astrobeed
Ho letto il post ma sempre due operazioni sono.
Ricapitolo.
C'è un modo per impostare contemporaneamente 2 o 3 bit di una porta (PORTB/C/D) lasciando invariati tutti gli altri nello stato in cui sono.
Ciao facendo una cosa del genere.
Stato della porta prima 01010101 vorrei che lo stato della porta sia 01010010 cambiando gli ultimi 3 bit lasciando invariati i primi 5 tutti insieme.
erpomata:
C'è un modo per impostare contemporaneamente 2 o 3 bit di una porta (PORTB/C/D) lasciando invariati tutti gli altri nello stato in cui sono.
No, almeno non con una singola operazione perché prima devi leggere tutti i bit della porta e poi devi applicare una opportuna mascheratura per lasciare invariati quelli che non devi scrivere.
SBI e CBI usano solo due cicli macchina, anche se ne usi otto in fila in totale fanno 16 cicli macchina che è sempre meno di quelli che dovresti usare con qualunque altro sistema, rammento che CBI e SBI sono istruzioni assemby specifiche per modificare un singolo bit di un registro, meglio di queste non esiste nulla.
erpomata:
C'è un modo per impostare contemporaneamente 2 o 3 bit di una porta (PORTB/C/D) lasciando invariati tutti gli altri nello stato in cui sono.
No, almeno non con una singola operazione perché prima devi leggere tutti i bit della porta e poi devi applicare una opportuna mascheratura per lasciare invariati quelli che non devi scrivere.
SBI e CBI usano solo due cicli macchina, anche se ne usi otto in fila in totale fanno 16 cicli macchina che è sempre meno di quelli che dovresti usare con qualunque altro sistema, rammento che CBI e SBI sono istruzioni assemby specifiche per modificare un singolo bit di un registro, meglio di queste non esiste nulla.
Perchè, in questo modo non stai settando vari bit con una operazione?
Lo scopo dell'OR è proprio quello di non dover leggere perchè lascia gli altri bit inalterati
PaoloP:
Comunque settando la porta puoi settare più pin contemporaneamente.
PORTD |= B10101000; // sets digital pins 7,5,3 HIGH
Stato della porta prima 01010101 vorrei che lo stato della porta sia 01010010 cambiando gli ultimi 3 bit lasciando invariati i primi 5 tutti insieme.
o conosci il byte da mandare al registro in un unica soluzione
01010101 = 85 in dec
01010010 = 82 in dec
PORTD = 82; ecco il tuo comando in un unico colpo!! In realtà riscrive tutto, ma i restanti 5 bit sono gli stessi di prima
o ricostruisci il byte
bitWrite(PORTD, 0, 0); //bit 0
bitWrite(PORTD, 1, 1); //bit 1
bitWrite(PORTD, 2, 0); //bit 2
gli altri bit 3/4/5/6/7 restano invariati
PaoloP:
Lo scopo dell'OR è proprio quello di non dover leggere perchè lascia gli altri bit inalterati
Ma lui voleva anche spengere dei bit, quindi AND. E non puoi fare OR e AND insieme.
Però col sistema della variabile temporanea che gli ho illustrato, può fare tutto con una sola operazione sul registro della porta, ovviamente "costruendo" prima le modifiche sulla variabile tampone.
leo72:
Ma lui voleva anche spengere dei bit, quindi AND. E non puoi fare OR e AND insieme.
Esatto, infatti alla fine sei sempre costretto a leggere il port, applicare le mascheratura, AND e OR, per ottenere il nuovo valore da scrivere nel port, ecco perché si fa sempre prima a settare/resettare i singoli bit tramite CBI e SBI, anche dovendo agire su tutti i bit alla fine ci si mette meno tempo (cicli macchina) di altri sistemi.
leo72:
Ma lui voleva anche spengere dei bit, quindi AND. E non puoi fare OR e AND insieme.
Esatto, infatti alla fine sei sempre costretto a leggere il port, applicare le mascheratura, AND e OR, per ottenere il nuovo valore da scrivere nel port, ecco perché si fa sempre prima a settare/resettare i singoli bit tramite CBI e SBI, anche dovendo agire su tutti i bit alla fine ci si mette meno tempo (cicli macchina) di altri sistemi.
Quindi questa operazione: PORTA &= (PORTA & 248) | value;
PORTA = (PORTA & 248) | value;
Impiega più cicli macchina sempre in ogni occasione rispetto alla manipolazione con _BV(bit)?
Comunque in tutti i casi con _BV(bit) operi su un singolo bit per istruzione, quindi manipoli la porta in tempi diversi.
oppure componendo più _BV(bit) | _BV() | ecc agisci su più bit in una unica soluzione, agendo nello stesso istante.
Però anche se ho letto tutti i post, non ho capito se si tratta di una curiosità, oppure di un problema reale che non si sa come affrontare.
MauroTec:
Impiega più cicli macchina sempre in ogni occasione rispetto alla manipolazione con _BV(bit)?
Ovviamente non è possibile dare una risposta assoluta, tocca valutare caso per caso, però se usi CBI e SBI hai la certezza matematica che per modificare un singolo bit di un registro, vale anche per quelli delle periferiche e non solo dei port, viene usata una singola istruzione assembly, ovvero una singola word della flash, e due cicli macchina sempre e comunque.