Hi,
ich will ein Lauflicht realisieren:
PORTB = PORTB << 1
Das schiebt ja praktisch bei jedem Aufruf ne 1 durch den kompletten
Port. Problem dabei, die LEDs bleiben ja an. Wie löst man das am besten?
thx, Moe
Das kannst du lösen, indem du eine Led an schaltest, wartest z.B. durch
einen Timer oder die delay-Funktion, und dann die Voherige ausschaltest
und die Nächste an. Und dann immer so weiter.
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).
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
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
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...
@ 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
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.
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?
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.
@ Moe (Gast)
>Öhm ja schon, war doch richtig meine Überlegung? Ich kann ja schlecht>"11110111" schreiben?
Aber 0b11110111, dass versteht der AVR-GCC Compiler.
MfG
Falk
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.
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
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
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.
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
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)
Die einfachste "Merkhilfe" ist, die Zahlen 0..15 in Dezimal, hex und
binär im Kopf zu haben. Dann sieht man das sofort. So muss man auch
Fremdsprachen etc. lernen.
MfG
Falk