Hallo,
jetzt probier ich schon seit einigen Stunden Daten mittels dem
USART0_RX_vect Interrupt zu empfangen, aber aus irgendeinen Grund wird
die ISR anscheinend nie aufgerufen.
Daten Senden mittels USART0_UDRE_vect funktioniert ohne Probleme. Daten
empfangen mittel Polling ebenfalls.
Hier mal der vereinfachte Code der nur überprüft ob die ISR aufgerufen
wird.
Wenn ja, dann sollten sich 4 LEDs die am PortC hängen einschalten. Nach
spätestens 4 sek sollen sich die LEDs aber auf jedenfall einschalten.
Und da passiert jetzt was seltsames: Wenn ich im Hyperterminal nichts
eingebe werden die LEDs nach 4 sekunden eingeschalten, aber wenn ich
Daten sende, dann scheint das Programm abzustürzen, weil dann garnichts
mehr passiert.
1
...
2
3
voiduart_init()
4
{
5
uint8_tsreg=SREG;
6
7
UBRR0H=UBRR_VAL>>8;
8
UBRR0L=UBRR_VAL&0xFF;
9
10
// Interrupts kurz deaktivieren
11
cli();
12
13
// UART Receiver und Transmitter anschalten, Receive Interrupt setzen
// Rücksetzen von Receive und Transmit Complete-Flags
28
UCSR0A=(1<<RXC0)|(1<<TXC0);
29
30
// Global Interrupt-Flag wieder herstellen
31
SREG=sreg;
32
}
33
34
ISR(USART0_RX_vect)
35
{
36
uint8_tsreg=SREG;
37
cli();
38
39
// LEDS einschalten
40
DDRC=0xFF;
41
PORTC=0b11110000;
42
43
UDR0;
44
45
SREG=sreg;
46
}
47
48
intmain(void)
49
{
50
sei();
51
52
uart_init();
53
54
// Nach 4 Sekunden sollen die LEDs auf jedenfall eingeschalten werden
55
for(inti=0;i<4000;i++)
56
_delay_ms(1);
57
58
DDRC=0xFF;
59
PORTC=0b11110000;
60
while(1);
61
62
return0;
63
}
Sieht hier jemand einen Fehler? Kann das irgendwie mit AT103
Kompatibilitätsmodus zusammenhängen? Oder liegts vielleicht sogar am
Bootloader?.
Danke schon mal im vorraus,
Thomas
Was soll das cli() im Interrupt Handler? Das ist unsinnig, weil die
Hardware das automatisch macht. Auch vom SREG sollte man als
Hochsprachen-Programmierer weitgehend die Finger lassen!
BTW: Das RXC-Flag ist Read-Only. Das kann man mit
> UCSR0A = (1 << RXC0) | (1 << TXC0);
nicht löschen.
Außerdem: Was soll diese Abfrage bewirken:
> while (UCSR0A & (1 << RXC0));
>BTW: Das RXC-Flag ist Read-Only. Das kann man mit>> UCSR0A = (1 << RXC0) | (1 << TXC0);>nicht löschen.
Ah ok, hab das von irgendeinem Musterbeispiel kopiert.
>Außerdem: Was soll diese Abfrage bewirken:>> while (UCSR0A & (1 << RXC0));
Hab ich ebenfalls kopiert. Die Schleife läuft halt solangen das Receive
Complete Flag gesetzt ist und liest solange UDR0 aus.
Weglassen der beiden Programmteile ändert leider auch nichts.
Meinst nicht das der Bootloader vielleicht an dem Problem schuld sein
kann? Oder irgendeine Fuse?
Thomas wrote:
>>Außerdem: Was soll diese Abfrage bewirken:>>> while (UCSR0A & (1 << RXC0));>> Hab ich ebenfalls kopiert. Die Schleife läuft halt solangen das Receive> Complete Flag gesetzt ist und liest solange UDR0 aus.
Die Schleife liest außer UCSR0A überhaupt nichts aus...
Thomas wrote:
> Hab ich ebenfalls kopiert. Die Schleife läuft halt solangen das Receive> Complete Flag gesetzt ist und liest solange UDR0 aus.
Genau genommen, liest sie UDR0 immer mindestens 1mal aus.
Stefan Ernst wrote:
> Johannes M. wrote:>>> Die Schleife liest außer UCSR0A überhaupt nichts aus...>> Schau nochmal hin und beachte den do-Block davor.
Yep, hast natürlich Recht. Oben ging es mir nur um die Abfrage an sich,
hab dann beim Weiterkopieren den Kontext nicht mehr mitgeschleppt...
Allerdings habe ich auf den zweiten Blick auch gesehen, dass die
Schleife und die Abfrage doch für was gut sind...
> Schon möglich.
Komisch ist dabei, dass das die USART0_UDRE_vect Interrupt funktioniert
und ich auch sonst noche keine Probleme hatte.
> Hast du denn die M103 Fuse verändert?
Nein, ich hab programmiere nur per USB. Siehe
Beitrag "Programmvorstellung "CCPro-Loader" - natives C (ohne Interpreter) auf der C-Control Pro"
Mittels einem Programm was auf den MC läuft kann man die Fuses sicher
nicht rücksetzen, oder? Würde dabei eigentlich auch der Bootloader
entfernt werden? Ich nehm mal an schon, sonst könnte man den Lese-Fuse
ja ganz einfach umgehen.
Thomas wrote:
> Komisch ist dabei, dass das die USART0_UDRE_vect Interrupt funktioniert> und ich auch sonst noche keine Probleme hatte.
Das wäre allerdings ein Indiz, dass die 103 Fuse richtig steht.
Steht die falsch, geht bereits der erste Funktionsaufruf in die Hose.
Bei deinen eigenen Funktionen könnte der Compiler per inline den
Funktionsaufruf überflüssig gemacht haben. Aber bei einer ISR muss ein
Aufruf erfolgen.
>> Hast du denn die M103 Fuse verändert?> Nein, ich hab programmiere nur per USB. Siehe
LOL. Das hat damit nicht das geringste zu tun.
Die 103 Fuse sorgt dafür, dass sich ein Mega128 wie ein Mega103 verhält.
Blöderweise ist die per Default im Auslieferungszustand des Prozessors
aktiviert.
>>> Hast du denn die M103 Fuse verändert?>> Nein, ich hab programmiere nur per USB. Siehe>LOL. Das hat damit nicht das geringste zu tun.
Wie soll ich den die Fuses verändert haben? Ich verwende weder ISP noch
JTAG.
>Die 103 Fuse sorgt dafür, dass sich ein Mega128 wie ein Mega103 verhält.
Schon klar...
Die normale, übliche und auch logisch nachvollziehbare Reihenfolge ist
doch wohl: zuerst alles einstellen und erst dann die Interrupts
freigeben. Und nicht umgekehrt.
>Dreh hier auch mal die Reihenfolge um:
Danke für den Tipp, zumindest schalten sich die LEDs jetzt nach 4
sekunden wieder ein. Aber auf eine gesendetes Zeichen wird noch immer
nicht reagiert.
> Die Fuse fällt als mögliche Fehlerquelle also definitiv raus.
Hab ich mir auch schon gedacht. Dann kanns doch eigentlich nurmehr am
Bootloader liegen, oder?
Thomas wrote:
>>Dreh hier auch mal die Reihenfolge um:>> Danke für den Tipp, zumindest schalten sich die LEDs jetzt nach 4> sekunden wieder ein. Aber auf eine gesendetes Zeichen wird noch immer> nicht reagiert.
Wie sieht dann das aktuell im µC laufende Programm jetzt aus?
Es hat sich übrigens noch was geändert. Interessanterweise werden die
LEDs erst 4 sekunden nach dem ich das letztes Zeichen im Hyperterminal
eingegeben habe eingeschalten. Irgendwie scheint der MC doch auf das
Interrupt zu reagieren.
Hier ist der aktuell Code:
Du bekommst nicht zufällig eine "return type defaults to 'int'"-Warnung
für die ISR, oder?
Wenn ja, dann:
1)
"#include <avr/interrupt.h>" einfügen.
2)
Warum ignorierst du Warnungen, oder postest sie nicht zumindest?
>Du bekommst nicht zufällig eine "return type defaults to 'int'"-Warnung>für die ISR, oder?
Nein, bekomm ich nicht, außer ich verwende SIGNAL statt ISR
> Richtiger µC-Typ ist auch ganz sicher ausgewählt?
Das ist gar nicht so einfach zu beantworten. Laut beigelegten Datasheet
ist da ein AT90CAN128 drinnen. Wenn ich den auswähle startet aber gar
kein Programm mehr.
Mit normalen Atmega128 hat bis auf das eine Interrupt jetzt alles
funktioniert.
> Ansonsten hätte ich keine Idee mehr.
Trotzdem danke für deine Mühe.
> Warum versucht man eigentlich Jemandem zu helfen, der sich beharrlich> weigert, den ganzen Code zu posten?
He mal ruhig Blut, ich wollte nur nicht den Thread zumüllen und den Code
auf die wichtigsten Teile beschränken. Keiner liest sich gerne durch zig
Zeilen trivialen Code.
Aber bitte sehr:
Thomas wrote:
>> Richtiger µC-Typ ist auch ganz sicher ausgewählt?> Das ist gar nicht so einfach zu beantworten. Laut beigelegten Datasheet> ist da ein AT90CAN128 drinnen. Wenn ich den auswähle startet aber gar> kein Programm mehr.
Also du musst schon genau wissen, welchen µC du da eigentlich
programmierst. Bei AT90CAN128 und ATmega128 liegt der
USART-RXC-Interrupt z.B. auf unterschiedlichen Vektoren. Und wenn der
Vektor nicht stimmt, wird halt nach 0 gesprungen, das Programm also neu
gestartet (was du ja auch beobachtet hast).
Wieso eigentlich CAN? War nicht von USB die Rede? Ist es nicht
vielleicht doch ein AT90USB128?
Thomas wrote:
> He mal ruhig Blut, ich wollte nur nicht den Thread zumüllen und den Code> auf die wichtigsten Teile beschränken. Keiner liest sich gerne durch zig> Zeilen trivialen Code.
Keiner liest sich aber auch durch 25 Postings mit jeweils einem
nichtssagenden Code Schnipsel, nur um den Rest zu erraten.
> Also du musst schon genau wissen, welchen µC du da eigentlich> programmierst. Bei AT90CAN128 und ATmega128 liegt der> USART-RCX-Interrupt z.B. auf unterschiedlichen Vektoren.
Hab im Datenblatt schon nachgesehen, wenn es wirklich ein AT90CAN128
wäre, würde auch USART0_UDRE_vect nicht funktionieren.
>Wieso eigentlich CAN? War nicht von USB die Rede? Ist es nicht>vielleicht doch ein AT90USB128?
Hab nur gesagt, dass ich das Programm per USB und integrierten
Bootloader raufspiele. Sry, hätt noch dazusagen soll, dass in dem
Programmierkabel ein Rs232 Wandler drinnen ist. Es wird also eigentlich
über UART programmiert.
>Grrrrrrrrr Lass endlich das SREG in Ruhe!
Sry, habs von der ISR raus, aber im Init noch vergessen.
Ändert aber auch nichts.
Thomas wrote:
>> Also du musst schon genau wissen, welchen µC du da eigentlich>> programmierst. Bei AT90CAN128 und ATmega128 liegt der>> USART-RCX-Interrupt z.B. auf unterschiedlichen Vektoren.>> Hab im Datenblatt schon nachgesehen, wenn es wirklich ein AT90CAN128> wäre, würde auch USART0_UDRE_vect nicht funktionieren.
Im Zweifel: Gerät aufschrauben - nachsehen
> Keiner liest sich aber auch durch 25 Postings mit jeweils einem> nichtssagenden Code Schnipsel, nur um den Rest zu erraten.
Dieser nichtsagende Teil ist jener der nicht funktioniert. Und wenn man
noch Information braucht, kann man nachfragen und muss nicht
herummotzen.
Nachdem ich jetzt alle ISR's durchprobiert habe (auch BADISR_vect) und
noch mal das Datenblatt studiert habe, gehe ich davon aus, dass Conrad
das IVSEL Bit aktiviert hat, was bedeuted, dass die Interrupts in den
Bootloader-Bereich abgelenkt werden. Da kann ich wohl nichts dagegen
machen.
Danke noch mal alle die mitgeholfen haben.
So so, und was ist dann damit:
> Komisch ist dabei, dass das die USART0_UDRE_vect Interrupt funktioniert
?
(ganz davon abgesehen, dass man das Bit auch wieder löschen könnte)
>So so, und was ist dann damit:>> Komisch ist dabei, dass das die USART0_UDRE_vect Interrupt funktioniert
Ich nehme an, dass bestimmte Interrupts vom Bootloader wieder umgeleitet
werden.
> (ganz davon abgesehen, dass man das Bit auch wieder löschen könnte)
Ohne ISP oder JTAG? Echt? Wie?
Thomas wrote:
> Ich nehme an, dass bestimmte Interrupts vom Bootloader wieder umgeleitet> werden.
Ja stimmt, die unbenutzten könnten auf die "unteren" Vektoren
weiterleiten.
>> (ganz davon abgesehen, dass man das Bit auch wieder löschen könnte)> Ohne ISP oder JTAG? Echt? Wie?
Das ist keine Fuse. Das ist ein "normales" Bit, das zur Laufzeit
modifiziert wird.
Datenblatt:
1
• Bit 1 – IVSEL: Interrupt Vector Select
2
When the IVSEL bit is cleared (zero), the interrupt vectors are placed at the start of the Flash
3
memory. When this bit is set (one), the interrupt vectors are moved to the beginning of the Boot
4
Loader section of the flash. The actual address of the start of the Boot Flash section is determined
5
by the BOOTSZ fuses. Refer to the section “Boot Loader Support – Read-While-Write
6
Self-Programming” on page 273 for details. To avoid unintentional changes of interrupt vector
7
tables, a special write procedure must be followed to change the IVSEL bit:
8
1. Write the Interrupt Vector Change Enable (IVCE) bit to one.
9
2. Within four cycles, write the desired value to IVSEL while writing a zero to IVCE.
10
Interrupts will automatically be disabled while this sequence is executed. Interrupts are disabled
11
in the cycle IVCE is set, and they remain disabled until after the instruction following the write to
12
IVSEL. If IVSEL is not written, interrupts remain disabled for four cycles. The I-bit in the Status
13
Register is unaffected by the automatic disabling.
>Das ist keine Fuse. Das ist ein "normales" Bit, das zur Laufzeit>modifiziert wird.
Ah danke hab ich auch gerade gesehen.
Der Aufruf von:
MCUCR = (1<<IVCE);
MCUCR &= ~(1<<IVSEL);
vor dem Programmstart hat allerdings nichts gebracht. Der Fehler muss
wohl doch woanders liegen. Komisch hab echt alle ISRs durchprobiert.