Frage zu Bitmanipulation

#775191
Lesenswert?

Moe wrote:
> PORTB = PORTB << 1
>
> Das schiebt ja praktisch bei jedem Aufruf ne 1 durch den kompletten
> Port.
Nö. Es schiebt den Inhalt von PORTB um eine Stelle nach links. Wenn in 
PORTB vorher keine 1 stand, dann wird auch keine 1 geschoben.

Wenn Du willst, dass immer nur eine LED leuchtet, musst Du hinten 
jeweils wieder ne 1 anhängen (also das Bit Nr. 0 auf 1 setzen).

Bsp.:
Anfang: PORTB: 11111110
-> PORTB <<= 1;
-->     PORTB: 11111100
-> PORTB |= 1; (letztes Bit 1 setzen)
-->     PORTB: 11111101
usw...
Da musste jetzt noch Code machen, den Dein Compiler versteht

EDIT:
Wenn die LEDs Low-Side angeschlossen sind, dann sieht das natürlich 
anders aus. Ich bin jetzt von High-Side angeschlossenen LEDs ausgegangen 
(Portpin 0 -> LED leuchtet).
Gast #775195
Lesenswert?

Abhilfe schaft ein Portsave.

Problem ist Read-Modify-Write.
Daher Char ändern und schreiben

unsigned char pas=1;

while(1){
  pas<<= 1;
  if (pas==0)pas=1;
  PORTA =pas;
  _delay_ms(100);
  PORTA =pas;
}

das geht bestimmt!!!
gruß hans
Gast #775201
Lesenswert?

Also nochmal:


Ich hab schon nen Timer der X mal in der Sekunde nen Interrupt auslöst.

So und mit meinem Code geht eine LED nach der anderen an bis alle an 
sind und dann werden sie praktisch wieder eingeschaltet. Es sollte aber 
immer nur eine LED an sein.

Startwert ist PORTB = 0xFF // Alle LEDS aus

11111111
01111111
10111111
11011111
.
.
.
so sollte es aussehen, ohne einen hexwert auf den kompletten port zu 
schreiben. Geht das?

Moe
#775216
Lesenswert?

Moe wrote:
> natürlich andersrum:
>
> 11111111
> 11111110
> 11111101
> 11111011
>
> Der Beitrag  von Johannes hört sich schonmal ganz gut an.
Die eleganteste Methode wäre, jeweils das höchstwertige Bit zu sichern 
und beim nächsten Schieben wieder hinten dranzuhängen. In Assembler 
geht das übrigens ganz einfach. In C ist es komplizierter...
#775236
Lesenswert?

@ Johannes M. (johnny-m)

>> 11111111
>> 11111110
>> 11111101
>> 11111011
>
> Der Beitrag  von Johannes hört sich schonmal ganz gut an.
>Die eleganteste Methode wäre, jeweils das höchstwertige Bit zu sichern
>und beim nächsten Schieben wieder hinten dranzuhängen. In Assembler

Kaum. Einfach auf positive Logik umrechnen, schieben und gut.

PORTA = ~(~PORTA<<1);

MfG
Falk
Gast #775267
Lesenswert?

volatile unsigned char PORTVar = 0x01; //Dient zur Sicherung des Ports

void main(void)
{
.. //Timer Inits, Interrupt inits usw...
PORTB = 0xFF; //Erstmal Pull ups ein.
DDRB = 0xFF;  //Port als Ausgang schalten!!! (Damit werden PortPins zu 
high)
}

ISR (TIMERX..)
{
  if (PORTVar == 0x00) PORTVar=0x01; //Kann man so machen, da ja genug
                                     //Timer-Zeit vorhanden
  PORTB=~PortVar;
  PORTVar<<=1;
}
Gast #775271
Lesenswert?

Du hast mehrere Möglichkeiten:

1.:
PORTA=0xFE;
 while(1){
  if (PORTA==0x7F) PORTA=0xFE;
  else{
   PORTA<<=1;
   PORTA++;
  };
 };

2.:
 unsigned char dummy;
 dummy=0x01;
 PORTA=0xFE;
 while(1){
  if (dummy==0x80) dummy=0x01;
  else dummy<<=1;
  PORTA=~dummy;
 };

3.:
 PORTA=0xFE;
 while(1){
  if (PORTA==0x7F) PORTA=0xFE;
  else PORTA=~(~PORTA<<1);
 };

Natürlich nicht in ne while(1) sondern in deine ISR. Und eben PORTB, 
nicht A.
#775344
Lesenswert?

Moe wrote:
> @Falk
>
> Naja, als Hobby-Tüfftler weniger. Ka wie man das sinnvoll begrenzen kann
> :o


Als erstes musst du dir mal überlegen, welche 4 LED es denn sein sollen.
Wenn du das weist, dann weist du auch mit welchem Initialiwert
dein Port geladen werden muss, damit genau diese erste LED
brennt.
Wenn du dann 4 mal geschoben hast, welche LED brennt dann?
Wie sieht daher dann das entsprechende Byte aus?
#775361
Lesenswert?

Weist du: Das schöne an unserem Hobby ist, dass man einfach
mal auch ein bischen experimentieren kann. Natürlich überlegt.
Es ist sinnlos einfach irgendwelchen Quatsch hinzuschreiben
und zu hoffen das das schon funktionieren wird.
Aber wenn man einen Plan hat und sich bei dem was man tut
auch noch ein bischen was überlegt, dann kann man einfach
drauflos experimentieren ohne Gefahr zu laufen irgendwas
kaputt zu machen.
Das geile an der Sache ist, dass man sofort Rückmeldung
hat. Macht der µC das so, wie ich mir das gedacht habe, oder
habe ich falsch gedacht.
Gast #775402
Lesenswert?

Dann rechne es halt um.

Tip zum Umrechnen:
Bei BIN -> HEX ist es recht übersichtlich, du teilst das Byte in 2 
Nibble auf -> 1111 und 0111.
Der linke Teil ist die höherwertige Stelle in HEX 1111 = F, die 
niederwertige 0111 = Eigenleistung.

EDIT: Alternativ zur Eigenleistung einfach unten schauen.
#775405
Lesenswert?

Moe wrote:
> Öhm ja schon, war doch richtig meine Überlegung? Ich kann ja schlecht
> "11110111" schreiben?

1. Man kann mit dem avr-gcc

   PORTB = 0b11110111;

   ist zulässig. Dieser Compiler ist erweitert um Zahlen mit
   dem Präfix 0b als Binärzahlen zu lesen

2. Die Umrechnung nach Hex sollte ja wohl kein Problem sein.
   Geht mittels Tabelle (die man bald auswendig kann)

   0000    0      0101   5      1010  A       1111  F
   0001    1      0110   6      1011  B
   0010    2      0111   7      1100  C
   0011    3      1000   8      1101  D
   0100    4      1001   9      1110  E


   Deine 8 Bit Zahl 11110111  in 2 4-Bit Einheiten (sog. Nibbles)
   zerlegen und für jeden Nibble den Wert aus der Tabelle holen:

   11110111 ->   1111  0111

                   |    |
                   |    |
                   v    v

                   F    7

   also entspricht 11110111 der Hex-Zahl 0xF7
Gast #775410
Lesenswert?

Danke, Danke, Danke für die Erklärungen. Wenn man sich damit nur paar 
Tage im Monat beschäftigt bleibt halt nicht immer so viel hängen. Aber 
das hilft mir aufjeden Fall weiter.

Echt gut erklärt, und kapiert -> funktioniert

Schönen Tag noch,

Moe
Gast #775419
Lesenswert?

Schön soweit, kannst dir ja mal selber überlegen was du ändern müsstest 
wenn du die jetzt unbenutzten 4 Bit für was anderes benutzen willst.

@Karl Heinz: Lust dein Posting als Artikel zur Umrechnung abzulegen? 
Sowas hab ich bislang nicht gefunden.
Gast #775443
Lesenswert?

Hi

Man muss sich eigentlich nur merken, daß die Bits in einem Nibble die 
Wertigkeiten 8-4-2-1 (also 2er-Potenzen) besitzen. Z.B. 1010 ist dann 
1*8+0*4+1*2+0*1=10D. Wenn man dann noch weiss, das 10D=A ist, kann man 
sich den Rest an den Fingern abzählen.

MfG Spess
#775451
Lesenswert?

Ich hab da auch ein paar Merkhilfen.
Wie Spess schon sagte: dezimal 10 entspricht A. In der
binären Schreibweise ist das 1010 (also 2 mal die 10 hintereinander).
Die Hex-Buchstaben zähl ich normalerweise an den Fingern ab (bis
auf F).
Alle ungeraden Zahlen haben eine 1 an der letzten Stelle.
Und die Binärzahlen für 8, 4, 2, 1 und 0 sind auch leicht
zu merken. Da kommt immer nur eine einzelne 1 vor
Mal sehen was haben wir bisher

   0   0000            9
   1   0001            A  1010
   2   0010            B     Fingern abzählen
   3      1            C     Fingern
   4   0100            D     Fingern
   5      1            E     Fingern
   6      0            F  1111
   7      1
   8   1000

Da sind dann noch 3 und 7. Da sie um 1 kleiner sind als
die unmittelbar danach folgende 2-er Potenz 4 bzw. 8
merkt man sich die auch leicht: Lauter 1-er bis unmittelbar
vor die Stelle an der die nächste 2-er Potenz den einzigen
1-er haben wird.

   3    0011     (weil: 4 0100)
   7    0111     (weil: 8 1000)

damit bleiben aber nur noch 5, 6 und 9.
5 und 9, als Zahl unmittelbar nach einer 2-er Potenz sind
ähnlich aufgebaut.

die 2-er Potenz war 4  0100, 5 ist daher: 0101 (von mir aus
deswegen weil es die nächste ungrade Zahl ist und ungerade
Zahlen haben immer eine 1 ganz rechts

die 2-er Potenz war 8  1000, 9 ist daher: 1001

Bleibt nur noch die 6. Und die muss man sich merken 0110
(von mir aus: die beiden 1-er sind im Zentrum und das Zentrum
des Menschseins ist nun mal Sex)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren