Forum: Mikrocontroller und Digitale Elektronik Usart verursacht Reset bei Rücksprung


von Bruno I. (bjnas)


Lesenswert?

Schönen Abend,

Der einfach Code unten macht mich Wahnsinnig, die USART0_Senden() 
Funktion geht einwandfrei. Warum er mit USART_Str("Hallo") die Hallo 
zwar ausgibt, aber dann einen Reset verursacht begreife ich nicht. Als 
könnte das Programm nicht aus der USART_Str() zurückspringen?

Nutze einen Atmega128A mit einem USB-Serial Kontroller.

Irgendwo muss der Hund sein.

1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
#ifndef F_CPU
5
#define F_CPU 8000000UL  // Systemtakt in Hz - Definition als unsigned long beachten 
6
#endif
7
 
8
#define BAUD 9600UL      // Baudrate, muss in Hterm gleich eingestellt sein.
9
 
10
// Berechnungen
11
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
12
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
13
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)      // Fehler in Promille, 1000 = kein Fehler.
14
 
15
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
16
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
17
#endif
18
19
void USART0_Init( void );
20
void USART0_Senden( unsigned char z);
21
void USART_Str(const char *s);
22
unsigned char USART0_Receive( void );
23
24
int main(void){
25
     unsigned char tmp=0;
26
27
   DDRB = 0xff;
28
   PORTB = 0x00;
29
   _delay_ms(100);
30
         USART0_Init(); 
31
     
32
    USART0_Senden('B');
33
   USART0_Senden('J');
34
   USART0_Senden('N');
35
   USART0_Senden('\n');  
36
   _delay_ms(1000);     
37
   USART_Str("Hallo");
38
   while(1){
39
     PORTB = 0xff;
40
       if(UCSR0A & (1<<RXC0)) 
41
       {
42
         tmp=USART0_Receive();
43
         USART0_Senden(tmp);
44
       } 
45
         }
46
   return 0;
47
}
48
49
void USART0_Init(){                              
50
     UCSR0B = (1<<RXEN0)|(1<<TXEN0);
51
     UCSR0C = (1<<UCSZ00)|(1<<UCSZ01);
52
     UBRR0H = UBRR_VAL >> 8; 
53
     UBRR0L = UBRR_VAL & 0x0FF;
54
}
55
56
57
unsigned char USART0_Receive(){    
58
     while ( !(UCSR0A & (1<<RXC0)) );
59
    
60
     return UDR0;
61
} 
62
63
64
void USART_Str (const char *s){ 
65
   while ( !(UCSR0A & (1<<UDRE0)));   //Warten bis UDR leer ist für Senden
66
67
   while (*s){ 
68
      USART0_Senden(*s);         //Zeichen senden 
69
      s++;                    //Adresse erhöhen 
70
   }    
71
} 
72
73
void USART0_Senden( unsigned char z ){
74
    
75
     while ( !( UCSR0A & (1<<UDRE0)) );
76
    
77
     UDR0 = z;
78
}

von Bernd R. (Firma: Promaxx.net) (bigwumpus)


Lesenswert?

Müssen in C die Unterprogramme immer noch mit "return" beendet werden ?

von Bruno I. (bjnas)


Lesenswert?

Könnte ich mal versuchen, auf dem Atmega8 läuft das trotzdem fehlerfrei.

von Jim M. (turboj)


Lesenswert?

> Müssen in C die Unterprogramme immer noch mit "return" beendet werden ?

Nicht wenn sie als "void" deklariert sind.

von Thomas B. (nichtessbar)


Lesenswert?

_delay_ms(1000);

Dir ist klar dass das nicht hinhaut? Die Delayfunktionen funktionieren 
nur bis zu bestimmten Werten, siehe 
http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

Glaub aber eher nicht dass dein Problem damit zusammenhängt. Was 
passiert, wenn du das const beim Parameter für USART_Str weglässt?

von Karl H. (kbuchegg)


Lesenswert?

Strohhalm

> Nutze einen Atmega128A

Hast du die M103 Fuse abgeschaltet?

von Peter II (Gast)


Lesenswert?

