Pages: [1]   Go Down
Author Topic: chiarimento su PORTD = B10101000;  (Read 952 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
God Member
*****
Karma: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

volevo chiedere se c'è la possibilita di evitare di scrivere una porta con il comando
PORTD = B10101000;
esempio  qui il pin 3 viene portato a HIGH  ma se uno vuole evitare di scrivere un pin
come deve fare
questo comando IN teoria dovrebbe sceivere i pin da 0 a 7
ma prende bit da 1 a 12 senza generare errore
che cosa fa in realta se si scrive

PORTD = B1;

oppure

PORTD = B101010001010;
Logged


Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

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

volevo chiedere se c'è la possibilita di evitare di scrivere una porta con il comando
PORTD = B10101000;
esempio  qui il pin 3 viene portato a HIGH 
Più precisamente, sono impostati su High i pin 7, 5 e 3, non solo il pin 3.

Quote
questo comando IN teoria dovrebbe sceivere i pin da 0 a 7
ma prende bit da 1 a 12 senza generare errore
che cosa fa in realta se si scrive

PORTD = B1;
Equivale a 0b00000001 per cui metti a 0 tutti i bit/pin dall'8° al 2° bit e ad 1 il 1° bit.

Quote
PORTD = B101010001010;
Qui il compilatore tronca il numero ai primi 8 bit dato che PORTD è un byte per cui hai PORTD caricato col valore 10001010. Il compilatore dovrebbe troncare i bit in eccesso rispetto all'8°, se questa è l'implementazione di avr-gcc.

Per modificare un solo bit si usano di solito le operazioni logiche AND e OR.
Ricordando che con AND si ha come risultato 1 solo se entrambi i valori sono 1, quindi 1 AND 1 = 1 ma 1 AND 0 = 0 e 0 AND 1 = 0 e con OR si ha 1 se anche uno solo dei 2 bit confrontati è ad 1, quindi 1 OR 0 = 1, 0 OR 1 = 1, 1 OR 1 = 1  e 0 OR 0 = 0, si usano le seguenti operazioni:
PORTD &= ~(1<<3)
per impostare a 0 il bit n° 3. Come funziona? L'operazione 1<<3 è un'operazione di spostamento dei bit. Nello specifico, sposti  "1", che in binario è 00000001, di 3 posizioni a sinistra, ottenendo 00001000. L'operatore ~ è una forma contratta di NOT, quindi serve ad invertire il valore. Per cui 00001000 diventa 11110111. A questo punto esegui l'AND tra il valore di PORTD e 11110111. Come detto, un bit AND 1 dà come risultato 1 se era impostato ad 1 (1 AND 1 = 1) e dà 0 se era impostato a 0 (0 AND 1 = 0) per cui non modifichi il valore dei bit che non ti interessano e metti a 0 solo il bit che ti interessa.

PORTD |= (1<<3)
per impostare ad 1 il bit n° 3. Quest'operazione è più semplice da spiegare. Sposti sempre a sinistra di 3 posizioni il valore 1 ottenendo 00001000 e poi fai un OR. Ora, siccome un bit OR 0 dà il bit originale, anche qui non modifichi il valore dei bit che non ti interessano, ma imposti ad 1 il bit che ti interessa perché un qualunque valore di 0 o 1 OR 1 dà come risultato sempre 1.

Ricapitolando, in questo modo:
1) modifichi solo il bit che ti interessa
2) non ti importa sapere il valore corrente del bit.

Logged


0
Offline Offline
Faraday Member
**
Karma: 39
Posts: 5611
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

x iscrizione (karma incluso)  smiley
Logged

- [GUIDA] IDE1.x - Nuove Funzioni - Sketch Standalone - Bootloader - VirtualBoard
http://arduino.cc/forum/index.php/topic,88546.0.html
- [LIBRERIA] ST7032i LCD I2C Controller Library
http://arduino.cc/forum/index.php/topic,96163.0.html

Offline Offline
God Member
*****
Karma: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

volevo chiedere se c'è la possibilita di evitare di scrivere una porta con il comando
PORTD = B10101000;


Ricapitolando, in questo modo:
1) modifichi solo il bit che ti interessa
2) non ti importa sapere il valore corrente del bit.



questa cosa è interessante  ma alla fine dei "conti"volevo sapere che cosa succede a i pin che non voglio che siano toccati,

esempio reale,  pin 2 e 3  settati come input per interrupt,   pin  0,1,4,5,6,7,  settati come output   nel setup

se faccioPORTD = B11111111;   coa accade a i 2 e3 ?   
  continuano a funzionare come imput  o vengono portati a HIGH


OPPURE   pin A4 A5  SETTATI   come pin digitali  A0 A1 A2 LI ADOPERO COME ANALOGICI

