Hallo! Hab mit meinem ATmega16 ein Problem mit der seriellen schnittstelle. Und zwar hab ich ein Programm vom AT90S4433 auf den mega angepasst nur läufts jetzt nicht. d.h. sobald der mega was über die serielle schnittstelle empfängt und ein entsprechender interrupt ausgelöst wird macht er nen neustart. allerdings hab ich auch noch festgestellt, dass die gleichen routinen und einstellungen funktionieren, wenn das programm ein bisschen kürzer ist. Was kann das jetzt sein? ist doch irgendwas an den einstellungen falsch? ist das Flash vom mega kaputt und es wird nicht richtig beschrieben? Hab es aber bis jetzt nur etwa 30 mal beschrieben. oder liegts vielleicht an irgendwelchen fuse bits? Danke Bernhard
>>Und zwar hab ich ein Programm vom AT90S4433 auf den mega angepasst >>nur läufts jetzt nicht. Das ist normal. Du mußt die geänderten Interrupt-Vektoren beachten und anpassen (richtige Include-Dateien) und nochmals genau kontrollieren.
das hab ich schon gemacht. wie gesagt, ein kleines testprogramm mit den selben interrupt-vektoren, include-datei und port-initialisierung läuft ja.
Hallo Bernhard, dein Problem liegt zu 99% an den Interruptvektoren: Vektor - adress (z.B.Mega8) - address (Mega16) 1 - 0x0000 - 0x0000 2 - 0x0001 - 0x0002 3 - 0x0002 - 0x0004 4 - 0x0003 - 0x0006 usw. d.h. beim Mega16 (und vermutlich allen größeren avrs) geht z.B. TX complete auf address 0x001A, bei den kleinen (z.B. Mega8) auf 0x000D, obwohl TX complete in beiden Fällen der Vektor No. 14 ist. Grüße leo
Hallo Leo! Das kann durchaus sein! Wie macht man dann am vernünftigsten für nen Mega16 die Interrupt-Vektor-Sprung-Tabelle. Ich habs bisher so: .org 0x00 rjmp anfang ; Reset reti ; Int0 reti ; Int1 usw. und so hauts ja anscheinend ned hin. also was ist besser? Danke Bernhard
>>Du mußt die geänderten Interrupt-Vektoren beachten und >>anpassen (richtige Include-Dateien) und nochmals genau >>kontrollieren. Mach es doch einfach einmal ! (Datenblatt)
Hi .org 0x00 rjmp anfang ; Reset reti ; Int0 reti Genau das ist das Problem. Das RETI ist ein Wort breit, der Abstand der Interruptvektoren ist aber zwei Worte, da dort gegebenenfalls ein CALL stehen muss, welches zwei Worte breit ist. So ist die ganze Interruptvektorentabelle Murks.
dann ist mir das auch klar. aber wie schreibt man dann jetzt die Interruptvektorentabelle auch formal richtig, dass da alles drin ist?
Danke an alle, jetz funktionierts so wie es soll! Ich hab die Tabelle jetz so gemacht: *** Sprungtabelle *** .org 0x00 rjmp anfang ; RESET .org 0x02 reti ; INT0 .org 0x04 reti ; INT1 .org 0x06 reti ; TIMER2 COMP usw. is zwar jetz ein bisschen unübersichtlich aber hauptsache es geht. oder hat jemand nen besseren vorschlag? Bernhard
Das kommt ganz einfach daher, dass man mit nem RJMP nicht mehr in den ganzen Speicher kommt, folglich muss in den Vektor ein JMP reinpassen. Wie wärs mit RETI + NOP oder einfach die Definitionen ausser Include nehmen? .org URXC0addr rjmp irgendwohin (aus der m161def.inc) .equ INT0addr =$002 ;External Interrupt0 Vector Address .equ INT1addr =$004 ;External Interrupt1 Vector Address .equ INT2addr =$006 ;External Interrupt1 Vector Address .equ CMP2addr =$008 ;Input Capture1 Interrupt Vector Address .equ OVF2addr =$00a ;Overflow1 Interrupt Vector Address .equ ICP1addr =$00c ;Input Capture1 Interrupt Vector Address .equ OC1Aaddr =$00e ;Output Compare1A Interrupt Vector Address .equ OC1Baddr =$010 ;Output Compare1B Interrupt Vector Address .equ OVF1addr =$012 ;Overflow1 Interrupt Vector Address .equ CMP0addr =$014 ;Overflow1 Interrupt Vector Address .equ OVF0addr =$016 ;Overflow0 Interrupt Vector Address .equ SPIaddr =$018 ;SPI Interrupt Vector Address .equ URXC0addr =$01a ;UART Receive Complete Interrupt Vector Address .equ URXC1addr =$01c ;UART Receive Complete Interrupt Vector Address .equ UDRE0addr =$01e ;UART Data Register Empty Interrupt Vector Address .equ UDRE1addr =$020 ;UART Data Register Empty Interrupt Vector Address .equ UTXC0addr =$022 ;UART Transmit Complete Interrupt Vector Address .equ UTXC1addr =$024 ;UART Transmit Complete Interrupt Vector Address .equ EERDYaddr =$026 ;UART Transmit Complete Interrupt Vector Address .equ ACIaddr =$028 ;Analog Comparator Interrupt Vector Address
Hi, schau mal ins AVR Tutorial unter Interrupts befindet sich die Mega8 Tabelle. Ich nutze diese und passe Sie nachdem Datenblatt an. Dirk
@dave: Danke! Hab leider die Include nicht, da ich gavrasm benutze. aber so schauts ganz gut aus. wie hat man das dann früher gemacht? da gabs ja auch schon avr mit großem speicher und da is ja dann auch nicht mit rjmp gegangen oder? @Dirk: die vom mega8 passt ja nicht und da is ja dann überhaupt erst mit den problemen angegangen. mfg Bernhard
Hallo Bernhard, im Prinzip hast du ja bereits eine Lösung. Ich füge halt für jedes "Sicherheits-reti" ein nop dazu: (hat auch den Vorteil dass undefinierte Int-Ansprünge (0x01,0x03,0x05 usw) einen definierten Programablauf haben. Wobei dieser Vorteil möglicherweise nur theoretischer Natur ist; ich habe keine Ahnung ob solche Sprünge in der Praxis durch irgendetwas ausgelöst werden. Und wenns nichts nutzt schaden tuts auf keinen Fall ;-) .org 0x00 rjmp reset.org 0x02 reti ; nicht benötigt nop reti ; auch unbenutzt nop rjmp int_prg ; INT1 reti ; und wieder unbenutzt nop ; usw. grüße leo
.org 0x00 rjmp reset ; 0 .org 0x02 reti ; 2 nop ; 3 reti ; 4 nop ; 5 rjmp int_prg ; 6 reti ; 7 nop ; 8 Bei der Methode würde ich aufpassen... hier wäre z.B. schon ein Vektor etwas verrutscht (wers nich sieht: nach der 6 fehlt ein NOP, denn 7 müsste ja auf die 8).
@dave: hast war, rjmps ( 1 word Speicherbedarf) durch calls ( 2 word breit) ersetzen und es passt oder halt besser aufpassen, in assembler sollte man sowieso immer wissen was man tut ;-) grüße leo9
@leo: In der Tat, bei Assembler sollte man wissen, was man tut ;) Mit nem call anstelle rjmp krachts garantiert. Die richtige Lösung gabs doch oben schon.
Hi thkais, stimmt natürlich. Da sollte nicht CALL stehen, sondern JMP (muss geträumt haben). Wichtig bleibt, dass der der Abstand zwei Worte ist, weil ein RJMP nicht den ganzen Speicher erreicht.
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.