Go Down

Topic: Velocizzare l'IO delle porte digitali (Read 4344 times) previous topic - next topic

leo72


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?

Sì.
0=LOW
1=HIGH
Quindi se riprendiamo la porta dell'esempio precedente, PORTD, e facciamo questa assegnazione:
Code: [Select]
PORTD = 0b10101010;
Hai impostato le porte collegate ai bit dispari su LOW (1-3-5-7) e quelle collegate ai bit pari su HIGH (0-2-4-6).

erpomata

Si ma se io volessi impostare, ad esempio i bit 0 e 1 rispettivamente a  HIGH ed a LOW ma preservando gli altri bit della porta non lo posso fare.

In quella maniera sovrascrivo tutte le impostazioni precedentemente date agli altri pin.
http://www.paologiammarco.it
http://www.valentinamagni.it

leo72

Allora vuol dire che non hai letto il mio post quotato da PaoloP  :P
http://arduino.cc/forum/index.php/topic,124080.msg933207.html#msg933207

astrobeed


Si ma se io volessi impostare, ad esempio i bit 0 e 1 rispettivamente a  HIGH ed a LOW ma preservando gli altri bit della porta non lo posso fare.


Per settare i singoli bit di un port, o un registro, puoi usare le macro SBI(reg,bit) e CBI(reg,bit), usano le omonime istruzioni assembly e richiedo solo due cicli macchina per l'esecuzione.

SBI = Set Bit in I/O Register
CBI = Clear Bit in I/O Register

Code: [Select]

//SBI e CBI
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

erpomata


Allora vuol dire che non hai letto il mio post quotato da PaoloP  :P
http://arduino.cc/forum/index.php/topic,124080.msg933207.html#msg933207


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.

http://www.paologiammarco.it
http://www.valentinamagni.it

Augusto Picciani

#20
Mar 09, 2013, 04:16 pm Last Edit: Mar 09, 2013, 04:19 pm by Augusto Picciani Reason: 1
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:
Code: [Select]

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.

leo72



Allora vuol dire che non hai letto il mio post quotato da PaoloP  :P
http://arduino.cc/forum/index.php/topic,124080.msg933207.html#msg933207


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:
Code: [Select]
PORTD |= ((1<<3) | (1<<5));
PORTD &= ~((1<<4) | (1<<2));



leo72


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:
Code: [Select]

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.

PCINTxx indicano gli interrupt di cambio di stato, non i pin.
Inoltre il PCINT2 è agganciato al pin PB2, non PD2.

Per fare la lettura dello stato del pin 2 fai:
Code: [Select]
if ((PIND & (1<<PB2)) == 1) { ...
}

erpomata

Ok alla fine si è giunti dove dicevo io:


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?
http://www.paologiammarco.it
http://www.valentinamagni.it

leo72


Ok alla fine si è giunti dove dicevo io:


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  :P
Perché puoi comporre il byte da passare alla porta PRIMA.

Riprendendo il mio esempio precedente, possiamo fare così:
Code: [Select]
byte temp = ((1<<3) | (1<<5));
temp &= ~((1<<4) | (1<<2));
PORTD = temp;


Come vedi, con UNA SOLA operazione sulla porta, cambio i bit che mi interessano.  ;)

astrobeed


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 ?

http://arduino.cc/forum/index.php/topic,152705.msg1149202.html#msg1149202

pablos

Quote
Scomponi le operazioni in 2 righe, una per l'attivazione con OR ed una per la disattivazione con AND.
Esempio:


Code: [Select]

PORTD |= ((1<<3) | (1<<5));
PORTD &= ~((1<<4) | (1<<2));


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.
no comment

leo72

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

erpomata

Esatto.

@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.
http://www.paologiammarco.it
http://www.valentinamagni.it

leo72

1) ti leggi la porta e depositi il suo valore in una variabile tampone
2) esegui le modifiche del caso alla variabile tampone
3) riscrivi la variabile tampone sulla porta.

In questo modo cambi lo stato solo dei bit/pin che ti interessa alterare.

Go Up