Forum: Mikrocontroller und Digitale Elektronik ATMEGA stürzt ab wenn zu schnell Daten kommen über USART


von Tobias H. (Gast)


Lesenswert?

Hi

Im Titel steht eigentlich schon alles. Ich sende Daten an meinen 
ATMEGA32 über das Programm "COM Terminal". Dieser schickt genau die 
Zeichen wieder zurück. Wenn ich bei "Pause zwischen den Zeichen" 0ms 
einstelle und einen längeren Text sende, resettet sich der AVR 
selbstständig. Woran kann das liegen?

Ciao Tobias

von Karl H. (kbuchegg)


Lesenswert?

> Woran kann das liegen?

An deinem Program

von Marco S. (masterof)


Lesenswert?

meine Glaskugel ist leider in der reperatur.
Kannst du auch den Quellecode mit schicken.

von Tobias H. (Gast)


Lesenswert?

void uart_senden_einzeln(unsigned char zeichen)
{
    loop_until_bit_is_set(UCSRA,UDRE); //Bereit zum Senden?
    UDR=zeichen; //Sende
}


void uart_senden(char *zeichen)
{
  while (*zeichen)
  {
  uart_senden_einzeln(*zeichen);
      zeichen++;
  }
}

void uart_entleeren()
{
  unsigned char dummy;
  while (UCSRA & (1<<RXC)) dummy=UDR;
}

unsigned char uart_empfangen(void)
{
  while (!(UCSRA & (1<<RXC))); // warten bis Zeichen verfuegbar
  uart_senden_einzeln(UDR); //Sende Zeichen zur Bestätigung zurück
  return UDR; // Zeichen aus UDR an Aufrufer zurueckgeben
}
void uart_initialisieren(unsigned long baud_rate)
{
  UCSRB |= (1<<TXEN|1<<RXEN); //UART TX und RX einschalten
  UCSRC |= (1<<URSEL)|(1<<UCSZ0|1<<UCSZ1); //Asynchron 8N1
  unsigned long ubrr_calc;
  ubrr_calc=F_CPU/(16*baud_rate)-1; //Berechne Wert, aus dem der AVR die 
Baudrate generiert
  UBRRH=(unsigned char)(ubrr_calc>>8); //schreibe den oberen Teil des 
Werts in die Schnittstelle
  UBRRL=(unsigned char)(ubrr_calc); //schreibe den unteren Teil des 
Werts in die Schnittstelle
  uart_entleeren(); //Puffer entleeren, damit keine Störungen vor den 
Daten zu Fehlern führen
}

int main(void)
{
  uart_initialisieren(19200);
  while (1)  //Endlosschleife
  {
    uart_empfangen();
  }
  return 1;
}

von unbeschreiblicher Rahul (Gast)


Lesenswert?

> Marco Schwan (masterof)

Gar kein "*abo*"?

von Karl H. (kbuchegg)


Lesenswert?

Woran merkst du, dass ein Reset erfolgt ist?

Das Pgm sieht nicht so schlecht aus.

von Tobias H. (Gast)


Lesenswert?

Ich habe noch eine LCD Routine und schalte 2 Relais. Dies tue ich, bevor 
dann der oben gepostete Code ausgeführt wird. Ich höre dann plötzlich 
ein Klacken und sehe wieder den Startbildschirm.

An den Fuses kann sowas nicht liegen, oder?

Ach ja, bei Bedarf poste ich auch den LCD Code usw...

von Karl H. (kbuchegg)


Lesenswert?

> An den Fuses kann sowas nicht liegen, oder?

Eher nicht.
Ein Reset könnte durch Spikes in der Stromversorgung
ausgelöst werden.

Lass doch den ganzen Rundumkram (LCD, Relais) weg und
schreibe ein Testprogramm, dass nur die UART initialisiert
und empfangene Zeichen wieder zurückschickt. Hast du
dann immer noch die unerklärlichen Resets?
(Zur Kontrolle ob ein Reset erfolgt, kannst du ja
folgendes machen: Beim Einschalten eine Led einschalten,
etwas warten und Led wieder ausschalten).

von A.K. (Gast)


Lesenswert?

Was ist Henne was ist Ei? Will sagen: Klackt das Relais als Folge des 
Reset oder kommt der Reset als Folge fehlerhafter Ansteuerung des 
Relais?

von Tobias H. (Gast)


Lesenswert?

Relais klackt in Folge des Resets. Das Relais wird vor dem Beginn der 
seriellen Routinen angeschaltet und bleibt so "für immer". Eigentlich 
zumindestens. Beim Reset wird es dann natürlich abgeschaltet und 
aufgrund eine Warteeinrichtung, die ich beim Start drin hab, erst nach 1 
sek. wieder angeschaltet.

>Eher nicht.
>Ein Reset könnte durch Spikes in der Stromversorgung
>ausgelöst werden.
>
>Lass doch den ganzen Rundumkram (LCD, Relais) weg und
>schreibe ein Testprogramm, dass nur die UART initialisiert
>und empfangene Zeichen wieder zurückschickt. Hast du
>dann immer noch die unerklärlichen Resets?
>(Zur Kontrolle ob ein Reset erfolgt, kannst du ja
>folgendes machen: Beim Einschalten eine Led einschalten,
>etwas warten und Led wieder ausschalten).

gute Idee! Probier ich bei Gelegenheit mal! An einem Portpin hängt ein 
Buzzer, der komplett ohne externe Beschaltung funktioniert (direkt am 
Portpin) - den kann ich dafür ja nehmen.

Ciao Tobias

von Tobias H. (Gast)


Lesenswert?

Das Programm zum Testen jetzt:

#ifndef F_CPU
#define F_CPU 16000000UL      //Prozessor Frequenz in Hz
#endif

#include <avr/io.h>
#include <util/delay.h>

void uart_senden_einzeln(unsigned char zeichen)
{
    loop_until_bit_is_set(UCSRA,UDRE); //Bereit zum Senden?
    UDR=zeichen; //Sende
}


void uart_senden(char *zeichen)
{
  while (*zeichen)
  {
  uart_senden_einzeln(*zeichen);
    zeichen++;
  }
}

void uart_entleeren()
{
  unsigned char dummy;
  while (UCSRA & (1<<RXC)) dummy=UDR;
}

unsigned char uart_empfangen()
{
  while (!(UCSRA & (1<<RXC))); // warten bis Zeichen verfuegbar
  return UDR; // Zeichen aus UDR an Aufrufer zurueckgeben
}

void uart_initialisieren(unsigned long baud_rate)
{
  UCSRB |= (1<<TXEN|1<<RXEN); //UART TX und RX einschalten
  UCSRC |= (1<<URSEL)|(1<<UCSZ0|1<<UCSZ1); //Asynchron 8N1
  unsigned long ubrr_calc;
  ubrr_calc=F_CPU/(16*baud_rate)-1; //Berechne Wert, aus dem der AVR die 
Baudrate generiert
  UBRRH=(unsigned char)(ubrr_calc>>8); //schreibe den oberen Teil des 
Werts in die Schnittstelle
  UBRRL=(unsigned char)(ubrr_calc); //schreibe den unteren Teil des 
Werts in die Schnittstelle
  uart_entleeren(); //Puffer entleeren, damit keine Störungen vor den 
Daten zu Fehlern führen
}

//Ton Routine
void ton(int laenge) //gibt einen Ton mit der Länge "lange" in ms aus
{
  PORTA |= (1<<PA1);
  _delay_ms(laenge);
  PORTA &= ~(1<<PA1);
}

int main(void)
{
  DDRA |= (1<<PA1);//Anschluss des Summers als Ausgang
  ton(10);//gibt kurz einen Ton aus, zur Bestätigung der 
Funktionstüchtigkeit
  uart_initialisieren(19200);
  int zeichen;
  while (1)  //Endlosschleife
  {
    zeichen=uart_empfangen();
    uart_senden_einzeln(zeichen);
  }
  return 1;
}

