programma troppo lento per settare 8 bit

ho un numero 8 bit da 0-255 e devo scriverlo nei pin 2-3-4-5-6-7-8-9 di arduino.
ho fatto delle funzioni che converte il numero in binario e poi bit per bit li scrive sui rispettivi pin.
mi sono accorto che questo metodo è molto lento e rallenta il resto del programma.
nei bit è collegato un decodificatore D/A R2R.

int b1x=2;
int b2x=3;
int b3x=4;
int b4x=5;
int b5x=6;
int b6x=7;
int b7x=8;
int b8x=9;
void setup() {
  pinMode(b1x, OUTPUT);
  pinMode(b2x, OUTPUT);
  pinMode(b3x, OUTPUT);
  pinMode(b4x, OUTPUT);
  pinMode(b5x, OUTPUT);
  pinMode(b6x, OUTPUT);
  pinMode(b7x, OUTPUT);
  pinMode(b8x, OUTPUT);
}
void stampa(int x){
  int bx=1;
  while(x!=0){
    if(x%2==0){
      x=x/2;
      scrivi_bx(bx, 0);
    }else{
      x=(x-1)/2;
      scrivi_bx(bx, 1);
    }
    bx++;
  }
}
void scrivi_bx(int bx, int livello){
  switch (bx){
    case 1:
      digitalWrite(b1x, livello);
      break;
    case 2:
      digitalWrite(b2x, livello);
      break;
    case 3:
      digitalWrite(b3x, livello);
      break;
    case 4:
      digitalWrite(b4x, livello);
      break;
    case 5:
      digitalWrite(b5x, livello);
      break;
    case 6:
      digitalWrite(b6x, livello);
      break;
    case 7:
      digitalWrite(b7x, livello);
      break;
    case 8:
      digitalWrite(b8x, livello);
      break;
  }
}


void loop(){
  stampa(N° desiderato)
}

se vi sembra complesso e incompressibile il programma è perché prima di chiedervi volevo provare a modo mio ed era l'unica idea che avevo :slight_smile:
Sapete come posso pilotare un D/C R2R?

ilmandorlone:
Sapete come posso pilotare un D/C R2R?

Non usare la digital Write, collega il DAC a PORTD, pin da 0 a 7, scrivi il byte direttamente sul PORTD tramite relativo registro, dato che i pin 0 e 1 vengono utilizzati come OUT non ci sono problemi per caricare il software tramite bootloader.

Quello che stavo per suggerire io, questo può aiutarti:
http://www.leonardomiliani.com/2013/manipoliamo-direttamente-le-porte-logiche-di-una-mcu/

Confermo erpomata, per avere il max della velocità potresti manipolare le porte in modo diretto.
In questo modo 8 pin li cambi con un'unica operazione. Però ovviamente dovresti usare i pin dallo 0 al 7, per cui dovresti mettere un paio di jumper sui pin 0 e 1 per non perdere la possibilità di upload dei nuovi sketch.

leo72:
per cui dovresti mettere un paio di jumper sui pin 0 e 1 per non perdere la possibilità di upload dei nuovi sketch.

Come ho già detto poco sopra non serve perché 0 e 1 sono OUT e come tale non danno fastidio alla seriale durante la programmazione, il problema si pone quando sono INPUT con device collegati.

se uso i 7 bit vado a usare i pin 0 e 1.
non capisco come la seriale non vada a influire sui pin 0-1??
mi fareste un esempio con un blink su pin 0 per capire meglio?

ilmandorlone:
non capisco come la seriale non vada a influire sui pin 0-1??

Ma lo hai letto quello che ho scritto oppure no ?
Vuoi provare con il blink ? Benissimo usa il programma d'esempio e cambia il pin da 13 a 0, o a 1, e vedrai che la cosa non crea nessun problema per la programmazione.

a ok nel mio caso basterà scrivere

DDRD = 0b11111111;
PORTD = 0b********;

se volessi scrivere una variabile decimale al posto di 0b... cosa devo fare?

Quest'articolo ti spiega un pò di cose.

erpomata:
Quello che stavo per suggerire io, questo può aiutarti:
http://www.leonardomiliani.com/2013/manipoliamo-direttamente-le-porte-logiche-di-una-mcu/

ilmandorlone:
se volessi scrivere una variabile decimale al posto di 0b... cosa devo fare?

La scrivi direttamente sul port, le varie notazioni sono solo per comodità umana, per il micro esiste solo il binario, scrivere PORTD = 0b11111111, oppure PORTD = 0xff, oppure PORTD = 255 è esattamente la stessa cosa e sono tutte e tre sintatticamente valide.

Quindi non hai neanche bisogno di fare questo:

ilmandorlone:
ho fatto delle funzioni che converte il numero in binario e poi bit per bit li scrive sui rispettivi pin.

leo72:
Confermo erpomata, per avere il max della velocità potresti manipolare le porte in modo diretto.
In questo modo 8 pin li cambi con un'unica operazione. Però ovviamente dovresti usare i pin dallo 0 al 7, per cui dovresti mettere un paio di jumper sui pin 0 e 1 per non perdere la possibilità di upload dei nuovi sketch.

E' in generale lenta la digitalWrite o la lentezza che riscontra @mandorlone è legato ai 4 kg di int che ha dichiarato?
Usando bitRead(x, n) e una variabile byte sarebbe comunque lento ? (bitRead è solo una define, no call a funzione)

Il problema è dalla gran quantità di codice che c'è nella digitalRead e digitalWrite.
Vedete qua:

http://www.skpang.co.uk/blog/archives/323

grazie per la disponibilità

ora che ho fatto vari test mi sono ricordato che uso 2 convertitori R2R ma c'è solo la porta logica D che ha 8 bit mentre B e C solo 6.
posso "fondere" B con C?

salve
usando i registri delle porte per migliorare la velocità di set dei pin avrei bisogno di 2 porte da 7 bit
l'ATmega 328 ha 1 porta da 7 e 2 da 5 bit
posso usare 2 bit della porta C per aggiungerle a quelle della porta B?

Certo che puoi ma non puoi settarle contemporaneamente.
Prima setti i pin della PORTA B e poi setti i 2 pin rimanenti della PORTA C

e come posso fare?
ho un numero decimale come imposto che i primi 6 bit vengono scritti in B e gli ultimi 2 in C?

Con una maschera di bit fatta con un AND binario.
Se fai un AND con 00111111 solo i primi 6 bit vengono considerati, facendo un AND con 11000000 solo gli ultimi 2.
Quindi

PORTB = valore & 0b00111111;
PORTC = valore & 0b11000000;

Attenzione che così per cambi tutti pin delle 2 porte.
Se vuoi approfondire, ho scritto un articolo a riguardo

Sbaglio o il thread è collegato a questo?

http://arduino.cc/forum/index.php/topic,161499.0.html

Sono simili. In entrambi si parla di manipolazione di una porta.