Forum: Compiler & IDEs [AVR] USART mit Interrupt (STK500/ATmega8515)


von Tobias H. (Gast)


Lesenswert?

Hallo, ich beschäftige mich schon seit ein paar Tagen mit dem ATmega8515 
auf dem STK500. Gestern und Heute stehen bei mir USART auf dem Plan.

Bei der Interrupt gesteuerten USART-Kommunikation ist irgendwie der Wurm 
drin.
1
#include <avr/io.h>
2
#include <avr/interrupt.h> 
3
#include <avr/delay.h>
4
5
#define LED_DDR         DDRB
6
#define LED_PORT        PORTB
7
#define LED0            0
8
#define LED1            1
9
#define LED2            2
10
#define LED3            3
11
#define LED4            4
12
#define LED5            5
13
#define LED6            6
14
#define LED7            7
15
#define ALL_LEDS    (1<<LED0|1<<LED1|1<<LED2|1<<LED3|1<<LED4|1<<LED5|1<<LED6|1<<LED7)
16
17
#define BAUD 9600      // for setbaud.h
18
#include <util/setbaud.h>    
19
20
void USART_init(void)
21
{
22
  UBRRH = UBRRH_VALUE;        
23
  UBRRL = UBRRL_VALUE;            
24
  UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);      // receive, transmit, receive interrupt enable
25
  UCSRC = (1<<URSEL)|(3<<UCSZ0);          // 8bit, no parity, 1 stop bit
26
}
27
28
int main(void)
29
{  
30
  LED_DDR = 0xff;
31
  LED_PORT = ALL_LEDS;
32
  
33
  cli();
34
  USART_init();          
35
  sei();
36
  
37
  while(1)
38
  {
39
    LED_PORT ^= ALL_LEDS;
40
    _delay_ms(250);
41
  }
42
}
43
44
ISR(USART_RX_vect)
45
{
46
   char temp;
47
   temp = UDR;    // Fetch value into the variable temp
48
   UDR = temp;    // Echo back to the computer 
49
}

Ziel ist ein simples Echo während die LEDs blinken.

Da ich gestern bereits eine Vorstufe (ohne Interrupt)zum laufen gebracht 
hatte, hab ich die Voreinstellungen übernommen und quasi nur den RXCIE 
dazu geschaltet und die ISR geschrieben.
Folgende Werte sind bei mir noch voreingestellt
F_CPU = 3686400
SUT_CKSEL "Ext. Crystal/Resonator High Freq.; Start-up time: 16K CK +64 
ms"
- Ich nutze also den Oszi vom STK500.
Könnt ihr einen Fehler erkennen? Muss man beim ATmega8515 irgendwas 
anders definieren als es im Datenblatt steht?

Danke schon mal im vorraus.
Tobias

von Hansi (Gast)


Lesenswert?

Es ist ungewöhnlich direkt in der RX-ISR wieder in das Datenregister zu 
schreiben. Deswegen kann ich nur vermuten, das hier einfach nur ein 
volatile fehlt. Andernfalls könnte der Compiler annehmen, das er sowieso 
nur in UDR schreibt was ohnehin schon drin steht und den ganzen Code 
rausoptimieren. Um das zu prüfen schau Dir mal den produzierten 
Assemblercode an.

von Tobias H. (Gast)


Lesenswert?

Hallo Hansi,

Hab gerade einfach mal die Optimierung auf -O0 gestellt (vorher -Os), 
dann sollte das ja eigentlich nicht passieren. Aber leider kein Erfolg. 
- Leider gibt es auch massenweise Tutorials die ähnlichen Code 
präsentieren.

Bin noch relativ neu im AVR Studio 5, weißt du wo ich einstellen kann 
das ich neben der .hex auch eine Assembler-Datei bekomme, dann schau ich 
da nochmal nach.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hansi schrieb:
> Es ist ungewöhnlich direkt in der RX-ISR wieder in das Datenregister zu
> schreiben.

Ungewöhnlich, aber OK.  Selbst
1
UDR = UDR;

muss funktionieren, so schräg es auch aussieht.

Da muss noch was anderes foul sein, der Code sieht OK aus.  Blinkt
die LED eigentlich (und blinkt sie mit der richtigen Frequenz)?

Der STK500-Oszillator ist aus Sicht des Controllers übrigens kein
externer Quarz, sondern ein externer Takt.  Das spielt aber keine
große Rolle, auch mit den von dir gewählten Fuse-Einstellungen muss
das mit externem Takt trotzdem klappen.

Das cli() am Anfang von main() kann übrigens raus: der Controller
kommt mit abgeschalteten Interrupts aus dem Reset.

von Hansi (Gast)


Lesenswert?

Jörg Wunsch schrieb:
>Ungewöhnlich, aber OK.

Das ist es (syntaktisch) unstreitig. Ich wollte nur den Wert meines 
Rates relativieren. Denn wenn es auch OK ist, so ist es doch 
ungewöhnlich; liegt jenseits meiner Erfahrung.
Meinst Du aber auch, das ein volatile nicht notwendig ist?
Jedenfalls ersetzt, denke ich, -O0 nicht volatile.


Mit AVRStudio 5 kenne ich mich nicht aus. Ich arbeite noch mit Version 
4. In dieser wird unter den "Project Options"->"General" die Erzeugung 
eines List-Files eingestellt. Ob das unter 5 noch so ist, weiss ich 
nicht.

von Tobias H. (Gast)


Lesenswert?

Nabend, die LEDs blinken auch nicht. Was das ganze noch komischer macht. 
Ich hab die USART_init() auch schon mal ausgeklamert um zu schauen ob 
sich überhaupt was tut... aber nichts. Lade ich einen anderen Code, der 
die USART(ohne RXCIE) direkt in der while-Schleife abhandelt 
funktioniert es wieder tadellos.

von Karl H. (kbuchegg)


Lesenswert?

Tobias H. schrieb:
> Nabend, die LEDs blinken auch nicht. Was das ganze noch komischer macht.
> Ich hab die USART_init() auch schon mal ausgeklamert um zu schauen ob
> sich überhaupt was tut... aber nichts.

Dann ist irgendwas anderes faul.
Bist du sicher, dass du das richtige HEX-File brennst?
Lach nicht, so wie das im AVR-Studio gemacht ist, kommt das schon mal 
vor.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Hansi schrieb:

> Meinst Du aber auch, das ein volatile nicht notwendig ist?

Ja.  Die SFRs selbst sind volatile, das genügt.

Beweis:
1
j@uriah 108% cat > foo.c
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
5
ISR(USART_RX_vect)
6
{
7
  UDR = UDR;
8
}
9
^D
10
j@uriah 109% avr-gcc -Os -mmcu=atmega8515 -S foo.c
11
j@uriah 110% cat foo.s
12
        .file   "foo.c"
13
__SREG__ = 0x3f
14
__SP_H__ = 0x3e
15
__SP_L__ = 0x3d
16
__CCP__  = 0x34
17
__tmp_reg__ = 0
18
__zero_reg__ = 1
19
        .text
20
.global __vector_9
21
        .type   __vector_9, @function
22
__vector_9:
23
        push __zero_reg__
24
        push r0
25
        in r0,__SREG__
26
        push r0
27
        clr __zero_reg__
28
        push r24
29
/* prologue: Signal */
30
/* frame size = 0 */
31
        in r24,44-32
32
        out 44-32,r24
33
/* epilogue start */
34
        pop r24
35
        pop r0
36
        out __SREG__,r0
37
        pop r0
38
        pop __zero_reg__
39
        reti
40
        .size   __vector_9, .-__vector_9

> Jedenfalls ersetzt, denke ich, -O0 nicht volatile.

"Ersetzen" ist ein schlechter Ausdruck: -O0 ist noch viel schlimmer
als volatile.

Tobias H. schrieb:
> Nabend, die LEDs blinken auch nicht. Was das ganze noch komischer macht.

Stimmt die -mmcu-Option denn beim Linken?  Überhaupt, passt -mmcu
zum benutzten Controller?

Klingt ein bisschen danach, als würde die Interruptvektortabelle
nicht zum Controller passen, sodass der aufgerufene Interrupt zu
einem Sprung auf Adresse 0 (Neustart) führt.

Blinkt die LED denn, solange noch niemand ein Zeichen auf der
UART eingibt?

von Tobias H. (Gast)


Lesenswert?

Guten Morgen,

ich hab heute einfach mal ein neues AVR-Projekt erstellt um ein neues 
makefile zu bekommen und das mal mit dem anderen zu vergleichen und 
siehe da einen Unterschied hab ich gefunden.

im alten makefile war unter der Linker-section diese Zeile zu finden:
1
$(QUOTE)$(AVR_APP_PATH)avr-gcc.exe$(QUOTE)  -mmcu=atmega8515   -o$(OUTPUT_FILE_PATH_AS_ARGS) $(OBJS_AS_ARGS) $(USER_OBJS) $(LIBS)
im neuen sah diese zeile dann so aus:
1
$(QUOTE)$(AVR_APP_PATH)avr-gcc.exe$(QUOTE)  -mmcu=atmega8515  -Wl,-Map=$(MAP_FILE_PATH_AS_ARGS) -o$(OUTPUT_FILE_PATH_AS_ARGS) $(OBJS_AS_ARGS) $(USER_OBJS) $(LIBS)

Also irgendwie ein paar Tags mehr, da ich darüber nicht soviel weiß 
schieb ich es erstmal auf die Tags, bis einer kommt der mir sagt das 
diese eigentlich keine Auswirkung haben.

Hab dann das "neue" Programm auf den µC gebrannt und siehe da: LEDs 
blinken und über die UART kommt auch was an und das sieht sogar genauso 
aus, wie das zuvor gesendete.

von Klaus W. (mfgkw)


Lesenswert?

Tobias H. schrieb:
> bis einer kommt der mir sagt das
> diese eigentlich keine Auswirkung haben.

bin schon da!

von Tobias H. (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> bin schon da!

hehe.

Also funktioniert jetzt alles und ich bastel gerade an nem Ringbuffer 
und co.

Vielen Dank für eure Hilfe.

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
Noch kein Account? Hier anmelden.