se faccio PORTC = B11111111;   che gli succede a A0 A1 A2  continuano a funzionare come analogici oppure vengono  portati a HIGH
Logged


Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

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

questa cosa è interessante  ma alla fine dei "conti"volevo sapere che cosa succede a i pin che non voglio che siano toccati,
Tu non leggi ciò che ti scrivo  smiley-razz

volevo chiedere se c'è la possibilita di evitare di scrivere una porta con il comando
PORTD = B10101000;
esempio  qui il pin 3 viene portato a HIGH
Più precisamente, sono impostati su High i pin 7, 5 e 3, non solo il pin 3.
[/quote]

Quote
esempio reale,  pin 2 e 3  settati come input per interrupt,   pin  0,1,4,5,6,7,  settati come output   nel setup

se faccioPORTD = B11111111;   coa accade a i 2 e3 ?   
  continuano a funzionare come imput  o vengono portati a HIGH
Con questo comando metti tutti i bit ad 1 (come detto sopra).

Quote
OPPURE   pin A4 A5  SETTATI   come pin digitali  A0 A1 A2 LI ADOPERO COME ANALOGICI

se faccio PORTC = B11111111;   che gli succede a A0 A1 A2  continuano a funzionare come analogici oppure vengono  portati a HIGH
La seconda che hai detto.

La manipolazione per come la vuoi fare te, ossia scrivere l'intero ottetto di bit in un registro, comporta che cambi di stato anche ai bit che non vuoi toccare.

Esempio. Vuoi impostare ad 1 solo i bit 3 e 5 lasciando inalterati gli altri bit.
Hai 2 strade:
1) la via facile, usare le funzioni del core. Fai
Code:
bitSet(PORTD, 3);
bitSet(PORTD, 5);
2) la via difficile (ma non troppo). Fai:
Code:
PORTD |= ((1<<3) | (1<<5));

La differenza sta nel fatto che usando le funzioni del core, nel caso bitSet, devi scrivere 1 istruzione per bit, mentre manipolando direttamente i bit puoi compattare tutto in 1 sola istruzione.
L'ultimo esempio si trasforma in PORTD = PORTD OR (8 OR 32), cambi ad 1 quindi il bit 3 (2^3=8) ed il bit 5 (2^5=32).
Ricordati sempre che:
bit 0 -> 1° bit
bit 1 -> 2° bit
....
bit 7 -> 8° bit
Cioè che la loro posizione (1°..8°) è differente dal loro indice (0..7).
Logged


Offline Offline
God Member
*****
Karma: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

vediamo se ho afferrato    smiley-confuse

  "fare"       
PORTC = B11111111; 
PORTD = B11111111;
PORTB = B11111111;

come risultato si ha   che si settano tutti i pin come autput  e si mettono tutti HIGH
anche mettendo prima es:  nel setup
DDRD = B11111110; 
DDRD = DDRD | B11111100;
le porte verranno "sovrascritte" tutte  uguamente come autput  e si mettono tutti HIGH

confermi?


poi
facedo cosi invece
PORTD |= ((1<<3) | (1<<5));

si portano ad 1   i bit alla posizione 3 e alla 5      do per scontanto che mettendo 0 al posto di 1 portano i bit  a zero 
confermi ?,

per ultimo

bitSet(PORTD, 3);
bitSet(PORTD, 5);

se queste 2 righe   settano  settano il 3 e il 5   a uno   per  settarli a   a zero come si fa?
Logged


Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

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

vediamo se ho afferrato    smiley-confuse

  "fare"       
PORTC = B11111111; 
PORTD = B11111111;
PORTB = B11111111;

come risultato si ha   che si settano tutti i pin come autput  e si mettono tutti HIGH
anche mettendo prima es:  nel setup
DDRD = B11111110; 
DDRD = DDRD | B11111100;
le porte verranno "sovrascritte" tutte  uguamente come autput  e si mettono tutti HIGH

confermi?
Confermo.

Quote
poi
facedo cosi invece
PORTD |= ((1<<3) | (1<<5));

si portano ad 1   i bit alla posizione 3 e alla 5      do per scontanto che mettendo 0 al posto di 1 portano i bit  a zero 
confermi ?,
No. Devi usare l'AND per mettere a 0 i bit. Leggi post sopra.
Se fai 1 OR 0 ottieni sempre 1.

Quote
per ultimo

bitSet(PORTD, 3);
bitSet(PORTD, 5);

se queste 2 righe   settano  settano il 3 e il 5   a uno   per  settarli a   a zero come si fa?

bitClear.
Leggi qui:
http://arduino.cc/en/Reference/BitClear
http://arduino.cc/en/Reference/BitRead
http://arduino.cc/en/Reference/BitSet
Logged


Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 104
Posts: 6626
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

x iscrizione
Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Offline Offline
God Member
*****
Karma: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

