Hallo Leute, ich bin neu in der µC Programmierung und ich arbeite mich rein. Ich habe das Kapitel "Sprungtabelle" gelesen und denke, auch verstanden... Ich möchte mit meinem Programm eine 7-Segment-Anzeige ansteuern, klappt nicht so wie ich will ;) Beim Reset soll ein 'n' angezeigt werden, bei mir ist es aber eine 9, welche ich gar nicht im Quelltext so stehen habe, da ich nur von 'r' bis '7' gehe. Die Ausgabe ist normalerweise i.O., habe alle Zeichen separat getestet. Ich nutze einen ATmega8 (myAVR USB MK2) und myAVR Workpad. Zudem habe ich alles Störende auskommentiert, sodass der µC eigentlich gleich in den zweiten Eintrag springen sollte. Ist eigentlich ein einfaches Programm, ist schon enttäuschend, das selbst das nicht klappt. Hier der Quelltext(ab 'main', Ausgabe aufs Wesentliche gekürzt): ;Start, Power ON, Reset main: ldi r16,lo8(RAMEND) out SPL,r16 ldi r16,hi8(RAMEND) out SPH,r16 sbi DDRB,5 ;Port B.5 für 'a' sbi DDRC,0 ;Port C.0 für 'b' sbi DDRC,1 ;Port C.0 für 'c' sbi DDRC,2 ;Port C.0 für 'd' sbi DDRC,3 ;Port C.0 für 'e' sbi DDRC,4 ;Port C.0 für 'f' sbi DDRC,5 ;Port C.0 für 'g' cbi DDRD,2 ;Port D.2 Eingang Taster1 sbi PORTC,2 ;Port D.2 Pull-Up cbi DDRD,3 ;Port D.3 Eingang Taster2 sbi PORTC,3 ;Port D.3 Pull-Up ldi r17,1 ;Neutral als Voreinstellung ;----------------------------------------------------------------------- - mainloop: wdr ;sbis DDRD,2 ;Taster1 gedrückt ;rcall RUNTER ;sbis DDRD,3 ;Taster2 gedrückt ;rcall HOCH ;'switch'-Anweisung ---------------------------- ;cpi r17,9 ;brsh mainloop ldi r30,Tabelle ldi r31,Tabelle add r30,r17 ldi r16,0 adc r31,r16 ijmp Tabelle: rjmp R_GANG rjmp NEUTRAL rjmp EINS rjmp ZWEI rjmp DREI rjmp VIER rjmp FUENF rjmp SECHS rjmp SIEBEN ; Anzeige runterschalten------------------------------------------------ RUNTER: cpse r17,0 ;R-Gang ist schon eingelegt dec r17 ret ; Anzeige hochschalten-------------------------------------------------- HOCH: cpse r17,8 ;7. Gang ist schon eingelegt inc r17 ret ; Ausgabe aktueller Gang (lange Version)-------------------------------- R_GANG: sbi PORTB,5 ;'a' sbi PORTC,0 ;'b' sbi PORTC,1 ;'c' sbi PORTC,2 ;'d' cbi PORTC,3 ;'e' sbi PORTC,4 ;'f' cbi PORTC,5 ;'g' rjmp ENDE NEUTRAL: sbi PORTB,5 ;'a' sbi PORTC,0 ;'b' cbi PORTC,1 ;'c' sbi PORTC,2 ;'d' cbi PORTC,3 ;'e' sbi PORTC,4 ;'f' cbi PORTC,5 ;'g' rjmp ENDE EINS: sbi PORTB,5 ;'a' cbi PORTC,0 ;'b' cbi PORTC,1 ;'c' sbi PORTC,2 ;'d' sbi PORTC,3 ;'e' sbi PORTC,4 ;'f' sbi PORTC,5 ;'g' rjmp ENDE ZWEI: cbi PORTB,5 ;'a' . . cbi PORTC,4 ;'f' cbi PORTC,5 ;'g' rjmp ENDE SIEBEN: cbi PORTB,5 ;'a' cbi PORTC,0 ;'b' cbi PORTC,1 ;'c' sbi PORTC,2 ;'d' sbi PORTC,3 ;'e' sbi PORTC,4 ;'f' sbi PORTC,5 ;'g' ENDE: ldi r30,mainloop ldi r31,mainloop ijmp Wo liegt mein Fehler? Für Eure hilfe bin ich im voraus dankbar. MfG Björn
Der Hauptfehler dürfte sein das du es in ASM versuchst, C wäre viel einfacher, übersichtlicher und schneller zu coden.
Hi! > ldi r30,Tabelle > ldi r31,Tabelle ändern in: ldi r30,low(Tabelle) ldi r31,high(Tabelle) dann sollte es eigentlich passen. > ldi r30,mainloop > ldi r31,mainloop da natürlich auch. Viel Erfolg, Uwe
Danke für die schnelle Antwort. Ich habe es geändert, aber das Problem ist immer noch gleich, obwohl diesmal ein anderes (wildes) Zeichen dargestellt wird. Ich habe so meine Entwicklungsumgebung in Verdacht. 1 zu 1 konnte ich es nicht angeben, konnte es aber als
1 | |
2 | ldi r30,lo8(Tabelle) |
3 | ldi r31,hi8(Tabelle) |
eingeben. Half, wie schon gesagt, nicht. Zumindest lese ich aus der Antwort von Uwe, dass es im Prinzip richtig ist. Melde mich, wenn ich es gelöst bekommen habe.
Björn schrieb:
> dargestellt wird. Ich habe so meine Entwicklungsumgebung in Verdacht.
1 | ldi r30,lo8(2*Tabelle) |
2 | ldi r31,hi8(2*Tabelle) |
Der Flash wird Wordweise addressiert...
Hi!
habe jetzt kein Datenblatt da, aber:
> cpse r17,0
geht das nicht blos mit Registern?
also cpse r17,r16 (r16 hat ja 0)
oder eben
RUNTER: cpi r17,0 ;R-Gang ist schon eingelegt
brne EndeR
dec r17
EndeR: ret
Viel Erfolg, Uwe
Sieh dir hier cbi DDRD,2 ;Port D.2 Eingang Taster1 sbi PORTC,2 ;Port D.2 Pull-Up cbi DDRD,3 ;Port D.3 Eingang Taster2 sbi PORTC,3 ;Port D.3 Pull-Up mal an, welche PORT Pins du auf 1 schaltest :-) Sag mal sind dir die sbi und cbi nicht auf den Wecker gegangen? Für sowas macht man doch keine Sprungtabelle sondern eine Datentabelle (ok, bei dir 2 Tabellen, weil du die LED auf 2 Ports verstreut hast)! http://www.mikrocontroller.net/articles/AVR-Tutorial:_7-Segment-Anzeige (und benutze das AVR-Studio. Das hat einen schönen Debugger, mit dem du dein Programm in Einzelschritten durchgehen kannst und nachsehen kannst was passiert, welche Register wie verändert werden, welche Portpins welchen Zustand haben. Damit hört dann das Stochern im Nebel auf, warum ein Programm nicht das tut, was du dir vorstellst)
Zu den ganzen bereits beschriebenen Fehlern, wuerde ich sagen ist deine Sprungtabellenaddition auch noch Fehlerhaft. rjmp ist 2 byte breit, also wuerde ich sagen muss man offset*2 addieren. Das heisst folgenden code: add r30,r17 ldi r16,0 adc r31,r16 aendern in: mov r16,r17 lsl r16 add r30,r16 ldi r16,0 adc r31,r16
> Der Hauptfehler dürfte sein das du es in ASM versuchst, > C wäre viel einfacher, übersichtlicher und schneller zu coden. wenn man sich schon coder nennt sollte man die vorteile von assembler gerade bei µCs zu schätzen wissen. nichts gegen C, aber ich würd das auch in assembler schreiben. mal eine frage an den threadstarter: kannst du deine schaltung noch ändern? wenn du alle 7 segmente deiner anzeige auf einen einzelnen port legst kannst du alle mit zwei befehlen bedienen. brauchst dann nur das entsprechene byte als ganzes auf den port zu schreiben, alle bits auf einmal. kannst dafür auch die binäre schreibweise verwenden, dann ist das für dich besser zu verstehen. also z.b. LDI R16, 0b01010101 OUT PORTn, R16 0b01010101 ist das gleiche wie 0x55 oder dezimal 85.
Ben schrieb: >> Der Hauptfehler dürfte sein das du es in ASM versuchst, >> C wäre viel einfacher, übersichtlicher und schneller zu coden. > > wenn man sich schon coder nennt sollte man die vorteile von assembler > gerade bei µCs zu schätzen wissen. nichts gegen C, aber ich würd das > auch in assembler schreiben. Nichts gegen Assembler, aber dazu ist mir die Anwendung nicht zeitkritisch genug :-) Warten wir ab, bis er zu dem Punkt kommt an dem er realisiert, dass die Taster entprellt werden müssen :-)
Karl Heinz, wo ist der Unterschied ?? Taster müssen entprellt werden. Dazu muß man doch nur wissen WIE es geht. Die Sprache ist dabei völlig wurscht. Aber wie Ben schon sagte, man sollte Hardwarenah arbeiten. zB. Die Anzeige auf einen Port um dann mit 1 oder 2 Befehlen fertig zu sein. Das ist ja bei den Tastern nicht anders. Dann isses in ASM und in C nur halb so schwer.
> Warten wir ab, bis er zu dem Punkt kommt an dem er realisiert, > dass die Taster entprellt werden müssen :-) das kann er ja in hardware machen - dafür wäre selbst C nicht langsam genug ;) ein kleiner kondi über den tastern reicht ja dank der internen pullups meistens schon. einfacher zu lösen ists aber wenn er nach einer veränderung einfach n takte wartet bis der nächste tastendruck angenommen wird.
Vielen Dank für die vielen Antworten, echt ein super Forum! Nun funktioniert es, habe es wie folgt geändert: Zuerst habe ich 'AVR Studio' installiert und 'myAVR ProgTool' zum Brennen, da ich ein Entwicklungsboard von myAVR verwende. Daher kann ich z.Z. nicht alle PINs des jeweiligen Ports im vollen Umfang nutzen, da immer nur sechs Pins raus geführt sind, finde ich z.Z. gar nicht so schlimm :) (@Ben, @Karl heinz Buchegger) @Karl heinz Buchegger: Oh wie peinlich. Da fällt mir das Sprichwort ein: Manchmal sieht man den Wald vor lauter Bäumen nicht. Habe ich gleich in
1 | cbi DDRD,2 ;Port D.2 Eingang Taster1 |
2 | sbi PORTD,2 ;Port D.2 Pull-Up |
3 | cbi DDRD,3 ;Port D.3 Eingang Taster2 |
4 | sbi PORTD,3 ;Port D.3 Pull-Up |
geändert. Vielen Dank für den Hinweis :) @Uwe > cpse r17,0 Ja, das geht so nicht, werde ich ändern, hatte AVR Studio schon angemahnt :) Hier ist nochmal die funktionierende Sprungtabelle, habe es auch mit verschiedenen Voreinstellungen getestet:
1 | main: ldi r16,low(RAMEND) |
2 | . |
3 | . |
4 | ldi r17,2 ;Zweiter Gang als Voreinstellung |
5 | ;------------------------------------------------------------------------ |
6 | mainloop: wdr |
7 | ; sbis DDRD,2 ;Taster1 gedrückt |
8 | ; rcall RUNTER |
9 | ; sbis DDRD,3 ;Taster2 gedrückt |
10 | ; rcall HOCH |
11 | ; 'switch'-Anweisung ---------------------------- |
12 | ; cpi r17,(9) |
13 | ; brsh mainloop |
14 | ldi r30,low(Tabelle) ;AVR Studio konform |
15 | ldi r31,high(Tabelle) |
16 | add r30,r17 |
17 | ldi r16,0 |
18 | adc r31,r16 |
19 | ijmp |
20 | Tabelle: rjmp R_GANG |
21 | rjmp NEUTRAL |
22 | rjmp EINS |
23 | rjmp ZWEI |
24 | rjmp DREI |
25 | rjmp VIER |
26 | rjmp FUENF |
27 | rjmp SECHS |
28 | rjmp SIEBEN |
29 | . |
30 | . |
31 | ; Ausgabe aktueller Gang (lange Version) ----------------------------- |
32 | . |
33 | . |
34 | ZWEI: cbi PORTB,5 ;'a' |
35 | cbi PORTC,0 ;'b' |
36 | sbi PORTC,1 ;'c' |
37 | cbi PORTC,2 ;'d' |
38 | cbi PORTC,3 ;'e' |
39 | sbi PORTC,4 ;'f' |
40 | cbi PORTC,5 ;'g' |
41 | rjmp ENDE |
42 | . |
43 | . |
44 | ENDE: ldi r30,low(mainloop) |
45 | ldi r31,high(mainloop) |
46 | ijmp |
@Ben: Das mit den n-Takten oder eine ähnliche Lösung hatte ich auch schon im Hinterkopf. Bei der Taktfrequenz des ATmega8 und einem Tastendruck habe ich praktisch nur zwei Gänge: 'r' oder '7', je nachdem welchen Taster ich drücke :) Nochmals vielen Dank für die vielen Tipps. Björn
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.