Forum: Mikrocontroller und Digitale Elektronik Schieberegister in C ansteuern


von seacrash (Gast)


Lesenswert?

Ein Hallo an alle,

Ich habe ein Problem mit folgendem Code Vision Code.



do{
          SR_counter++;
          SR = SR_counter / 8;
          SR_bit = SR_counter % 8;

          set_clk;

          clr_clk;

 } while(!((1<<SR_bit ) & (SR_array[SR])));


Diese do while Schleife soll in einem Schieberegister ( der Reihe nach
) genau dort  eine "1" schreiben, wo im SR_array eine "1" steht. Da
es sehr viele Schieberegister sind und nur eine "1" immer
durchgeschoben werden soll, verzichte ich auf ein vollständiges Update
und schiebe diese "1" nur durch.
Funktioniert auch soweit.
Jetzt das Problem:
Beim Ausführen des Codes wird jedoch genau an der Stelle (SR_array[SR])
das erste untere Halb Byte des Schieberegisters überschrieben.(Aus
zB.0b11110111 wird 0b11110000) Woher weiß ich das?
Wenn ich (SR_array[SR]) ersetzte mit z.B. 0b01010100 bleibt der Wert im
array erhalten, der vorher drin stand.
Bin ratlos und würde mich über eine Idee über die mögliche Fehler -
Ursache freuen.

Bis dahin Gruß

von peter dannegger (Gast)


Lesenswert?

"verzichte ich auf ein vollständiges Update  und schiebe diese "1"
nur durch."

Das geht nicht !

Wenn Du in der Schlange vorm Stones-Konzert stehst, darfst Du Dich ja
auch nicht vordrängeln.

Ein Schieberegister schiebt oder schiebt nicht. Was es schiebt, ist ihm
wurscht (Bits mit VIP-Ausweis gibt es nicht).


Hier mal ein einfaches SPI-Beispiel mit WINAVR:
1
#include <io.h>
2
3
#define SPI_PORT        PORTB
4
#define SPI_SCK         PB0
5
#define SPI_DOUT        PB1
6
7
8
void spi_out( unsigned char dat )
9
{
10
  unsigned char i;
11
12
  for( i = 8; i; i-- ){
13
    SPI_PORT &= ~(1<<SPI_DOUT);
14
    if( dat & 1 )
15
      SPI_PORT |= 1<<SPI_DOUT;
16
    dat >>= 1;
17
    SPI_PORT |= 1<<SPI_SCK;
18
    SPI_PORT &= ~(1<<SPI_SCK);
19
  }
20
}

Peter

von seacrash (Gast)


Lesenswert?

Hallo Peter,

Danke für deine Antwort.

Vielleicht hab ich mich etwas undeutlich ausgedrückt. Natürlich schiebe
ich die "1" durch jedes Register, aber nur wenn eine 1 im Array steht,
wird es mit dem "store" clock an den Registerausgang durchgegeben.
Nach der von mir geposteten Schleife findet immer ein "store" statt.

Gruß

von peter dannegger (Gast)


Lesenswert?

"Vielleicht hab ich mich etwas undeutlich ausgedrückt."

Das ist aber stark untertrieben.


Schau Dir meinen Code an, der ist compilierbar.

Und nun schau Dir Deine paar Fitzelchen an, da ist überhaupt nichts mit
anzufangen.

Es kann doch keiner in Deinen Kopf gucken.


Peter

von Profi (Gast)


Lesenswert?

ich verstehe auch nicht ganz, was Du willst (was bedeutet z.B.
"vollständiges Update").

Es geht auch etwas kompakter (hier mit 16 Bits):
  unsigned int i;
  for(i=0x8000;i;i&data?printf("1"):printf("0"),i/=2);
oder
  i=0x8000;do i&data?printf("1"):printf("0");while(i/=2);

oder andersherum schieben (hier mit 8 Bits):
  unsigned char i;
  for(i=1;i;i&data?printf("1"):printf("0"),i*=2);
oder
  i=1;do i&data?printf("1"):printf("0");while(i*=2);

Der Clou ist, dass i sowohl Bitmaske als auch Bit-"Zähler" ist.
Die Ende-Bedingung ist, dass das Bit "herausfällt", i also 0 und
damit false wird.
while(i*=2)  bewirkt sowohl das Schieben der Maske als auch die Prüfung
des Ergebnisses der Schiebung auf die Ende-Bedingung.

Ich liebe "high-density Code"...

@Peter:
Wwarum setzt Du das Port zuerst mal auf 0, um es dann bedingt wieder zu
setzen? wäre nicht besser:
    if( dat & 1 )
      SPI_PORT |= 1<<SPI_DOUT;
    else
      SPI_PORT &= ~(1<<SPI_DOUT);

-> Weniger unnötige Aktivität auf der Datenleitung
-> weniger Störungen
-> weniger Stromverbrauch durch Umladen

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.