Bit e shift

fratt:
Riguardo la digitalWrite, non ne capisco molto di implementazione a basso livello e temporizzazioni, ma anni fa ho fatto un progettino che genera un'onda quadra con digitalWrite e funziona da anni senza problemi.

Forse, come tu dici, in questo caso i tempi non sono critici, ma qui trovi delle prove che hanno fatto:
http://www.billporter.info/2010/08/18/ready-set-oscillate-the-fastest-way-to-change-arduino-pins/
Tieni presente ciò se in futuro dovrai fare qualcosa a maggior velocità. :slight_smile:

Ma secondo voi è corretta questa istruzione che dovrebbe invertire lo stato di un bit come indicato nel link di Datman?

#define sbi(port,bit) (port)|=(1<<(bit))

È una macro.
sbi=set bit: mette un bit di una porta a livello alto.

Questo lo so ma nell' articolo dice:

Next I tested just flipping a pin. By this I mean I just changed the pin state without knowing what the initial state was without testing. The methods of testing

  • digitalWrite(pin, !digitalRead(pin))
  • PORTB ^= (_BV(0))
  • sbi(PINB,0)

#define sbi(port,bit) (port)|=(1<<(bit))

Lui sta facendo un test per invertire lo stato di un bit.

Mettendo a 1 PINB si inverte lo stato.

Facendo un OR? sono un po confuso

No.
ATmega328p datasheet:
13.2.2 Toggling the Pin
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn. Note that the SBI instruction
can be used to toggle one single bit in a port.

Ah ecco cosa mi sfuggiva....

Si, ma in effetti io starei attento ad usare un metodo simile perché ... la portabilità va a farsi friggere ...

Quella è una peculiarità dei vecchi AVR, ci sarebbe già da andare a verificare se, con le nuove famiglie, funziona e, quasi sicuramente, non esiste l'equivalente su altre MCU, quindi ... o si sta scrivendo firmware altamente ottimizzato che deve girare su una specifica MCU o ... meglio evitare e fare in altro modo.

Guglielmo

EDIT: ... guardando il datasheet, sembra che la cosa sia implementata anche sulla serie megaAVR 0 (i nuovi AVR) e ho trovato qualche cosa anche sul SAMD21 ... comunque, come detto, verificare sempre perché è cosa legata alla specifica famiglia di MCU e quindi in alcune potrebbe essere presente, in altre potrebbe richiedere una tecnica diversa (la scrittura in uno specifico registro dedicato all'inversione del bit) ed in altre ancora potrebbe proprio non esserci.

Giusto! :slight_smile:

Riprendo a stressare ho provato con questo sketch ma ancora non funziona

int val1 = 0b000000000001;
int val2 = 0b000000000011;
int val3 = 0b000000000010;
int val4 = 0b000000000000;

int Uscita = 1;
int Valore = 0;
int i = 0;
int bitout = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(Uscita, OUTPUT);
}

void loop()
{
  Valore = analogRead(A1);     // effettuo lettura su pin analogico A1 e memorizzo il valore nella variabile valore_letto
  //digitalWrite (Uscita, LOW);
  // Pulsante 4
  if (Valore >= 0 && Valore <= 200)
  {
    delayMicroseconds(11520); //Pausa di Reset
    {
      for (int i = 0; i < 11; i++)
      bitout = (val1 >> i) & 1;

      if (bitout == 0)
      {
        digitalWrite(Uscita, LOW);
        delayMicroseconds(330);
        digitalWrite(Uscita, HIGH);
        delayMicroseconds(660);
        digitalWrite(Uscita, LOW);
      }
   
      {
        digitalWrite(Uscita, LOW);
        delayMicroseconds(660);
        digitalWrite(Uscita, HIGH);
        delayMicroseconds(330);
        digitalWrite(Uscita, LOW);
      }
    }
  }
}

nel senso che non mi da in uscita il segnale che speravo, ho corretto alcune cose avete un suggerimento grazie.

Probabilmente ti manca un if...

 }
   
      {
        digitalWrite(Uscita, LOW);
        delayMicroseconds(660);
        digitalWrite(Uscita, HIGH);
        delayMicroseconds(330);
        digitalWrite(Uscita, LOW);
      }

Io resto dell'idea che il problema è il for e forse manca l'else

Edit: come verifichi che il risultato non è corretto?

fratt:
Io resto dell'idea che il problema è il for e forse manca l'else

Edit: come verifichi che il risultato non è corretto?

se inserisco l'else mi da errore sulla graffa, cominque se if è vero esegue il blocco successivo e se valso lo salta ed esegue quello dopo giusto?
lo verifico collegando l'uscita all'ingresso line del pc e con audacity vedo il segnale in uscita del micro.

Sono sul tel e faccio fatica a verificare le graffe, ma così a occhio se nella riga vuota metti un else (lasciando le graffe come sono) non dovrebbe darti errore.
Adesso il secondo blocco viene eseguito comunque, sia se l'if è vera sia se è falsa.

Però, il for senza graffe ripete solo la prima riga che trova subito dopo, quindi adesso esegue 12 volte lo shift e dopo esegue un'unica volta l'if.
E' quello che ti serve?

Ce n'è una di troppo.

fratt:
Sono sul tel e faccio fatica a verificare le graffe, ma così a occhio se nella riga vuota metti un else (lasciando le graffe come sono) non dovrebbe darti errore.
Adesso il secondo blocco viene eseguito comunque, sia se l'if è vera sia se è falsa.

Però, il for senza graffe ripete solo la prima riga che trova subito dopo, quindi adesso esegue 12 volte lo shift e dopo esegue un'unica volta l'if.
E' quello che ti serve?

Scusa ma non potevo rispondere. No volevo fargli eseguire un blocco se 0 ed il secondo se 1. Comunque ho modificato un pochino la cosa e sembra funzionare solo che non mi convince questo passaggio perché sembra mi restituisca solo 0 o 1 alla variabile

   for (int i = 0; i < 11; i++)
      bitout = (val1 >> i) & 1;

Se funziona col for così allora non ho capito la logica del programma.

In che senso ti restituisce solo 0 o 1... Stai lavorando sui bit, solo 0 o 1 possono essere... Mi sfugge qualcosa?

fratt:
Se funziona col for così allora non ho capito la logica del programma.

In che senso ti restituisce solo 0 o 1... Stai lavorando sui bit, solo 0 o 1 possono essere... Mi sfugge qualcosa?

Ciao il discorso è che voglio realizzare un telecomando apricancello a 433Mhz e utilizzare una codifica a 12 bit quindi il programma dovrebbe leggere il valore di ogni bit della variabile valx ed a seconda se è 0 o 1 deve mandare un impulso diverso per i due valori. La mia idea era leggere l'ultimo bit della variabile fare l'operazione, leggere il secondo e così via per tutti e 12 poi un periodo che serve al ricevitore come reset/sincronismo e ripetere l'operazione fino a quando il tasto è premuto. Lo voglio realizzare con un attiny85 domani vedo di postare lo sketch che ho realizzato così potremmo vedere perchè si intoppa e dove. Purtroppo non sono molto ferrato in C ma me la cavo con l'elettronica tradizionale reduce da un diplona praticamente risalente al paleolitico (fine anni 80).

Allora avevo capito giusto...
E mi sembra strano che funzioni col for senza graffe.
In ogni caso, per quello che vuoi fare forse è più semplice con la funzione bitRead come suggerito da @maubarzi al post #8.