Thomas Bergmüller schrieb:
> _delay_ms(1000);
> Dir ist klar dass das nicht hinhaut? Die Delayfunktionen funktionieren
> nur bis zu bestimmten Werten, siehe
> http://www.nongnu.org/avr-libc/user-manual/group__...
hast du dir überhaupt mal durchgelese was dort steht, wenn du schon die 
quelle angibst?

> When the user request delay which exceed the maximum possible one,
> _delay_ms() provides a decreased resolution functionality. In this
> mode _delay_ms() will work with a resolution of 1/10 ms, providing
> delays up to 6.5535 seconds (independent from CPU frequency). The
> user will not be informed about decreased resolution.


@Bruno In.
das delay ist ok.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Der Fehler ist revht einfach du hast den String nicht terminiert.
1
USART_Str("Hallo");
2
machste zu:
3
USART_Str("Hallo\0");
Dadurch Terminiert dein while(*s) nicht da ein Nullzeichen fehlt.

von Peter II (Gast)


Lesenswert?

Martin Wende schrieb:
> Der Fehler ist revht einfach du hast den String nicht terminiert.

was soll denn das hier? Es geht um C - da ist jeder Sting der mit "" 
geschrieben wird terminiert.

von Oliver J. (skriptkiddy)


Lesenswert?

Martin Wende schrieb:
> Dadurch Terminiert dein while(*s) nicht da ein Nullzeichen fehlt.

Dääd - falsch.

"" terminiert automatisch

Gruß Oliver

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Sagt das meinem AVRGCC, als ich mit AVR Anfing habe ich das \0 auch 
immer weggelassen und da stand dann aufm LCD der gesamte 
Speicherinhalt...

von Peter II (Gast)


Lesenswert?

Martin Wende schrieb:
> Sagt das meinem AVRGCC, als ich mit AVR Anfing habe ich das \0 auch
> immer weggelassen und da stand dann aufm LCD der gesamte
> Speicherinhalt...
dann war der Fehler woanders, der (AVR)GCC hat no nie diesen Fehler 
gemacht.

von Thomas E. (thomase)


Lesenswert?

Peter II schrieb:
> dann war der Fehler woanders, der (AVR)GCC hat no nie diesen Fehler
> gemacht.
Doch.
Das ist der hundertmillionste Compiler. Der hat diesen Fehler. Den kann 
man gegen einen Goldbarren und einen funktionierenden eintauschen.

mfg.

von Oliver J. (skriptkiddy)


Lesenswert?

Martin Wende schrieb:
> Sagt das meinem AVRGCC, als ich mit AVR Anfing habe ich das \0 auch
> immer weggelassen und da stand dann aufm LCD der gesamte
> Speicherinhalt...

Du meinst nicht zufällig diese Art der Deklaration?
1
char str[]={'H','A','L','L','O','\0'};

oder sogar sowas?
1
str[0] = 'H';
2
str[1] = 'A';
3
str[2] = 'L';
4
str[3] = 'L';
5
str[4] = 'O';
6
str[5] = '\0';

Gruß Oliver

von Oliver J. (skriptkiddy)


Lesenswert?

Thomas Eckmann schrieb:
> Doch.
> Das ist der hundertmillionste Compiler. Der hat diesen Fehler. Den kann
> man gegen einen Goldbarren und einen funktionierenden eintauschen.
>
> mfg.

Hoffe das war ironisch gemeint?

Gruß Oliver

von Thomas E. (thomase)


Lesenswert?

Oliver J. schrieb:
> Hoffe das war ironisch gemeint?
Nee. Ich bin sowas von humorlos.

mfg.

von Oliver J. (skriptkiddy)


Lesenswert?

Thomas Eckmann schrieb:
> Oliver J. schrieb:
>> Hoffe das war ironisch gemeint?
> Nee.

Doch. :)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter II schrieb:
> Martin Wende schrieb:
>> Sagt das meinem AVRGCC, als ich mit AVR Anfing habe ich das \0 auch
>> immer weggelassen und da stand dann aufm LCD der gesamte
>> Speicherinhalt...
> dann war der Fehler woanders, der (AVR)GCC hat no nie diesen Fehler
> gemacht.

Jedenfalls wurde solch ein Fehler nie berichtet, und ich hab die avr-gcc 
Fehler ziemlich genau im Blick.

Also Martin, her mit dem Testfall, der Compilerversion und den Optionen 
:-)

von Thomas E. (thomase)


Lesenswert?

Johann L. schrieb:
> Also Martin, her mit dem Testfall, der Compilerversion und den Optionen
Dann müsste er sich ja selber hochladen.

mfg.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Is schon lange her, machte im Hirn nur klick und ich habs getippt, 
also lasst meine Eingeweide da wo sie hingehören.

von Weingut P. (weinbauer)


Lesenswert?

ist das wirklich so, dass bei

while (*s){

und Inhalt = 0 die Schleife verlassen wird?

Davon abgesehen, das Programm hängt dann ewig in der schnarchlangsamen 
UART-Routine fest bei der Programmausführung.
Es wär evtl. sinnvoll mal über den TXC Flag zum Einen und den 
TXC-Interrupt im Besonderen nachzudenken.

von Peter II (Gast)


Lesenswert?

Fhutdhb Ufzjjuz schrieb:
> ist das wirklich so, dass bei
>
> while (*s){
>
> und Inhalt = 0 die Schleife verlassen wird?

ja

von Thomas B. (nichtessbar)


Lesenswert?

Peter II schrieb:
>> http://www.nongnu.org/avr-libc/user-manual/group__...
> hast du dir überhaupt mal durchgelese was dort steht, wenn du schon die
> quelle angibst?

Ich glaub ich muss mich entschuldigen, sehr peinlich... (wobei ich 
solche langen Delays üblicherweise mit einem Timer lösen würde, dann 
kann der Prozessor inzwischen was anderes tun (auch wenns hier im 
Beispiel wenig Sinn machen wird))

von Bruno I. (bjnas)


Lesenswert?

Sorry, war den ganzen Tag auf dem Bau. Habe ja eine Flut von Antworten 
erhalten. Super, Werde es sofort durchchecken.


Karl Heinz Buchegger schrieb:
> Hast du die M103 Fuse abgeschaltet?

Nein. Werde ich sofort mal machen.

>_delay_ms(1000);

Die waren zum Testen, sonst resetet der so schnell.

>USART_Str("Hallo\0");

Auch schon versucht, gleiches Resultat.

>while (*s)

Hier habe ich schon getestet mit einem Aufruf ohne Pointer, genau 
dasselbe.


Danke für die vielen Hinweise.

bjn

von Bruno I. (bjnas)


Lesenswert?

Das gibt's ja nicht, Du bist Super Karl Heinz.

> Karl Heinz Buchegger schrieb:
>> Hast du die M103 Fuse abgeschaltet?

Das war's schon, die M103 Fuse. Habe das mal nachgeschlagen im 
Datenblatt. Der wird ja mit dem Watchdog zusammen beschrieben. Steig 
leider nicht ganz durch, mein Englisch ist schwach ;-{ .

Und was ich gar nicht begreife, was hat das mit einem Funktionsaufruf 
zuntun.

Die Tiefen der Mikrokontroller.

von Peter II (Gast)


Lesenswert?

Bruno In. schrieb:
> Und was ich gar nicht begreife, was hat das mit einem Funktionsaufruf
> zuntun.

überhaupt nichts.

> an ATmega103 compatibility mode can be selected by programming
> the fuse M103C
damit hat er andere Register und Upcodes - der µC hat also eine eine 
Sprache verstanden.

von Stefan E. (sternst)


Lesenswert?

Bruno In. schrieb:
> Und was ich gar nicht begreife, was hat das mit einem Funktionsaufruf
> zuntun.

Der Compiler ist von einem Mega128 ausgegangen, und hat Code erzeugt, 
der den Stack-Pointer auf das Ende des RAM des Mega128 initialisiert. 
Der Controller ist aber in Wirklichkeit ein Mega103 (wegen der Fuse). 
Bei dem endet das RAM eher (weil er weniger Register hat und daher das 
RAM auch eher anfängt). Somit zeigt der Stack-Pointer auf eine Adresse, 
an der gar kein RAM ist, und damit geht das erste ret mit ziemlicher 
Sicherheit in die Hose.

von Bruno I. (bjnas)


Lesenswert?

Ja ,das wars wohl.

Danke für die Erklärung

Schönen Abend noch

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.