Datum:
Hallo Community, ich bin gerade am Verzweifeln. Meine Erfahrung mit Assembler Programmierung ist ziemlich dürftig. Deshalb drehe ich mich wohl seit knapp 3 Std im Kreis. Als Hardware wird ein Atmega644P verwendet. Hier der Code: (Fragen stehen danach)
; ;Includes .include "PFAD/m644Pdef.inc" ;LEDs .EQU LED_1 = 6 .EQU LED_2 = 5 .EQU LED_3 = 4 ;Registernamen .def temp1 = r16 .def zeichen = r17 ;Berechnen der UBRR_VAL anhand der Baud und der CPU Frequenz .equ BAUD = 9600 .equ F_CPU = 19660800 .equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ;Interrupts .org 0x0000 ;Beginn des Programms (Bei Reset oder Power-Down) jmp MAIN .org 0x0004 jmp ISR_INT1 ;;;;;; ;MAIN; ;;;;;; MAIN: call INIT ldi zeichen, "b" call UARTOUT LOOP: ldi temp1, (1 << LED_1) | (1 << LED_2) | (1 << LED_3) out PORTD, temp1 jmp LOOP ;;;;;;;;;;; ;Interrupt; ;;;;;;;;;;; ISR_INT1: LOOP1: ldi temp1, (0 << LED_1) | (0 << LED_2) | (0 << LED_3) out PORTD, temp1 jmp LOOP1 reti UARTOUT: lds temp1, UCSR0A sbrs temp1, UDRE0 jmp UARTOUT sts UDR0, zeichen ret ;;;;;;;;;;;;;;;;; ;INITIALISIERUNG; ;;;;;;;;;;;;;;;;; INIT: ;PORT D ldi temp1, (1 << LED_1) | (1 << LED_2) | (1 << LED_3) out DDRD, temp1 out PORTD, temp1 ;UART Initiaisierung ldi temp1, (1 << RXEN0) | (1 << TXEN0) sts UCSR0B, temp1 ldi temp1, (1 << UCSZ00) | (1 << UCSZ01) sts UCSR0C, temp1 ;Baudrate festlegen ldi temp1, HIGH(UBRR_VAL) sts UBRR0H, temp1 ldi temp1, LOW(UBRR_VAL) sts UBRR0L, temp1 ;Pin Change Interrupt ldi temp1, 1 << PCIE2 sts PCICR, temp1 ldi temp1, (1 << PCINT16) | (1 << PCINT20) sts PCMSK2, temp1 ;Externe Interrupts ldi temp1, 1 << ISC11 sts EICRA, temp1 ldi temp1, 1 << INT1 sts EIMSK, temp1 ;Stack Initialisieren ldi temp1, LOW(RAMEND) out SPL, temp1 ldi temp1, HIGH(RAMEND) out SPH, temp1 sei ;Interrupts aktivieren ret |
1. Der Interrupt wird nicht ausgelöst. Mir ist wohl klar, dass es nicht sinnvoll ist den Controller in der ISR "gefangen" zu halten. Die Intention ist einfach die, dass die LEDs sichtbar angehen. Ich hab allerdings keine Erklärung dafür, die Interruptsregister sind gesetzt, die Globalen Interrupts aktiviert und die Einsprungadressen definiert. 2. Des Weiteren ist zu sehen, dass ein Zeichen ausgegeben wird, nachdem die Initiaisierung aufgerufen wurde. Dieses Zeichen gibt er aber nur dann aus, wenn Controller a) Programmiert wurde b) Aus/Eingeschalten wurde NICHT aber wenn der RESET Knopf betätigt wurde. Warum ? Alls Assembler wurde der gavrasm unter Linux verwendet. Der code wird fehlerfrei assembliert. Freue mich auf eure Hilfe Hochachtungsvoll Quantum
Datum:
Einen Call init zu machen und erst danach den Stack zu initialisieren ist keine gute Idee. Thomas
Datum:
Hi >ISR_INT1: >LOOP1: > ldi temp1, (0 << LED_1) | (0 << LED_2) | (0 << LED_3) > out PORTD, temp1 > jmp LOOP1 > reti Und wie soll der Controller hier wieder rauskommen? MfG Spess
Datum:
Thomas P. schrieb: > Einen Call init zu machen und erst danach den Stack zu initialisieren > ist keine gute Idee. > > Thomas Danke, dass löst schonmal das Problem mit dem Resettaster. spess53 schrieb: > Hi > >>ISR_INT1: >>LOOP1: >> ldi temp1, (0 << LED_1) | (0 << LED_2) | (0 << LED_3) >> out PORTD, temp1 >> jmp LOOP1 >> reti > > Und wie soll der Controller hier wieder rauskommen? > > MfG Spess Das ist rein zum Testen. Will erstmal dass er überhaupt reinspringt. Wenn er das dann tun sollte wird das mit sinnvollem Code belegt. Grüße
Datum:
wie hast du INT1 am Contoller beschaltet? es ist keine gute Idee den PCINT einzuschalten, aber keine entsprechende ISR zu haben - dann springt er dir u.U. irgendwo ins Programm rein. Am besten immer die komplette Interrupttabelle ins Program einbauen, und alle nicht benötigten ISR's mit RETI 'kurzschließen'! Sascha
Datum:
Sascha Weber schrieb: > wie hast du INT1 am Contoller beschaltet? > > es ist keine gute Idee den PCINT einzuschalten, aber keine entsprechende > ISR zu haben - dann springt er dir u.U. irgendwo ins Programm rein. > Am besten immer die komplette Interrupttabelle ins Program einbauen, und > alle nicht benötigten ISR's mit RETI 'kurzschließen'! > > Sascha Danke für deine Antwort Die ISR, die den PCINT2 abarbeitet ist implementiert. Übersichshalber hab ich den Code etwas gekürzt. Nach weiterem experimentieren ist mir aufgefallen, dass der PCINT16 Pin auf einen Interrupt anspricht. Der PCINT20 jedoch nicht. Bei beim INT1 Interrupt hat sich immer noch nichts getan. Der INT1 Pin ist mit nem PullUp und nem Taster beschalten, der den Pin dann auf Masse zieht. Gruß
Datum:
> UARTOUT: > lds temp1, UCSR0A > sbrs temp1, UDRE0 > jmp UARTOUT > sts UDR0, zeichen > ret sbrs templ,UDRE0 hmm hieß sbrs nicht "skip if bits in Register are set" und als operand dahinter eine Bitmaske ? also : sbrs templ,1<<UDRE0
Datum:
Hi >hmm hieß sbrs nicht "skip if bits in Register are set" und als operand >dahinter eine Bitmaske ? >also : sbrs templ,1<<UDRE0 Nein. MfG Spess
Datum:
Mark L. schrieb: > Quantum schrieb: >> Der >> PCINT20 jedoch nicht. > > JTAG aktiviert?? JTAG hab ich mithilfe den Fuses deaktiviert Uwe schrieb: >> UARTOUT: >> lds temp1, UCSR0A >> sbrs temp1, UDRE0 >> jmp UARTOUT >> sts UDR0, zeichen >> ret > > sbrs templ,UDRE0 > > hmm hieß sbrs nicht "skip if bits in Register are set" und als operand > dahinter eine Bitmaske ? > also : sbrs templ,1<<UDRE0 Wenn ich das so mache bringt mir der Assembler einen Fehler. Die Ausgabe funktioniert ja auch. Danke für die Hilfe Gruß
Datum:
Hab jetzt kurz ne kleine C Routine geschrieben, da funktionieren beide Interrupts tadellos. An dem Prozessor kann es also nicht liegen. Grüße
Datum:
Bist du sicher, dass kein Kurzschluss zwischen PD3 und PD4 ist? Du könntest auch mal einfach in der Hauptschleife den Taster abfragen und die LEDs ohne INT1 schalten. Ha, nochmal in's Datenblatt geschaut: Hab den Fehler! (glaub ich) sts EIMSK ist falsch, muss out EIMSK sein! Mark
Datum:
Mark L. schrieb: > Bist du sicher, dass kein Kurzschluss zwischen PD3 und PD4 ist? Du > könntest auch mal einfach in der Hauptschleife den Taster abfragen und > die LEDs ohne INT1 schalten. > > Ha, nochmal in's Datenblatt geschaut: Hab den Fehler! (glaub ich) > sts EIMSK ist falsch, muss out EIMSK sein! > > Mark Danke !! Es funktioniert :) Darf ich erfahren wie du das herausgefunden hast, bzw wo das steht. Was hat dieses Register mit den I/O Registern zu tun ? Oder hab ich das mit dem out falsch verstanden ? Das Problem mit dem Pin Chang Interrupt auf PCINT20 bleibt allerdings. PCINT16 funktioniert. Obwohl ich beide eingeschalten habe.
Datum:
Hi >Das Problem mit dem Pin Chang Interrupt auf PCINT20 bleibt allerdings. >PCINT16 funktioniert. Obwohl ich beide eingeschalten habe. Hast du die Frage Beitrag "Re: AVR Assembler Probleme/Fragen Interrupt" beachtet? MfG Spess
Datum:
spess53 schrieb: > Hi > >>Das Problem mit dem Pin Chang Interrupt auf PCINT20 bleibt allerdings. >>PCINT16 funktioniert. Obwohl ich beide eingeschalten habe. > > Hast du die Frage > > Beitrag "Re: AVR Assembler Probleme/Fragen Interrupt" > > beachtet? > > MfG Spess Wie ich schon geschrieben habe, ist JTAG abgeschaltet. Die ISR wird mit einem entsperechendem C Programm problemlos, an beiden Pins, aufgerufen
Datum:
Hi Außer deinem, jetzt unbekanntem, Programm und dem JTAG-Interface gibt es nichts, was den Interrupt verhindern könnte. MfG Spess
Datum:
Quantum schrieb: > Darf ich erfahren wie du das herausgefunden hast, bzw wo das steht. Was > hat dieses Register mit den I/O Registern zu tun ? Oder hab ich das mit > dem out falsch verstanden ? Das out geht für alle Register bis 0x5F Die Adresse ist bei out aber um 0x20 versetzt. Alles was mit out erreichbar ist, steht auch mit der out-Adresse in der *def.inc, daher führt sts zum Beschreiben eines falschen IO-Registers. Ist manchmal etwas nervig bei den Atmels, gibt immer wieder Unterschiede. Steht einmal in der *def.inc und im Datenblatt die IO-Register mit den doppelten Adressen. In kurzen Programmen sind das und die sbr/sbrs-Geschichte so Fehlerquellen, die man einfach nicht direkt sieht und die die Fehlersuche selbst in einem 20-Zeiler zur nervenaufreibenden Sache werden lassen. Mark
Datum:
Mark L. schrieb: > Das out geht für alle Register bis 0x5F Die Adresse ist bei out aber um > 0x20 versetzt. Alles was mit out erreichbar ist, steht auch mit der > out-Adresse in der *def.inc, daher führt sts zum Beschreiben eines > falschen IO-Registers. Ist manchmal etwas nervig bei den Atmels, gibt > immer wieder Unterschiede. IN, LD, LDI, LDD, LDS, MOV, OUT, ST, STD, STS ... und dann auch noch mit unterschiedlichen Adressen, je nach Befehl ... Manchmal habe ich den Eindruck, daß hier völlige Anfänger den Befehlssatz entworfen haben. Man könnte meinen, daß sie nicht mal den 8051 kannten. Dort gibt es einen Befehl für alle diese (und noch weitere) Aktionen: MOV Um den Rest kümmert sich der Kompiler. Und genau von dem erwarte ich diese Leistung! Wenn man ein Programm von einem AVR in einen anderen überträgt, kann es bei SFRs die dort an anderer Stelle hocken, passieren, daß man IN und OUT gegen LDS und STS tauschen muß. Es gibt nicht mal eine Meckermeldung vom Kompiler. Also muß ich von Hand heraussuchen, welches SFR nun in welchem Bereich sitzt. Da kann ich die Adresse auch gleich von Hand eintragen! *kopfschüttel** - Die Dinger sind eigentlich völliger Murks! Gruß Jobst
Datum:
Jobst M. schrieb: > Manchmal habe ich den Eindruck, daß hier völlige Anfänger den > Befehlssatz entworfen haben. Man könnte meinen, daß sie nicht mal den > 8051 kannten. Den gleichen Eindruck habe ich auch seit dem Umstieg an die AVRs. Im Gegensatz zum 51er ist der Befehlssatz aus Sicht eines Assemblerprogrammierers einfach Schrott. Thomas
Datum:
Angehängte Dateien:Hi >Den gleichen Eindruck habe ich auch seit dem Umstieg an die AVRs. Im >Gegensatz zum 51er ist der Befehlssatz aus Sicht eines >Assemblerprogrammierers einfach Schrott. Dann macht doch einen eigenen Thread dazu auf. Dort könnt ihr euren Frust in aller Ruhe ausdiskutieren. @Quantum (Gast) Im Anhang ein kurzer Test. Funktioniert problemlos. MfG Spess
Datum:
Mark L. schrieb: > Quantum schrieb: >> Darf ich erfahren wie du das herausgefunden hast, bzw wo das steht. Was >> hat dieses Register mit den I/O Registern zu tun ? Oder hab ich das mit >> dem out falsch verstanden ? > > Das out geht für alle Register bis 0x5F Die Adresse ist bei out aber um > 0x20 versetzt. Alles was mit out erreichbar ist, steht auch mit der > out-Adresse in der *def.inc, daher führt sts zum Beschreiben eines > falschen IO-Registers. Ist manchmal etwas nervig bei den Atmels, gibt > immer wieder Unterschiede. Steht einmal in der *def.inc und im > Datenblatt die IO-Register mit den doppelten Adressen. > > In kurzen Programmen sind das und die sbr/sbrs-Geschichte so > Fehlerquellen, die man einfach nicht direkt sieht und die die > Fehlersuche selbst in einem 20-Zeiler zur nervenaufreibenden Sache > werden lassen. > > Mark Danke, hab´s nun verstanden. In der *def.inc ist das sehr übersichtlich dargestellt. spess53 schrieb: > Hi > >>Den gleichen Eindruck habe ich auch seit dem Umstieg an die AVRs. Im >>Gegensatz zum 51er ist der Befehlssatz aus Sicht eines >>Assemblerprogrammierers einfach Schrott. > > Dann macht doch einen eigenen Thread dazu auf. Dort könnt ihr euren > Frust in aller Ruhe ausdiskutieren. > > @Quantum (Gast) > > Im Anhang ein kurzer Test. Funktioniert problemlos. > > MfG Spess Es funktioniert nun auch, lag an der externen Beschaltung. Ich bedanke mich bei allen Problemlösern. Habt mir wirklich sehr geholfen. Grüße
Datum:
man kann sich das Leben mit ein paar Macros einfacher machen z.B. für out
.macro out_ .if (@0 <= 63) out @0,@1 .else sts @0,@1 .endif .endmacro |
im Program dann einfach immer 'out_' schreiben, das Macro beutzt dann den richtigen Befehl. Sascha
Datum:
Ach was, die Macros werden erst nach der Adressumsetzung aufgerufen? So genau habe ich mich damit noch nie befasst ... Danke für den Hinweis. Ich glaube, ich werde mal einen kleinen Pre-Compiler schreiben und diesen dann hier veröffentlichen ... MOV, ich komme :-D Gruß Jobst
Datum:
Hi >Ich glaube, ich werde mal einen kleinen Pre-Compiler schreiben und >diesen dann hier veröffentlichen ... Meine Codegenerierung macht das schon seit Jahren richtig. MfG Spess