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
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;
}
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...
> 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).
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
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
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
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.
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....
>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
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
>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?
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
>>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.
>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
@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
#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;
}
>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
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
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?
> 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
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
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
@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
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