Pages: 1 [2] 3 4 5   Go Down
Author Topic: Velocizzare l'IO delle porte digitali  (Read 3164 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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).
Logged


Roma (RM)
Offline Offline
God Member
*****
Karma: 3
Posts: 634
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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


Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9178
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
//SBI e CBI
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
Logged

Roma (RM)
Offline Offline
God Member
*****
Karma: 3
Posts: 634
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Allora vuol dire che non hai letto il mio post quotato da PaoloP  smiley-razz
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.

Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 49
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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.
« Last Edit: March 09, 2013, 10:19:08 am by Augusto Picciani » Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Allora vuol dire che non hai letto il mio post quotato da PaoloP  smiley-razz
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:
PORTD |= ((1<<3) | (1<<5));
PORTD &= ~((1<<4) | (1<<2));

Logged


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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:
if ((PIND & (1<<PB2)) == 1) { ...
}
Logged


Roma (RM)
Offline Offline
God Member
*****
Karma: 3
Posts: 634
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Riprendendo il mio esempio precedente, possiamo fare così:
Code:
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.  smiley-wink
Logged


Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9178
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
Logged

Genova
Offline Offline
Faraday Member
**
Karma: 38
Posts: 3282
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
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.
Logged

no comment

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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


Roma (RM)
Offline Offline
God Member
*****
Karma: 3
Posts: 634
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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


Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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


Pages: 1 [2] 3 4 5   Go Up
Jump to: