Hallo, ich habe ein Problem mit dem USART_RX Interrupt beim ATmega128.
Der spingt nämlich immmer an den Anfang der main() zurück?
Ich sende Zeichen via RS232 die ich später verwenden will und wollte
diese zum Test dann erstmal zurückschicken. Kommt aber leider immer nur
mein Initialwert 00 zurück.
Die ISR von USART0_RX_vect springt also jedesmal zum Anfang der main()
zurück und somit ist meine frisch gespeicherte Variable auch futsch. Den
erhaltenen Wert gebe ich am PortD auf LEDs aus.
AVR-Studio in Version 4.14.
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<inttypes.h>
4
#include<stdio.h>
5
#ifndef F_CPU
6
#define F_CPU 14745600UL
7
#endif
8
#include<util/delay.h>
9
#define BAUD 115200UL
10
#define UBRR_BAUD (F_CPU/(16UL*BAUD))-1
11
12
volatileunsignedchartemp=0x00;
13
14
voiddelay_ms(uint16_tms)
15
{
16
for(;ms>0;ms--)_delay_ms(1);
17
}
18
19
voidUSART_Init(unsignedintubrr)
20
{
21
UBRR0H=(unsignedchar)(ubrr>>8);
22
UBRR0L=(unsignedchar)ubrr;
23
UCSR0B|=(1<<TXEN0)|(1<<RXEN0)|(1<<RXCIE0);
24
}
25
26
voidUSART_Transmit(unsignedchardata)
27
{
28
while(!(UCSR0A&(1<<UDRE0)));
29
UDR0=data;
30
}
31
32
intmain(void)
33
{
34
USART_Init(UBRR_BAUD);
35
36
DDRD=0xFF;//Bit0 Ausgang
37
PORTD|=(1<<PD0);//LED Test
38
delay_ms(500);
39
PORTD&=~(1<<PD0);
40
41
sei();
42
while(1)
43
{
44
PORTD=0x00;//LEDs aus
45
USART_Transmit(temp);
46
delay_ms(200);
47
}
48
}
49
50
ISR(USART0_RX_vect)
51
{
52
temp=UDR0;
53
PORTD=temp;
54
}
Kenn mich ´noch nicht so sehr aus und bin für jede Hilfe dankbar.
Was mach ich falsch???
(Hatte das auch schon mal zu einem anderen Beitrag geschrieben, aber da
hatte ich mich im Datum verguckt, da wird wohl niemand mehr antworten -
und sonst habe ich auch schon mal ähnliche Probleme durchgesucht, aber
nix passendes für mich gefunden)
ISR habe ich jetzt auch gesehen. Ich habe den üblicherweise in meinen
Sourcen ziemlich am Anfang und daher überlesen.
Ich kann deine Schlussfolgerung (Die ISR von USART0_RX_vect springt also
jedesmal zum Anfang der main() zurück ) nicht nachvollziehen.
Empfängst du auf dem AVR NIE ein anderes Zeichen als 0x00 per RX?
Sendest du auf dem AVR IMMER ein 0x00 per TX?
Empfängst du auf dem PC NIE ein anderes Zeichen als 0x00?
> Empfängst du auf dem AVR NIE ein anderes Zeichen als 0x00 per RX?
Doch natürlich, darum gehts ja. Ich sende Werte, die ich später
verwenden will.
> Sendest du auf dem AVR IMMER ein 0x00 per TX?
Genau das ist das Problem. Die Variable ändert sich nicht. Nur in der
ISR wo ich die Variable temp direkt auf dem Port ausgebe. Das klappt,
aber danach ist sie in der main() wieder 00.
> Empfängst du auf dem PC NIE ein anderes Zeichen als 0x00?
Somit also nicht, weil temp ja immer wieder genullt wird.
Das ganze passiert auch bei einem externen Interrupt. Hatte mal nen
Taster zum hochzählen. Da ist er auch immer zurück an den Anfang der
main() gesprungen und meine Variable war auf 00.
Patrick wrote:
> Vielleicht solltest Du in deiner Transmit funktion am Schluss noch> warten, bis die Daten weg sind.
Das bringt leider auch nix. Immer noch der Sprung zum Anfang.
Solche ähnlichen Probleme gabs doch schon öfters, dass die ISR immer an
den Anfang der Interrupt-Vector-Tabelle springt. Wieso macht die das?
Die erste Adresse da ist ja RESET.
Schöne SCH... sitz da jetzt schon ne Weile dran.
Ich nochmal...
was kommt denn vom Mikrocontroller über die RS232 zurück?
Ich vermute nämlich, dass das alles funktioniert, nur ist in der main
etwas, das wohl nicht so beabsichtigt ist.
Und zwar wird da der PortD zyklisch in der while-Schleife auf 0x00
gesetzt.
Mach das mal raus und schau mal ob deine Bytes aufm port angezeigt
werden:
> Doch natürlich, darum gehts ja. Ich sende Werte, die ich später> verwenden will.
Also du siehst definitiv mehrere LEDS (nicht nur PD0) an PORTD
zappeln, wenn du einen Haufen Zeichen vom PC zum AVR schickst. Nur der
AVR schickt nicht die Zeichen als Echo zurück, sondern auf dem PC
bekommst du immer nur 0x00 zurückgeliefert. Richtig von mir verstanden?
Du vermutest die auf dem PC empfangene 0x00 kommt daher, dass nach jedem
Zeichen, dass der AVR empfängt, beim Verlassen der ISR ein RESET
passiert und so beim nächsten Eintritt in die while-Schleife der
Defaultwert von temp (0x00, schonmal einen anderen Wert probiert?)
gesendet wird.
> Solche ähnlichen Probleme gabs doch schon öfters, dass die ISR immer an> den Anfang der Interrupt-Vector-Tabelle springt. Wieso macht die das?> Die erste Adresse da ist ja RESET.
Dieser Spekulation mag ich nicht folgen. Kannst du das mit dem RESET
belegen - blitzt PORTD typisch mit PD0 einmal mit 0.5s Dauer auf?
Ich nehme eher an, dass kein RESET passiert und eine andere
Fehlerursache vorliegt, z.B. eine Nichtbeachtung des notwendigen
volatile
Um auszuschliessen, dass du mit einer alten Version deiner Source
arbeitest (nämlich einer ohne volatile), würde ich mal vor dem
Flashen/Ausprobieren die Source speichern, alle automatisch erzeugten
Dateien löschen (make clean) und ein Rebuild All durchführen.
Und kannst du mal das frisch erzeugte Assemblerlisting (*.LSS) zeigen?
In dem kann man nachforschen, ob der Compiler temp korrekt als
volatile behandelt und entsprechenden Code erzeugt. Bitte gib auch an,
welche Version der Toolchain du benutzt. Eventuell braucht man zum
Nachvollziehen des Problems auch das Makefile oder die Projektdatei.
BTW. deine Debugausgabe ist IMHO zu leicht zu verwechseln mit der
Debugausgabe PORTD = temp aus der ISR bei jedem empfangenen Zeichen. Ich
würde beim RESET/Init vor dem While was anderes programmieren, öfter
oder charakteristischer oder an einem anderen Port blinken.
ADD: Und checke auch mal die Einstellung der Fuses. Nicht dass du den
watchdog scharf geschaltet hast...
Hi Stefan,
ja alles richtig verstanden. Meine Zahl wird wirklich immer in der ISR
korrekt am Port angezeigt, und auch wenn PD0 nicht soll blinkt sie
trotzdem JEDESMAL für 0.5 sek auf (so stehts ja am Anfang der main() und
daher bin ich recht sicher, dass er immer dorthin springt).
Ich habe auch schonmal einen anderen Initialwert probiert, aber das ist
das gleiche Problem, dann kommt eben immer der und nicht der neue.
Das volatile habe ich von Anfang an drin gehabt und das ganze auch schon
oft mit make clean und Rebuild all durchgeführt um solche Fehler zu
vermeiden.
> Und kannst du mal das frisch erzeugte Assemblerlisting (*.LSS) zeigen?
Das mach ich morgen früh gleich mal. Hab die Umgebung + Hardware nicht
zu hause.
> ADD: Und checke auch mal die Einstellung der Fuses. Nicht dass du den> watchdog scharf geschaltet hast...
Okay...das sagt mir gerade mal gar nichts aber dazu les ich dann mal fix
im Tutorial und morgen früh gibts dann was dazu.
@bennigotchi
Das ist bloß wieder zum Ausschalten der LEDs, die werden in der ISR
richtig angezeigt und gehen dann planmäßig aus. Ich speicher das ja in
temp und auch nur das wird gesendet, also sollte es egal sein, was der
PORTD dabei macht.
Danke für eure Hilfe...hoffe ich kriegs irgendwann zum laufen. Ist ja
eigenlich ne elementare einfache Sache - theoretisch. :-)
Beim Überprüfen der Fuses bitte auch auf die M103C Fuse achten.
Nicht dass du den Atmega128 physikalisch als Atmega103-Kompatiblen
vorliegen hast (M103C fuse ist ab Werk gesetzt!) und versuchst den mit
Atmega128 Register/Vektoradressen in der avr/io.h anzusprechen.
Wenn die kleinen Funktionen (USART_Init) vom Compiler als inline
Funktionen übersetzt werden, crasht es beim ersten Senden (oder nicht
falls inline) und garantiert beim ISR. Mehr kann man im *.LSS File
sehen.
s. auch AVR Fuses und
http://www.mikrocontroller.net/articles/AVR_Checkliste#Besonderheiten_bei_ATmega64_.2F_ATmega128
> Beim Überprüfen der Fuses bitte auch auf die M103C Fuse achten.
Das war ein guter Tip, jetzt bin ich happy und kann endlich richtig
loslegen. Da wäre ich alleine nicht drauf gekommen, wusste nicht, was
dieses Fuse-Bit bedeutet.
War das erste was ich heut morgen probiert habe und sofort hats
funktioniert.
Danke, jetzt weiß ich ja an wen ich mich mit Problemen wenden kann. ;-)
Schönes Wochenende!!!