schmiert auch bei längeren Texten ab! Aber immer nur zu Beginn einer 
Übertragung. Dafür machmal gleich mehrfach (höhre mehrere der kurzen 
Töne)...

Ciao Tobias

von Tobias H. (Gast)


Lesenswert?

hab mal die Stromversorgung gezeichnet. Hoffe, das funktioniert, 
ansonsten im Anhang!

Die 100nF Dinger sitzen alle direkt an den ICs. Die beiden Elkos sitzen 
aus Platzgründen irgendwo anders auf der Platine.
Hier erstmal der Plan:



              1N4004P                   .----------------------------.
          .-----|<------.               |            .------.        |
          |    __     |               |      .-----o Reset|        |
 12V=     |   |    |    |               |      |     |      |        |
 --o----o-o---|7805|----o----o----------o------)-----o VCC  | .---o--'
   | +  |     |____|    |    | +              ---  | |  GND o-)-. |
  ###  ---      |      ---  ###         100nF --- ---|      | | |---
  ---  ---      |      ---  ---                |  ---|      | | |---
   |    |       |       |    |                 |   | | AVCC o-' | |
 --o----o-------o-------o----o--------------o--o---o-o  µC  |   '-o---.
       100nF          100nF                 |        |GND   |         |
                                            |   100nF|      |    100nF|
 1000µF                    470µF            |        |      |         |
                                            |        |      |         |
                                            |        |      |         |
                                            |        |      |         |
                                            |        |      |         |
                                            |        '------'         |
                                            |                         |
                                            |                         |
                                            |                         |
                                            '-------------------------'
(created by AACircuit v1.28.6 beta 04/19/05 www.tech-chat.de)

Kann das auch am Max232N liegen? Oder an dessen Kondensatoren? Hab 
nämlich ein Max232N "geröstet" und ausgetauscht - können vielleicht beim 
Rösten die Kondensatoren einen Schlag weg bekommen haben? Aber wie 
könnte das wiederum einen Reset am AVR auslösen?
Der MAX232N hat auch einen 100nF Kondensator zwischen VCC und GND und 
halt die 4 Stück 1µF Kondensatoren...

Ciao Tobias

von Tobias H. (Gast)


Angehängte Dateien:

Lesenswert?

der Anhang... aber ich glaube, es geht schon!

von Marco S. (masterof)


Lesenswert?

unbeschreiblicher Rahul wrote:
>> Marco Schwan (masterof)
>
> Gar kein "*abo*"?


braucht man dank der neuen software nicht mehr.

@Tobias H.

änder mal bei deinem "normalen" Programm die Funktion uart_empfangen 
folgend um

unsigned char uart_empfangen(void)
{
  unsigned char a = ;
  while (!(UCSRA & (1<<RXC))); // warten bis Zeichen verfuegbar
  a = UDR;
  uart_senden_einzeln(a); //Sende Zeichen zur Bestätigung zurück
  return a; // Zeichen aus UDR an Aufrufer zurueckgeben
}


Weil die UART vom AVR mag es nicht 2 mal ausgelesen zu wrden hat mich 
mal 5 Stunden an Zeit gekosten das raus zufinden.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Kann das mal sein, daß durch die vielen schnellen Zeichen das Prog nicht 
mehr aus den Schleifen kommt und der Watchdog zuschlägt? Nur so ´ne 
Vermutung....

von Tobias H. (Gast)


Lesenswert?

>Kann das mal sein, daß durch die vielen schnellen Zeichen das Prog nicht
>mehr aus den Schleifen kommt und der Watchdog zuschlägt? Nur so ´ne
>Vermutung....

Mit dem Watchdog hab ich mich noch nie beschäftigt - muss ich den nicht 
erst explizit einschalten, damit der arbeitet? Außerdem stürzt der 
Prozessor schon nach Sekundenbruchteilen ab. Ist aber auch verschieden. 
Manchmal reichen 5 Zeichen, manchmal auch erst 10. Wenn ich einzeln mit 
Pausen sende, passiert eben nichts. Außerdem müssten 19200 Baud für 
einen AVR bei 16Mhz zu packen sein, oder?

>unbeschreiblicher Rahul wrote:
>>> Marco Schwan (masterof)
>>
>> Gar kein "*abo*"?
>
>
>braucht man dank der neuen software nicht mehr.
>
>@Tobias H.
>
>änder mal bei deinem "normalen" Programm die Funktion uart_empfangen
>folgend um
>
>unsigned char uart_empfangen(void)
>{
>  unsigned char a = ;
>  while (!(UCSRA & (1<<RXC))); // warten bis Zeichen verfuegbar
>  a = UDR;
>  uart_senden_einzeln(a); //Sende Zeichen zur Bestätigung zurück
>  return a; // Zeichen aus UDR an Aufrufer zurueckgeben
>}
>
>
>Weil die UART vom AVR mag es nicht 2 mal ausgelesen zu wrden hat mich
>mal 5 Stunden an Zeit gekosten das raus zufinden.

Ich probiers mal...

Ciao Tobias

von Läubi (Gast)


Lesenswert?

Vieleicht produzierst du aber auch nen Stack überlauf?
Zudem ist 16mhz auch kein sher Tauglicher Quarz für UART

von Tobias H. (Gast)


Lesenswert?

Hmm nein, stürzt immer noch ab. Komisch nur, dass er das immer nur zu 
Beginn einer Übertragung tut... Wenn die dann erstmal läuft, dann gibs 
keine Probleme mehr. So lange, bis ich die nächste lange Kette sende. Es 
sei denn, ich warte lange. Dann stürzt er auch dabei dann wieder ab. 
Also sende ich 10 Zeichen, sag ich mal schmiert er nach 5 ab. Sende ich 
100 Zeichen, schmiert er auch nach 5 ab, vielleicht nochmal nach 10, 
aber der Rest geht...

Ich versuch mal weiter, die serielle Schnittstelle am STK500 in Gang zu 
bekommen. Dann könnte ich es damit mal testen... Kann mir irgendjemand 
sagen, warum die nicht geht? ;-) (Glaskugel repariert?)

Ciao Tobias

von Tobias H. (Gast)


Lesenswert?

>Vieleicht produzierst du aber auch nen Stack überlauf?
>Zudem ist 16mhz auch kein sher Tauglicher Quarz für UART

Wie finde ich das raus und behebe das?

von Läubi (Gast)


Lesenswert?

ich würde das Programm einfach mal vereinfachen!
Ohne Unteraufrufe etc.

Also nur im Mainloop
# warten auf ein Zeichen --> empfangen
# warten bis sendepuffer leer --> senden

von Thomas (Gast)


Lesenswert?

>>Zudem ist 16mhz auch kein sher Tauglicher Quarz für UART

> Wie finde ich das raus und behebe das?

Im Datenblatt ist am Unterpunkt "USART" eine Tabelle mit den 
Baudratenfehlern bei verschiedenen Taktfrequenzen zu finden.
Laut der Liste hast du bei 16MHz und 19,2k eine Abweichung von 0,2%.
Diese Abweichung sollte aber eigentlich noch im Rahmen sein.

von Tobias H. (Gast)


Lesenswert?

>ich würde das Programm einfach mal vereinfachen!
>Ohne Unteraufrufe etc.
>
>Also nur im Mainloop
># warten auf ein Zeichen --> empfangen
># warten bis sendepuffer leer --> senden

Auch dieses Programm schmiert laufend ab...

Kann das wirklich nicht irgendwie am MAX232N liegen? Einen Fehler/Defekt 
an der Stelle könnte ich mir nämlich erklären... Aber kann das einen 
Reset auslösen?

P.S.: Bei meiner Stromversorgungsschaltung oben hab ich eins vergessen: 
Der 10k Pull-up am Reset-Pin ist natürlich vorhanden!

Ciao Tobias

von Falk (Gast)


Lesenswert?

@Läubi

> Zudem ist 16mhz auch kein sher Tauglicher Quarz für UART

Immer diese Baudratenquarzfetischisten. Mann!!! ;-)

Mit 16 MHz kann ich alle normalen Baudratenm ausser 57k6 und 115k2 mit 
einem Fehler klener als 0,8% generieren.

MFG
Falk

von Läubi (Gast)


Lesenswert?

poste mal das Program.
Klar kans am MAX liegen, wenn z.B: deine Stromversorgung zusammenbricht 
oder so.

von Tobias H. (Gast)


Lesenswert?

#ifndef F_CPU
#define F_CPU 16000000UL      //Prozessor Frequenz in Hz
#endif

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  DDRA |= (1<<PA1);//Anschluss des Summers als Ausgang
  PORTA |= (1<<PA1);
  _delay_ms(10);
  PORTA &= ~(1<<PA1);//gibt kurz einen Ton aus, zur Bestätigung der 
Funktionstüchtigkeit
  UCSRB |= (1<<TXEN|1<<RXEN); //UART TX und RX einschalten
  UCSRC |= (1<<URSEL)|(1<<UCSZ0|1<<UCSZ1); //Asynchron 8N1
  unsigned long ubrr_calc;
  ubrr_calc=F_CPU/(16*19200L)-1; //Berechne Wert, aus dem der AVR die 
Baudrate generiert
  UBRRH=(unsigned char)(ubrr_calc>>8); //schreibe den oberen Teil des 
Werts in die Schnittstelle
  UBRRL=(unsigned char)(ubrr_calc); //schreibe den unteren Teil des 
Werts in die Schnittstelle
  unsigned char dummy;
  while (UCSRA & (1<<RXC)) dummy=UDR; //Puffer entleeren, damit keine 
Störungen vor den Daten zu Fehlern führen
  unsigned char a;
  while (1)  //Endlosschleife
  {
     while (!(UCSRA & (1<<RXC))); // warten bis Zeichen verfuegbar
     a = UDR; //Sende Zeichen zur Bestätigung zurück
      loop_until_bit_is_set(UCSRA,UDRE); //Bereit zum Senden?
      UDR=a; //Sende
  }
  return 1;
}

von Tobias H. (Gast)


Lesenswert?

>Klar kans am MAX liegen, wenn z.B: deine Stromversorgung zusammenbricht
>oder so.

Ich habe heute gerade 3 STück MAX232N und 2 Stück 16 polige Sockel 
bekommen. In einer Stunde denke ich, hab ich das Ding ausgewechselt (das 
ist immer ein Gefriemel, ungesockelte ICs auszulöten...). Diesmal würd 
ich die Kondensatoren außen rum gleich mit auslöten. Dann hätte ich die 
komplette Beschaltung des seriellen Ports ausgewechselt. Sinnvoll oder 
nicht?

Ciao Tobias

von Läubi (Gast)


Lesenswert?

Wenn deine Stromversorgung zu schwach ist ---> Nö :)

von Tobias H. (Gast)


Lesenswert?

Hi

Soo, ich habe jetzt mal den Prozessor auf ein Steckbrett gesteckt. 
Gleiche Beschaltung, Kondensatoren selbigen Typs, eins von den neuen Max 
ICs. Spannungsregler ist auch der gleiche Typ. Einzige Unterschiede: Der 
Spannungsregler ist komplett unbeschaltet (kein Kondensator, keine 
Diode) und als Kabel verwende ich die andere Hälfte des in der Mitte 
durchgeschnittenen Nullmodemkabels. Damit gehts ohne Absturz - Fehler 
ist also in meiner Schaltung zu suchen...

Ciao Tobias

von Dirk (Gast)


Lesenswert?

In deiner Schematic fehlt der Pull Up Widerstand am RST Pin.

von Tobias H. (Gast)


Lesenswert?

Autor: Tobias H. (Gast)
Datum: 04.01.2007 12:30
>
>[...]
>
>P.S.: Bei meiner Stromversorgungsschaltung oben hab ich eins vergessen:
>Der 10k Pull-up am Reset-Pin ist natürlich vorhanden!
>
>Ciao Tobias

Wie ich schon sagte, der ist natürlich eingebaut!

Da fällt mir gerade och ein Unterschied ein. Auf dem Steckbrett ist der 
Resetpin direkt mit VCC verbunden. Auf meiner Platine über den 10k 
Widerstand, damit man noch programmieren kann. Könnte der zu groß sein?

von Falk (Gast)


Lesenswert?

> Resetpin direkt mit VCC verbunden. Auf meiner Platine über den 10k
> Widerstand, damit man noch programmieren kann. Könnte der zu groß sein?

Nein.

MfG
Falk

von Tobias H. (Gast)


Lesenswert?

Ich stelle nun gerade keinen Reset mehr fest, dafür kommen vollkommen 
falsche Zeichen zurück... hmmm...

von Tobias H. (Gast)


Lesenswert?

Aus "test" wird "t{}|"

116 101 115 116
wird zu
116 125 123 124

das klingt nach falscher Baudrate, oder?

von Tobias H. (Gast)


Lesenswert?

ich wieder:

jetzt passt es wieder - dafür schmiert er jetzt wieder ab :-(

von Tobias H. (Gast)


Lesenswert?

irgendwie hab ich das Gefühl, den Fehler gefunden zu haben. Entweder das 
Quarz, oder die Kondensatoren am Quarz haben einen defekt... Ich löte 
mal!

von Tobias H. (Gast)


Lesenswert?

yyyyyeeeeeeeeeeeeeeeeeeeeeehhhhhhhhhaaaaaaaaaaaaaaaaaaaaaaa

Einer der beiden 22pF Kondensatoren am Quarz war offensichtlich defekt. 
Hab nur den einen ausgewechselt, jetzt wieder getestet und: ES GEHT!! 
Ohne Absturz!

Ciao Tobias

von Dirk (Gast)


Lesenswert?

Sicherlich nen falschen erwischt.

von Tobias H. (Gast)


Lesenswert?

nein, der war schon richtig (steht ja drauf) - aber ich glaube der hat 
einiges mechanisch mitgemacht. Erstmal ist das Rastermaß 2,54 und ich 
musste ihn auf das doppelte hinbiegen. War extra vorsichtig eigentlich. 
Und außerdem ist er mir mal "umgeklappt" also platt umgebogen auf die 
Platine rauf. Beides zusammen hat ihn wohl rzerstört. Jetzt hab ich die 
Schaltung so angepasst, dass ich ihn direkt mit 2,54mm anlöten konnte.

Ciao Tobias

von Paul Baumann (Gast)


Lesenswert?

@Tobias
So etwas kann einen wahnsinnig machen. Ich fühle mit Dir ;-)
Ich habe mal 22nF als 22pF geliefert bekommen, der Effekt war ähnlich 
lustig.
Daraufhin ein Reim:
Vor dem Löten, nach dem Essen
Messen nicht vergessen!
:-)

MfG Paul

von Tobias H. (Gast)


Lesenswert?

Hi Paul

Danke für dein Mitgefühl :-)

Darauf hab ich jetzt noch nicht geachtet - hab nur die 22 gesehen. Ob 
eine "Niete" zwischen den 22pF Dingern war, kann ich nicht sagen. Auf 
jeden Fall hats insgesamt mehr als 1 Tag quasi dauerhafter Suche 
gebraucht, den defekt zu finden...

Ich sollte mir mal ein Messgerät für Kapazitäten kaufen/bauen!

Ciao Tobias

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.