vediamo se ho afferrato    smiley-confuse

  "fare"       
PORTC = B11111111; 
PORTD = B11111111;
PORTB = B11111111;

come risultato si ha   che si settano tutti i pin come autput  e si mettono tutti HIGH
anche mettendo prima es:  nel setup
DDRD = B11111110; 
DDRD = DDRD | B11111100;
le porte verranno "sovrascritte" tutte  uguamente come autput  e si mettono tutti HIGH

confermi?
Confermo.

Quote
poi
facedo cosi invece
PORTD |= ((1<<3) | (1<<5));

si portano ad 1   i bit alla posizione 3 e alla 5      do per scontanto che mettendo 0 al posto di 1 portano i bit  a zero 
confermi ?,
No. Devi usare l'AND per mettere a 0 i bit. Leggi post sopra.
Se fai 1 OR 0 ottieni sempre 1.

Quote
per ultimo

bitSet(PORTD, 3);
bitSet(PORTD, 5);

se queste 2 righe   settano  settano il 3 e il 5   a uno   per  settarli a   a zero come si fa?

bitClear.
Leggi qui:
http://arduino.cc/en/Reference/BitClear
http://arduino.cc/en/Reference/BitRead
http://arduino.cc/en/Reference/BitSet

allora mettiamo le cose in pratica,prendiamo ad esmpio un pezzo di codice che  modifichero


if (CFR2 >= 80000 && CFR2 < 90000)


digitalWrite (11, HIGH);
digitalWrite (5, HIGH);
digitalWrite (6, HIGH);
digitalWrite (7, HIGH);
digitalWrite (8, HIGH);
digitalWrite (9, HIGH);
digitalWrite (10,HIGH);
digitalWrite (16, LOW);
  }

posso trasformarlo in

if (CFR2 >= 80000 && CFR2 < 90000)



PORTD |= ((1<<6) | (1<<7) |(1<<5));   //metto HIGH pin 5,6,7,
PORTB |= ((1<<1) | (1<<2) | (1<<3)| (1<<4) );   //metto HIGH pin 8,9,10,11
PORTC &= ( (1<<3) );  //metto LOW pin 16
  }

e in questo  caso risparmio qualcosa in tempi di esecuzione e piu o meno quanto  rispetto a gli 8 digitalWrite

Logged


Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

Genova
Offline Offline
Faraday Member
**
Karma: 17
Posts: 2758
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Tutto quello che ti passa per la mente di chiedere prendi il forum e scrivi, quando potresti con un po' di impegno e ricerca risponderti da solo.

si 10us forse li hai risparmiati  smiley-roll
il fatto che questo sistema ti obbliga a scrivere 2 righe differenti per un high o low non so quanto sia conveniente.
Un digitalWrite (a, b); ti permette di sostituire le variabili per il cambio H/L in modo fast dando direttamente il num del pin (anche se in modo dispersivo), dipende sempre da cosa devi fare.
Se vuoi veramente risparmare tempo sull'esecuzione non usare l' ide e programmatelo in assembler per la generazione del codice macchina, quando a qualcuno esperto in programmazione di microcontrllori dici che usi arduino non so perchè gli si rizzano i capelli con arricciamenti di naso inclusi dato il suo sistema di programmazione  smiley-grin smiley-money
« Last Edit: September 24, 2012, 08:28:53 am by pablos » Logged

Meglio imparare dalle cose inutili piuttosto che non imparare niente.   [Arduino Mega R3 + Ethernet shield W5100 + SD card 8Gb FAT32]

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

il fatto che questo sistema ti obbliga a scrivere 2 righe differenti per un high o low non so quanto sia conveniente.
Quoto.
L'alternativa è studiare un modo per usare gli 8 pin contigui di una stessa porta, in modo da poter assegnare un byte unico alla porta e modificare così tutti i pin di quella porta.
Ad esempio, PORTD è mappata sui pin D0..D7.
Logged


Offline Offline
God Member
*****
Karma: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

eh eh  c'ero quasi arrivato annch'io,
solo che PORTD  contiene i pin interrupt   e mi servono
se ci fosse un modo per spostarli  su 2 pin analogici
userei i pin da 0 a 13  per far tutto
Logged


Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

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

Usa i PCINT invece degli INT.
http://arduino.cc/playground/Main/PinChangeInt
Li puoi agganciare a qualunque pin dell'Arduino.
Logged


Offline Offline
God Member
*****
Karma: 8
Posts: 691
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ma si potrebbe spostare  i 2 pin interrupt     su  A4  A5  senza caricare la libreria
o scrivento pochissimo codice?
Logged


Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

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

Certamente. Ti prendi il datasheet e piloti i registri per attivare i PCINT sui pin che ti interessano. Poi crei una ISR per intercettare gli interrupt.
Logged


Pages: [1]   Go Up
Jump to: