Forum: Mikrocontroller und Digitale Elektronik UART RX Interrupt Problem


von Christian W. (christianw92)


Lesenswert?

Hallo Zusammen,

ich bin gerade dabei ein bisschen mit UART herumzuspielen und habe mir 
ein kleines Programm geschrieben. Das senden funktioniert einwandfrei, 
aber wenn ich dem Controller per Terminalprogramm etwas sende, wird der 
uC angehalten, So als ob er in der Interruptrutine stecken bleibt. Habe 
ich was falsch gemacht?
Hier der Code:
1
#define F_CPU 16000000
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
#include <stdint.h>
6
#include <avr/interrupt.h>
7
8
9
uint8_t BAUD_Wert = 103;//Baudrate (9600)
10
uint8_t UART_Daten = 10;
11
12
ISR (UART_RXC_vect)
13
{
14
  UART_Daten = UDR0;
15
}
16
17
18
void AVR_Init (void)
19
{
20
  
21
  DDRD |= (1<<PB1);// PD1 als Ausgang (TXD)
22
  
23
}
24
25
26
void UART_Init (void)
27
{
28
  
29
  UBRR0 = BAUD_Wert;//Baudrate setzen
30
  UCSR0B |= (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0);// RX, TX und RX Interrupt aktivieren
31
  UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);// 8 Bit Paketgröße einstellen
32
  
33
}
34
35
36
37
38
int main(void)
39
{
40
    while(1)
41
    {
42
        AVR_Init;
43
        UART_Init();
44
        sei();//Interrupts aktivieren
45
        
46
        while(1)
47
        {
48
          
49
50
          while (!(UCSR0A & (1<<UDRE0))){}
51
          UDR0 = UART_Daten;
52
      _delay_ms(2000); 
53
    }  
54
    }
55
}

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christian W. schrieb:
> uint8_t BAUD_Wert = 103;//Baudrate (9600)
> uint8_t UART_Daten = 10;
>
> ISR (UART_RXC_vect)
> {
>   UART_Daten = UDR0;
> }

1
 volatile uint8_t UART_Daten = 10;

Christian W. schrieb:
> DDRD |= (1<<PB1);// PD1 als Ausgang (TXD)

 Wozu soll das gut sein ?

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

Die erste while-Schleife bei dir ist ziemlich sinnlos da sie durch die 
zweite while-Schleife eh nicht Kreise ziehen wird.

Die ISR kann man so machen, ist aber ziemlich witzlos.

Am besten schaust du dir hier auf der Seite mal das UART-Beispiel in C 
genauer an.

von Stefan F. (Gast)


Lesenswert?

>> DDRD |= (1<<PB1); // PD1 als Ausgang (TXD)
> Wozu soll das gut sein ?

Bei ATtiny und ATmega ist das nicht notwendig. Nur bei Xmega 
Controllern.

> aber wenn ich dem Controller per Terminalprogramm etwas sende,
> wird der uC angehalten

Du musst die Interrupts noch mit "sei()" freigeben. Ich denke, dein 
Programm bleibt in der Zeile "while (!(UCSR0A & (1<<UDRE0))){}" hängen, 
weil wegen gesperrter Interrupts das UDR register nicht frei wird.

von M. K. (sylaina)


Lesenswert?

Stefan U. schrieb:
> Du musst die Interrupts noch mit "sei()" freigeben.

Hat er doch drin. ;)

Christian W. schrieb:
> ...
>         sei();//Interrupts aktivieren
> ...

von Stefan F. (Gast)


Lesenswert?

>> Du musst die Interrupts noch mit "sei()" freigeben.
> Hat er doch drin. ;)

Oha, blinder geht nicht. Sorry.

von Stefan F. (Gast)


Lesenswert?

Probier mal, den RXCIE0 weg zu lassen und schau nach, ob das Programm 
dann immer noch stehen bleibt. Vielleicht bringt uns das der 
fehlerursache etwas näher.

Erstelle mal ein LST File, damit wir die Interrupt-Vektoren 
kontrollieren können.

von Christian W. (christianw92)


Lesenswert?

Hallo zusammen,

erstmal Danke für die Antworten.

1.
Marc V. schrieb:
> Christian W. schrieb:
>> DDRD |= (1<<PB1);// PD1 als Ausgang (TXD)
>
>  Wozu soll das gut sein ?

Ich hatte das mal irgendwo gelesen und dachte das braucht man.

2.
M. K. schrieb:
> Die erste while-Schleife bei dir ist ziemlich sinnlos da sie durch die
> zweite while-Schleife eh nicht Kreise ziehen wird.

Hab ich garnicht bemerkt. Ist mir anscheinend beim Kopieren aus meinem 
anderen Projekt passiert.

3.
M. K. schrieb:
> Die ISR kann man so machen, ist aber ziemlich witzlos.

Was ist daran denn falsch? Falls du meinst, weil sonst kein anderer Code 
ausgeführt wird, der kommt noch.

4.
Stefan U. schrieb:
> Probier mal, den RXCIE0 weg zu lassen und schau nach, ob das Programm
> dann immer noch stehen bleibt. Vielleicht bringt uns das der
> fehlerursache etwas näher.

Habe ich mal weggelassen. Das Programm bleibt nicht mehr stehen wenn 
etwas empfangen wird. Allerdings kann der uC nichts empfangen, weil ja 
der Interrupt deaktiviert ist.


Mein aktueller Code sieht so aus:
1
#define F_CPU 16000000
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
#include <stdint.h>
6
#include <avr/interrupt.h>
7
8
9
uint8_t BAUD_Wert = 103;//Baudrate (9600)
10
volatile uint8_t UART_Daten = 10;
11
12
ISR (USART_RX_vect)
13
{
14
  PORTB ^= (1<<PB5);
15
  UART_Daten = UDR0;
16
}
17
18
19
void UART_Init (void)
20
{
21
  
22
  UBRR0 = BAUD_Wert;//Baudrate setzen
23
  UCSR0B |= (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0);// RX, TX und RX Interrupt aktivieren
24
  UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);// 8 Bit Paketgröße einstellen
25
  
26
}
27
28
29
int main(void)
30
{
31
  
32
       DDRB |= (1<<PB5);
33
        UART_Init();
34
        sei();//Interrupts aktivieren
35
        PORTB |= (1<<PB5);
36
    
37
        while(1)
38
        {
39
          
40
          while (!(UCSR0A & (1<<UDRE0))){}
41
          UDR0 = UART_Daten;
42
      
43
      _delay_ms(2000); 
44
    }  
45
    
46
}

Anscheinend habe ich die ISR falsch geschrieben. ISR (USART_RX_vect). 
Bleibt zwar nicht mehr stehen, der Code in der ISR wird aber trotzdem 
nicht ausgeführt.
Ich habe jetzt noch einen LED toggle Befehl eingefügt um optisch sehen 
zu können was passiert. Es passiert aber nichts.

: Bearbeitet durch User
von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Welchen Controller verwendest Du?

Register wie z.B. "UDR0" klingen nach einem Controller mit mehreren 
UARTs. In diesem Fall würde ich aber für jeden UART einen eigenen 
Interruptvektor erwarten. "ISR (USART_RX_vect)" passt nach meinem 
Verständnis dann eher zu einem Controller mit nur einem UART.

von Christian W. (christianw92)


Lesenswert?

Ich verwende einen ATmega328, der auf einem Arduino Nano sitzt und den 
ich per XLoader flashe.
Der 328 hat nur einen UART.

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Christian W. schrieb:
> Ich verwende einen ATmega328, (...)
> Der 328 hat nur einen UART.

Und dein Compiler haut Dir keine Fehler um die Ohren? RESPEKT!

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Magnus M. schrieb:
> Register wie z.B. "UDR0" klingen nach einem Controller mit mehreren
> UARTs.

Magnus M. schrieb:
> Und dein Compiler haut Dir keine Fehler um die Ohren? RESPEKT!

Sorry, vergiss bitte den Quatsch, den ich da geschrieben habe. Liege 
schon im Bett und bin nur mit dem Smartphone online.

Habe es mittlerweile dann auch geschafft mir auf dem Smartphone das 
Datenblatt anzusehen und siehe da - deine Registerbezeichnungen scheinen 
korrekt zu sein...

Asche auf mein Haupt!

Ich leg das Smartscheißding jetzt beiseite und schlaf mal ein wenig.

Grüße
Magnus

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christian W. schrieb:
> Anscheinend habe ich die ISR falsch geschrieben. ISR (USART_RX_vect).
> Bleibt zwar nicht mehr stehen, der Code in der ISR wird aber trotzdem
> nicht ausgeführt.
> Ich habe jetzt noch einen LED toggle Befehl eingefügt um optisch sehen
> zu können was passiert. Es passiert aber nichts.

 Probiere zuerst mal ohne Echo bei dir:
1
 int main(void)
2
 {
3
    DDRB |= (1<<PB5);
4
    UART_Init();
5
    sei();//Interrupts aktivieren
6
    PORTB |= (1<<PB5);
7
    
8
    while(1)
9
        {
10
           UART_Daten += 1;
11
           _delay_ms(10); 
12
        }
13
  }
 Dein Programm muss ganz einfach die ISR ausführen.

 P.S.
 Falls auf der anderen Seite Echo eingeschaltet ist, ausschalten.

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

Christian W. schrieb:
> Was ist daran denn falsch? Falls du meinst, weil sonst kein anderer Code
> ausgeführt wird, der kommt noch.

witzlos != falsch. Witzlos ist es jedes empfangene Byte an den selben 
Speicher zu schreiben. Normalerweise schreibt man den in einen Loop 
rein, für gewöhnlich in eine Zeichenkette. Das ist schon das 
ungewöhnliche bei dir: Dein Speicher wo du das Byte reinschreibst ist 
kein char sondern ein int. Aber OK, es ist anscheinend nur zum testen.

Christian W. schrieb:
> void UART_Init (void)
> {
>
>   UBRR0 = BAUD_Wert;//Baudrate setzen
>   UCSR0B |= (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0);// RX, TX und RX
> Interrupt aktivieren
>   UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);// 8 Bit Paketgröße einstellen
>
> }

Beim Einstellen des UBRR0 empfiehlt es sich, zunächst das High-Byte zu 
setzen, dann das Low-Byte. Und BAUD_Wert sollte ein 16 bit Integer sein 
wobei man in dem Fall auch das High-Byte zunächst zu 0 setzen kann und 
BAUD_Wert dann ans Low-Byte übergibt. Es kann sonst sein, dass es nicht 
klappt. Geht denn das Senden sicher (was empfängst du wenn du eine 65 
sendest?). Möglicherweise hast du auch das Datenformat auf der 
Empfangsseite falsch eingestellt.
Paketgröße stellst du auf 8 Bit ein. Kann man machen, ist aber unnötig. 
8 Bit Paketgröße ist der Initialisierungswert. Genauer: 8N1 ist der 
Initialisierungswert des UART am Atmega328.
Und wie stehen die Fuses bei dir? Ist der Atmega auch richtig 
eingestellt sodass er mit 16 MHz läuft?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

M. K. schrieb:
> Beim Einstellen des UBRR0 empfiehlt es sich, zunächst das High-Byte zu
> setzen, dann das Low-Byte. Und BAUD_Wert sollte ein 16 bit Integer sein
> wobei man in dem Fall auch das High-Byte zunächst zu 0 setzen kann und
> BAUD_Wert dann ans Low-Byte übergibt. Es kann sonst sein, dass es nicht

 Glücklicherweise macht das der Compiler schon richtig. Aber man sollte
 trotzdem aufpassen bei solchen Sachen.

M. K. schrieb:
> Und wie stehen die Fuses bei dir? Ist der Atmega auch richtig
> eingestellt sodass er mit 16 MHz läuft?
Christian W. schrieb:
> Ich verwende einen ATmega328, der auf einem Arduino Nano sitzt und den
> ich per XLoader flashe.

 Das wird schon in Ordnung sein.
 Ich glaube eher, dass Echo sein Problem war.

von M. K. (sylaina)


Lesenswert?

Marc V. schrieb:
> Das wird schon in Ordnung sein.

Ist halt die Frage ob er einen Original Nano hat oder ein Clone. Bei den 
Clones hab ich es schon erlebt, dass die Megas nicht geflasht sind.

von Christian W. (christianw92)


Lesenswert?

M. K. schrieb:
> Ist halt die Frage ob er einen Original Nano hat oder ein Clone. Bei den
> Clones hab ich es schon erlebt, dass die Megas nicht geflasht sind.

Es ist ein Nano Nachbau. Wenn der atmega nicht geflasht wäre könnte ich 
ja kein Programm über den Com Port aufspielen.

Das Programm ist vorerst nur zu Test und Übungszwecken gedacht.


M. K. schrieb:
> Geht denn das Senden sicher (was empfängst du wenn du eine 65 sendest?).
> Möglicherweise hast du auch das Datenformat auf der Empfangsseite falsch
> eingestellt.

Ich benutze das Program hterm und das empfängt alles einwandfrei vom uC. 
Es funktioniert nur das empfangen am Atmega nicht.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christian W. schrieb:
> Ich benutze das Program hterm und das empfängt alles einwandfrei vom uC.
> Es funktioniert nur das empfangen am Atmega nicht.

 Doch, das tut es.

von Christian W. (christianw92)


Lesenswert?

Aktuell ja nicht. Der Code stoppt ja nicht mehr. Allerdings wird auch 
der Code in der ISR nicht ausgeführt.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Christian W. schrieb:
> Ich verwende einen ATmega328

Aha. Dann heisst dein ISR Vektor aber nicht richtig. Beim Mega328 muss 
der ISR Vektor
1
ISR(USART_RX_vect)
 heissen, wenn du die avr-libc benutzt. Den ganzen 'Du hast die Baudrate 
falsch' o.ä. kannst du in die Tonne kloppen, denn Senden geht ja 
korrekt. Ist vermutlich nur der falsche Vektorname.

Das ganze kannst du in der Online Doku zur avr-libc nachschauen:
http://nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

Den Vektor 'ISR (UART_RXC_vect)' gibt es nur bei ATmega16, ATmega32, 
ATmega323 und ATmega8.

von M. K. (sylaina)


Lesenswert?

Matthias S. schrieb:
> Beim Mega328 muss
> der ISR VektorISR(USART_RX_vect)
>  heissen

Und wie man oben lesen kann heißt er auch inzwischen

Christian W. schrieb:
> ISR (USART_RX_vect)

Darauf wurde nämlich schon hingewiesen.

Hab das Programm mal bei mir aufgespielt. Funktioniert. Ist denn auch 
sonst alles richtig angeschlossen? Hat alles vernünftigen Kontakt? 
Funktioniert der serielle Wandler?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christian W. schrieb:
> Aktuell ja nicht. Der Code stoppt ja nicht mehr. Allerdings wird auch
> der Code in der ISR nicht ausgeführt.

 Ziehe dein USB-Kabl aus PC raus, stecke es in irgendeine PowerBank
 oder ähnliches, verbinde Rx un Tx am Nano und lasse dein korrigiertes
 Programm (USART_RX_vect) laufen.
 Wetten, dass es geht ?

von Christian W. (christianw92)


Lesenswert?

Hallo zusammen,

ich habe jetzt mal den Code verändert. Das aktuelle Program funktioniert 
perfekt. Das heißt Senden und Empfangen geht.
1
int main(void)
2
{
3
  
4
       DDRB |= (1<<PB5);
5
        UART_Init();
6
    
7
        while(1)
8
        {
9
        
10
    while (!(UCSR0A & (1<<RXC0)));
11
    UART_Daten = UDR0;
12
    PORTB ^= (1<<PB5);
13
      
14
    while (!(UCSR0A & (1<<UDRE0))){}
15
    UDR0 = UART_Daten;
16
       
17
  }   
18
}



Ich würde aber gerne den Interrupt verwenden. Ich habe auch versucht die 
ganze main leer zu lassen und nur beim Empfangen etwas zu tun, also ohne 
echo, nur ein Pin Toggle. Aber das geht einfach nicht, aber warum.:

ISR (USART_RX_vect)
{
  PORTB ^= (1<<PB5);
  UART_Daten = UDR0;
}

von M. K. (sylaina)


Lesenswert?

Versuche mal folgenden Code (copy&paste)

Das funktioniert hier hervorragend.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
unsigned char empfang = 'A';
5
6
void uart_setup (uint16_t ubbr_value) {
7
  UBBR0 = ubbr_value >> 8;
8
  UBBR0 = ubbr_value & 0xff;
9
10
  UCSR0B |= (1 << TCEN0)|(1 << RXEN0)|(1 << RXCIE0);
11
}
12
void sendChar(unsigned char charToSend) {
13
  //Warten, dass der Sendespeicher frei wird.
14
  while( !(UCSR0A & (1 << UDRE0) );
15
  //Und Zeichen reinschieben zum Senden.
16
  UDR0 = charToSend;
17
}
18
19
int main(void) {
20
  //Initialisierungen/Einstellungen des AVR
21
  uart_setup( 103 );
22
  DDRB |= (1 << PB5);
23
  //interrupts ein.
24
  sei();
25
  //begin der Endlosschleife/ des Programms
26
  for(;;) {
27
    sendChar( empfang );
28
  }
29
  //hier kommt man nie hin
30
  return 0;
31
}
32
ISR ( USART_RX_vect ) {
33
  //Empfangenes Zeichen speichern
34
  empfang = UDR0;
35
  //Und Pin togglen
36
  PORTB ^= (1 << PB5);
37
}

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

M. K. schrieb:
> Das funktioniert hier hervorragend.

 Bestimmt nicht.
 Ohne überhaupt näher auf deinen Code einzugehen, aber UBBR0 gibt
 es bei AVR nicht - UBRR0 vielleicht ?
 Auch ist TCEN0 etwas fraglich - TXEN0 vielleicht ?

   while( !(UCSR0A & (1 << UDRE0) );
 Wieder mal an Klammern gespart ?

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Angehängte Dateien:

Lesenswert?

Christian W. schrieb:
> Ich würde aber gerne den Interrupt verwenden. Ich habe auch versucht die
> ganze main leer zu lassen und nur beim Empfangen etwas zu tun, also ohne
> echo, nur ein Pin Toggle. Aber das geht einfach nicht, aber warum.:

 Also, folgendes geht sicher:
1
#define F_CPU 16000000UL
2
#include <util/delay.h>
3
#include <stdlib.h>
4
#include <stdint.h>
5
6
#include <avr/io.h>
7
#include <avr/interrupt.h>
8
9
10
uint16_t BAUD_Wert = 103;                //Baudrate (9600)
11
volatile uint8_t UART_Daten = 10;
12
13
ISR (USART_RX_vect)
14
{
15
  PORTB ^= (1<<PB5);
16
  UART_Daten = UDR0;
17
}
18
19
20
void UART_Init (void)
21
{
22
  UBRR0 = BAUD_Wert;                                    //Baudrate setzen
23
  UCSR0B |= (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0);      // RX, TX und RX Interrupt aktivieren
24
  UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);                   // 8 Bit Paketgröße einstellen
25
}
26
27
28
int main(void)
29
{
30
  
31
     DDRB |= (1<<PB5);
32
     UART_Init();
33
     sei();                          //Interrupts aktivieren
34
     PORTB |= (1<<PB5);
35
    
36
     while(1)
37
     {
38
          
39
//          while (!(UCSR0A & (1<<UDRE0))){}
40
//          UDR0 = UART_Daten;
41
42
          _delay_ms(20); 
43
     }
44
    
45
}

 Beim Start muss die LED leuchten.

 EDIT:
 Jetzt ist auch die HEX-Datei dabei.
 Probieren und melden wie es geht, OK ?

: Bearbeitet durch User
von Christian W. (christianw92)


Lesenswert?

Inwiefern unterscheidet sich das von meinem Code. Die Baudrate wird bei 
mir korrekt eingestellt. Das Senden in der Endlosschleife habe ich auch 
schon weggelassen.
Bei mir Leuchtet die Led auch beim Start, nur wird der Code in der ISR 
nicht ausgeführt.
Ich werde dein Hex File dennoch ausprobieren.

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

> nur wird der Code in der ISR nicht ausgeführt.

sei() vergessen?

MfG Spess

von M. K. (sylaina)


Lesenswert?

Marc V. schrieb:
> Ohne überhaupt näher auf deinen Code einzugehen, aber UBBR0 gibt
>  es bei AVR nicht - UBRR0 vielleicht ?

Ja, hab ich aus dem Kopf getippt. Aber das funktioniert mit Sicherheit 
wenn die Rechtschreibfehler raus sind. Das garantiere ich.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
volatile unsigned char empfang = 'A';
5
6
void uart_setup (uint16_t ubrr_value) {
7
  UBRR0 = ubrr_value >> 8;
8
  UBRR0 = ubrr_value & 0xff;
9
10
  UCSR0B |= (1 << TXEN0)|(1 << RXEN0)|(1 << RXCIE0);
11
}
12
void sendChar(unsigned char charToSend) {
13
  //Warten, dass der Sendespeicher frei wird.
14
  while( !(UCSR0A & (1 << UDRE0)) );
15
  //Und Zeichen reinschieben zum Senden.
16
  UDR0 = charToSend;
17
}
18
19
int main(void) {
20
  //Initialisierungen/Einstellungen des AVR
21
  uart_setup( 103 );
22
  DDRB |= (1 << PB5);
23
  //interrupts ein.
24
  sei();
25
  //begin der Endlosschleife/ des Programms
26
  for(;;) {
27
    sendChar( empfang );
28
  }
29
  //hier kommt man nie hin
30
  return 0;
31
}
32
ISR ( USART_RX_vect ) {
33
  //Empfangenes Zeichen speichern
34
  empfang = UDR0;
35
  //Und Pin togglen
36
  PORTB ^= (1 << PB5);
37
}

spess53 schrieb:
> sei() vergessen?

Einfach mal den Thread lesen ;). Bist nicht der erste, der das meint und 
oben kann mans nachlesen, dass das sei() drin ist.

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christian W. schrieb:
> Inwiefern unterscheidet sich das von meinem Code.
 Dadurch, dass in der main() ein '_delay_ms(20);' steht.

> Das Senden in der Endlosschleife habe ich auch schon weggelassen.
 Gerade weil du (wahrscheinlich) eine leere Schleife in der main() hast,
 wird das Ganze vom Compiler wegoptimiert, dein Program landet beim
 <exit>, da wird dann ordentlich 'cli' ausgefuhrt und ein endloses
 'rjmp .-2'.
 Also, Interrupts sind gesperrt, da kannst du ewig warten, OK ?

 Probiere es doch mal endlich.

: Bearbeitet durch User
von Christian W. (christianw92)


Lesenswert?

Also das HEX File funktioniert.

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christian W. schrieb:
> Ist das Hex file auch für den Atmega328?

 Ja, probiere es doch.
 Oder paste mein Programm.
 Oder lese meine vorherige Post.

von M. K. (sylaina)


Lesenswert?

Marc V. schrieb:
> Gerade weil du (wahrscheinlich) eine leere Schleife in der main() hast,
>  wird das Ganze vom Compiler wegoptimiert, dein Program landet beim
>  <exit>, da wird dann ordentlich 'cli' ausgefuhrt und ein endloses
>  'rjmp .-2'.

Dann würde ich den Compiler aber wegwerfen. Der avr-gcc macht sowas mit 
Sicherheit nicht.

von Christian W. (christianw92)


Angehängte Dateien:

Lesenswert?

Also ich habe keine Ahnung warum aber mein Code funktioniert jetzt auch.

Hier der Code:
1
#define F_CPU 16000000
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <stdlib.h>
5
#include <stdint.h>
6
#include <avr/interrupt.h>
7
8
9
uint8_t BAUD_Wert = 103;//Baudrate (9600)
10
volatile uint8_t UART_Daten = 10;
11
12
13
ISR (USART_RX_vect)
14
{
15
  PORTB ^= (1<<PB5);
16
  UART_Daten = UDR0;
17
}
18
19
20
21
22
void UART_Init (void)
23
{
24
  
25
  UBRR0 = BAUD_Wert;//Baudrate setzen
26
  UCSR0B |= (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0);// RX, TX und RX Interrupt aktivieren
27
  UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);// 8 Bit Paketgröße einstellen
28
  
29
}
30
31
32
int main(void)
33
{
34
  
35
       DDRB |= (1<<PB5);
36
        UART_Init();
37
        sei();//Interrupts aktivieren
38
        PORTB |= (1<<PB5);
39
    
40
        while(1)
41
        {
42
          
43
44
         
45
  }  
46
    
47
}

Achja wegen der Baudrate: Warum Recourcen für ein 16 Bit Integer 
verschwenden wenn ein 8 Bit auch reicht.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

M. K. schrieb:
> Dann würde ich den Compiler aber wegwerfen. Der avr-gcc macht sowas mit
> Sicherheit nicht.

 Mit Sicherheit macht der das.
 Für Compiler ist eine leere Schleife nutzlos, nach der Schleife gibt
 es auch keine Befehle mehr, was soll der deiner Meinung nach tun ?
 Deswegen gibt es auch Optionen für Optimierung.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christian W. schrieb:
> Achja wegen der Baudrate: Warum Recourcen für ein 16 Bit Integer
> verschwenden wenn ein 8 Bit auch reicht.

 Aber nur weil sich der Compiler besser beim AVR auskennt als du.

von Christian W. (christianw92)


Lesenswert?

Marc V. schrieb:
> Aber nur weil sich der Compiler besser beim AVR auskennt als du.

Nein. Ich weiß das das Register 16 Bit groß ist. Ich habe es ausprobiert 
und es hat geklappt. Der Compiler benutzt immer erst das Low Byte.

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Marc V. schrieb:
> Mit Sicherheit macht der das.

 LOL.
 Nehme alles zurück.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christian W. schrieb:
> Marc V. schrieb:
>> Aber nur weil sich der Compiler besser beim AVR auskennt als du.
>
> Nein. Ich weiß das das Register 16 Bit groß ist. Ich habe es ausprobiert
> und es hat geklappt. Der Compiler benutzt immer erst das Low Byte.

 Seit wann hat ein uint8_t  auch ein High-Byte ?

von Christian W. (christianw92)


Lesenswert?

Nicht die Variable sondern das Register

: Bearbeitet durch User
von Carl D. (jcw2)


Lesenswert?

Marc V. schrieb:
> M. K. schrieb:
>> Dann würde ich den Compiler aber wegwerfen. Der avr-gcc macht sowas mit
>> Sicherheit nicht.
>
>  Mit Sicherheit macht der das.
>  Für Compiler ist eine leere Schleife nutzlos, nach der Schleife gibt
>  es auch keine Befehle mehr, was soll der deiner Meinung nach tun ?
>  Deswegen gibt es auch Optionen für Optimierung.

Optimierung soll einen funktionsidentischen Ersatz für das, was dasteht 
liefern. Ein Ersatz der Endlosschleife in main() durch ein return wäre 
KEIN solcher.
Wenn in der Schleife eine nicht-volatile Variable hochgezählt wird, die 
nirgends sonst benutzt wird, dann darf das weg. Nicht aber die Schleife 
selbst.
Zum Glück kennt sich der XYZ-GCC aber besser mit C* und Optimierung aus, 
als so manscher Poster hier.

von Christian W. (christianw92)


Lesenswert?

Mein Programm funktioniert ja mit leerer Schleife.

von Christian W. (christianw92)


Lesenswert?

Problem: gelöst. Ursache: keine Ahnung. Thread beendet.

von M. K. (sylaina)


Lesenswert?

Marc V. schrieb:
> Mit Sicherheit macht der das.
>  Für Compiler ist eine leere Schleife nutzlos, nach der Schleife gibt
>  es auch keine Befehle mehr, was soll der deiner Meinung nach tun ?
>  Deswegen gibt es auch Optionen für Optimierung.

Quatsch. Eine leere Schleife der Form
1
while(1){
2
}
wird der Compiler nicht weg optimieren da er nicht weiß was man damit 
bezwecken will und die Schleifenbedingung immer erfüllt ist. Er müsste 
dann auch sowas wie:
1
while(ADCSRA & (1 << ADSC));
oder, um beim obigen Beispiel zu bleiben
1
while( !(UCSR0A & (1 << UDRE0)) );
Das sind nämlich auch leere Schleifen. Das Einzige, was ein Compiler 
vielleicht wegoptimiert ist ein
1
while( 0 );
da diese Schleife nie ausgeführt werden wird.

von M. K. (sylaina)


Lesenswert?

Carl D. schrieb:
> Wenn in der Schleife eine nicht-volatile Variable hochgezählt wird, die
> nirgends sonst benutzt wird, dann darf das weg. Nicht aber die Schleife
> selbst.

Richtig, die Schleife selbst optimiert der gcc mit Sicherheit nicht weg.

Carl D. schrieb:
> Zum Glück kennt sich der XYZ-GCC aber besser mit C* und Optimierung aus,
> als so manscher Poster hier.

Das will ich mal schwer hoffen. Ich bin mir sicher, ich hätte sonst auch 
einige Probleme mehr. Ein Glück weis der gcc es besser als ich, deshalb 
überlasse auch ich ihm die Optimierungen.

von Carl D. (jcw2)


Lesenswert?

M. K. schrieb:
> Carl D. schrieb:
>> Wenn in der Schleife eine nicht-volatile Variable hochgezählt wird, die
>> nirgends sonst benutzt wird, dann darf das weg. Nicht aber die Schleife
>> selbst.
>
> Richtig, die Schleife selbst optimiert der gcc mit Sicherheit nicht weg.
>
> Carl D. schrieb:
>> Zum Glück kennt sich der XYZ-GCC aber besser mit C* und Optimierung aus,
>> als so manscher Poster hier.
>
> Das will ich mal schwer hoffen. Ich bin mir sicher, ich hätte sonst auch
> einige Probleme mehr. Ein Glück weis der gcc es besser als ich, deshalb
> überlasse auch ich ihm die Optimierungen.

Das ging nicht gegen dich, sondern gegen den Urheber dieser schrägen 
Vorstellung. Wie auch immer optimiert wird, es darf nie die Semantik 
eines Programms ändern.

von M. K. (sylaina)


Lesenswert?

Carl D. schrieb:
> Das ging nicht gegen dich

So hatte ich es auch nicht aufgefasst ;)

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.