Hallo,
Eine Info gleich vorab: Ich bin erfahrener Programmierer (Java und etwas
C) aber Einsteiger im Bereich Mikrocontrollerprogrammierung.
Für ein kleines Projekt im Heimbereich hab ich mir das Pollin AVR-Net-IO
Board zugelegt. Die ersten Programmierungen mit dem Board (Firmware von
Ulrich Radig) liefen eigentlich recht erfolgreich. Webserver, UART etc.
hab ich schon viel umgesetzt.
Nach kurzer Zeit hab ich dann auch festgestellt, dass ein zweiter UART
nicht schlecht wäre. Daher habe ich den ATmega32 gegen einen ATmega644P
getauscht. Da auch recht viel mit UART gearbeitet wird, habe ich auch
gleich den Quarz von 16MHz auf 18,432 MHz gewechselt. Ansonsten ist das
Board aber unverändert geblieben.
Nun zu meinem Problem, wo ich euch um etwas Hilfe bitte: Ich verwende
beide UARTS mit einem MAX232. Irgendwann nach dem Umstieg auf den
ATmega664P habe ich festgestellt, dass der Controller unregelmäßig
resetet oder in er Loop wilde Zeichen auf der Konsole ausgibt. Eine Zeit
lang dachte ich einfach nur an Programmierfehler, letztendlich konnte
ich aber keine mehr ausmachen. Daher hab ich versucht das Problem
einzugrenzen und habe schrittweise alles an Code entfernt. Übrig
geblieben ist nur folgende main.c:
1
#include<avr/interrupt.h>
2
#include"config.h"
3
4
voidusart_write_char(constcharc)
5
{
6
while((UCSRA&(1<<UDRE))==0);
7
UDR=c;
8
}
9
10
ISR(USART_RXC_vect)
11
{
12
puffer=UDR;
13
}
14
15
voidprintit(void)
16
{
17
if(puffer!=0)
18
{
19
usart_write_char(puffer);
20
puffer=0;
21
}
22
}
23
24
intmain(void)
25
{
26
// UART initialisieren:
27
uint16_tbaud=F_CPU/(BAUDRATE*16L)-1;
28
UBRRH=(uint8_t)(baud>>8);
29
UBRRL=(uint8_t)baud;
30
UCSRB=(1<<TXEN|0<<RXEN|0<<RXCIE);
31
32
charbootmsg[]="****** System Ready *******\n\r";
33
for(inti=0;i<29;i++)
34
usart_write_char(bootmsg[i]);
35
// Buffer init:
36
puffer=0;
37
sei();
38
while(1)
39
{
40
printit();
41
}
42
}
die config.h sieht auch nicht recht spektakulär aus:
1
#define _CONFIG_H_
2
3
//Taktfrequenz
4
// #define F_CPU 16000000UL
5
#define F_CPU 18432000UL
6
7
#define BAUDRATE 9600
8
9
// UART Inputpuffer
10
volatilecharpuffer;
11
12
#if defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__)
13
#define UCSRA UCSR0A
14
#define UCSRB UCSR0B
15
#define UBRRL UBRR0L
16
#define UBRRH UBRR0H
17
#define TXEN TXEN0
18
#define RXEN RXEN0
19
#define RXCIE RXCIE0
20
#define UDR UDR0
21
#define UDRE UDRE0
22
#define USART_RXC_vect USART0_RX_vect
23
#endif
Mein Problem ist nun: Der UART0 hängt über den MAX232 vom Board an einem
USB2Serial Adapter am PC. Am PC habe ich Putty auf den entsprechenden
Com Port göffnet. Sofort nach dem programmieren erhalte ich
Erwartungsgemäß die Meldung "System Ready" im Putty.
Aber: Sobald ich in der Putty Sitzung ein paar Zeichen eingebe resetet
der Controller. Wenn ich auf einer beliebigen Taste drauf bleibe,
resetet er alle paar Sekunden. Und das unabhängig davon, ob diese Code
Zeile
1
UCSRB=(1<<TXEN|0<<RXEN|0<<RXCIE);
oder so
1
UCSRB=(1<<TXEN|1<<RXEN|1<<RXCIE);
aussieht. Bei zweiterer werden die Empfangenen Zeichen korrekt wieder
ausgegeben (Echo); Aber der Controller resetiert trotzdem.
Setze ich anstatt dem ATmega644P den originalen ATmega32 ein,
funktioniert es einwandfrei. Ohne Probleme. Getestet bei beiden
Prozessoren mit 16MHz und 18,324 MHz Quarz. Habs auch mit 3
verschiedenen USB2RS232 Convertern probiert.
Jetzt meine Frage an euch: Hab ich hier einen defekten ATmega644P oder
ist der UART an diesem anders zu programmieren als am ATmega32? Diese
Fehler hat mich nun schon ziemlich viel Zeit gekostet und jetzt bin ich
am Ende meiner Weisheit.
Meine Hausaufgaben (Google, Datenblatt, Tutorial, ...) habe ich alle
schon mehrfach gesichtet. Finde aber nichts brauchbares mehr.
Kann das mit den Fuses zusammenhängen? Alles betreffend der Taktung kann
ja eher ausgeschlossen werden - die Ausgabe auf dem UART funktioniert
tadellos. Der UART1 weist dieses Verhalten nicht auf. Nur der UART0
macht hier Probleme.
Wenn ich obige main wie folgt umbaue (den Inhalt der printit in die
main-loop direkt eintragen):
1
#include<avr/interrupt.h>
2
#include"config.h"
3
4
voidusart_write_char(constcharc)
5
{
6
while((UCSRA&(1<<UDRE))==0);
7
UDR=c;
8
}
9
10
ISR(USART_RXC_vect)
11
{
12
puffer=UDR;
13
}
14
15
intmain(void)
16
{
17
// UART initialisieren:
18
uint16_tbaud=F_CPU/(BAUDRATE*16L)-1;
19
UBRRH=(uint8_t)(baud>>8);
20
UBRRL=(uint8_t)baud;
21
UCSRB=(1<<TXEN|1<<RXEN|1<<RXCIE);
22
23
charbootmsg[]="****** System Ready *******\n\r";
24
for(inti=0;i<29;i++)
25
usart_write_char(bootmsg[i]);
26
// Buffer init:
27
puffer=0;
28
sei();
29
while(1)
30
{
31
if(puffer!=0)
32
{
33
usart_write_char(puffer);
34
puffer=0;
35
}
36
}
37
}
dann funktioniert es auch am ATmega644P. Allerdings, sobald ein
Funktionsaufruf in der main-loop enthalten ist (das kann auch eine
andere, leere Funktion sein), ist die Sache vorbei soabld Zeichen am
UART0 eintrudeln. Sieht so aus, als verwürfelt dann irgendetwas den
Stack ...
Danke im Voraus für eure Hilfe & Tips!
vG Alram
>natürlich wird das Projekt auch für den jeweiligen Controller übersetzt.
Und im Programmierdialog hast du auch die entsprechende
HEX Datei ausgewählt?
Irgend ein elektrisches Problem? (Pull Up am Reset-Pin vergessen, und
weil der UART0 da näher dran liegt kommt die Störung da an, aber nicht
wenn du was mit dem UART1 machst, ... oder so ...)
>natürlich wird das Projekt auch für den jeweiligen Controller übersetzt.
Der ATMEGA644P kennt aber kein UDR. UDR0 und UDR1 kennt er.
Ich frag mich auch wo puffer deklariert ist.
Ich denke es wird Zeit für vollständigen Code.
Irgendwas was man mal durch den Compiler jagen kann.
Hi,
elektrische Probleme hab ich eigentlich ausgeschlossen, da ja der
ATmega32 im gleichen im Sockel des Boards bestens funktioniert ... der
uart0 ist auch zur gänze auf der platine des boards. der uart1 ist mit
kabeln auf einem externen steckbrett angeschlossen und der funktioniert
ja bestens.
der UART0 des 664P funktioniert ja auch, bis man eben bspw. den code der
main loop in eine funktion auslagert. (siehe printit)
vG Alram
holger schrieb:> ammierdialog hast du auch die entsprechende> HEX Datei ausg
ich stelle im projekt (atmel studio) das device um und drücke F5. wenn
ich da den falschen device hab, meldet er mir das ziemlich schnell.
ich hab ja bereits den kompletten webserver und telnetserver erfolgreich
am laufen gehabt. ich denke, das hätte wohl nicht funktioniert, wenn ich
das falsche binary in den atmega644p geschossen hätte. ;)
leider hab ich keinen zweiten 644p zum testen da.
Alram Lechner schrieb:> der UART0 des 664P funktioniert ja auch, bis man eben bspw. den code der> main loop in eine funktion auslagert. (siehe printit)Alram Lechner schrieb:> void printit(void)> {> if (puffer != 0)> {> usart_write_char(puffer);> puffer = 0;> }> }
Wo ist puffer definiert? Nicht in der funktion und wird auch nicht
übergeben... glaubst du das das eine gute idee ist? nur mal so am
rande...
Grüße
> Wo ist puffer definiert?
Auch im Config header. Nicht schön, sollte aber tun.
Nächste Idee: Hast du schonmal versucht, einen Breakpoint auf den R
Reset-Vektor zu setzen? Keine Ahnung, ob das was bringt, oder ob da
schon alle Information verloren ist.
Kaj schrieb:> Wo ist puffer definiert? Nicht in der funktion und wird auch nicht
in der config.h
> übergeben... glaubst du das das eine gute idee ist? nur mal so am> rande...
ich möchte hier nicht um den Sinn des gezeigten Problems disktuieren!
den Code habe ich geschrieben, um mit möglichst wenig Zeilen,
übersichtlich mein Problem darzustellen. Weil funktionieren müsste es ja
so, oder? (OK: theoretisch können Zeichen verloren gehen - aber das ist
ja nicht mein Problem)
Den Fehler hab ich festgestellt, während ich mittels UDP Paketen Befehle
an den NetIo gesendet und damit am UART0 Befehle ausgelöst habe; Dort
hängt dann mein Receiver dran, der Antworten sendet. Und immer bei
Empfang einer Antwort, resetierte sich der Controler. Auf dem Weg das
Problem einzugrenzen, bin ich bei den obigen Code-Zeilen gelandet.
vG Alram
sebastan schrieb:> Hast du schonmal versucht, einen Breakpoint auf den R> Reset-Vektor zu setzen?
hab nur den AVRISP mkII - da ist nix mit debuggen, oder?
> hab nur den AVRISP mkII - da ist nix mit debuggen, oder?
Stimmt. Außer du kannst den Fehler im Simulator reproduzieren. Kann dir
aber nicht sagen, wie man UART-Input simuliert.
holger schrieb:> Probier mal die HEX Datei im Anhang.
da kommt "Test" beim UART0 raus.
kein tastaturecho;
aber auch kein reset; auch wenn ich länger auf einer taste bleibe ...
wie sieht der source dazu aus?
holger schrieb:>>Probier mal die HEX Datei im Anhang.>> Und jetzt die.
die gibt "****** System Ready *******" aus und resetiert regelmäßig,
solange ich auf einer taste bleibe ...
>> Probier mal die HEX Datei im Anhang.>>da kommt "Test" beim UART0 raus.>kein tastaturecho;
Son Mist da fehlte ein sei()
So, nochmal wenn du magst.
Bei mir schmiert das so nicht ab.
Und wenn man sich deine erste Version aus deinem Post
genauer ansieht hätte eine Eingabe gar nicht funktionieren
dürfen.
UCSRB = (1 << TXEN | 0 << RXEN | 0 << RXCIE);
RXEN aus, RXCIE aus. Eingabe nicht möglich.
holger schrieb:> Und nochmal dein Programm, das schmiert bei mir auch nicht ab.> Allerdings hab ich das auch nur mit 16MHz laufen lassen.
guten morgen,
das scheint zu funktionieren. es kommt die "****** System Ready
*******" meldung und alle eingaben kommen als echo zurück. ohne reset.
das schaffe ich nur, wenn die mainloop so aussieht:
1
while(1)
2
{
3
if(puffer!=0)
4
{
5
usart_write_char(puffer);
6
puffer=0;
7
}
8
}
sobald ich den inhalt in die printit() funktion auslagere, resetet er.
wie sieht dein code zu dem hex aus?
danke nochmals für deine bemühungen!
vG Alram
holger schrieb:> Und wenn man sich deine erste Version aus deinem Post> genauer ansieht hätte eine Eingabe gar nicht funktionieren> dürfen.>> UCSRB = (1 << TXEN | 0 << RXEN | 0 << RXCIE);>> RXEN aus, RXCIE aus. Eingabe nicht möglich.
korrekt. das echo der zeichen hat auch nicht funktioniert. resetieren
tut der controller aber schon.
daher hab ich im ersten post auch explizit auf diese zeile hingewiesen.
vG Alram
Volker schrieb:> Wie ist denn das Low-Byte Fuse gesetzt?
sorry - hab ich erst jetzt gelesen:
low: 0xFF
high: 0xDF
extended: 0xFF
kann es mit den fuses zusammenhängen?
Hallo Leute, ich habe erst vor drei Wochen angefangen, mich mit C zu
befassen. Meine Wortmeldung hier ist daher vielleicht verfrüht, vorlaut
sein will ich auch nicht.
Mir ist aufgefallen, dass in der config.h folgender Passus steht:
Alram Lechner schrieb:> #if defined (_AVR_ATmega644_) || defined (_AVR_ATmega644P_)> #define UCSRA UCSR0A> #define UCSRB UCSR0B> #define UBRRL UBRR0L... usw.
Ich hätte da anstatt des "#if defined" ein "#ifndef" erwartet, um
Doppeldeklarationen zu vermeiden, die angeblich zu unverstehbaren
Effekten führen sollen.
ernst oellers schrieb:> Alram Lechner schrieb:>> #if defined (_AVR_ATmega644_) || defined (_AVR_ATmega644P_)>> #define UCSRA UCSR0A>> #define UCSRB UCSR0B>> #define UBRRL UBRR0L... usw.>> Ich hätte da anstatt des "#if defined" ein "#ifndef" erwartet, um> Doppeldeklarationen zu vermeiden, die angeblich zu unverstehbaren> Effekten führen sollen.
Das passt schon. Diese Makros werden dem Compiler auf der Command Line
übergeben und spezifizieren welcher µC-Typ benutzt wird.
> die angeblich zu unverstehbaren> Effekten führen sollen.
na ja. so unverstehbar ist das jetzt nicht gerade.
Es geht einfach nur darum, dass Atmel, der Himmerl weiß warum, es nicht
schafft eine einheitliche Nomenklatur für die UART Register quer über
alle AVR hinzukriegen. Also wird das hier nachgeholt. Die Korrektur ist
für die beiden Typen 644 und 644P identisch. Mehr steht da nicht.
So, da bin ich nochmal.
Ich hab dein erstes Beispiel ohne RX Interrupt probiert.
Da gibt es keinen Reset. Dann den Rx mit Interrupt aktiviert.
Kein Reset. Ich hab die Flosse so lange auf der X Taste gelassen
bis das Terminalfenster voll war.
Im Anhang mal die Hex für mit Rx Interrupt.
holger schrieb:> So, da bin ich nochmal.>> Ich hab dein erstes Beispiel ohne RX Interrupt probiert.> Da gibt es keinen Reset. Dann den Rx mit Interrupt aktiviert.> Kein Reset. Ich hab die Flosse so lange auf der X Taste gelassen> bis das Terminalfenster voll war.>> Im Anhang mal die Hex für mit Rx Interrupt.
Hallo Holger,
danke für deine Bemühungen - ich weiss das sehr zu schätzen. Ich hab nun
dein letztes Images geflasht und im Putty einfach nur die x Taste
gedrückt (und gedrückt gehalten). Das Ergebnis ist im Anhang ...
:((
also ich denke, ich hab da einen defekten ATmega644P.
Bin gerade dabei einen ATmega1284P (leider im TQFP package) auf eine
prototyping Platine zu löten und dann testweise mit dem AVR Net IO zu
verbinden ... mal sehen, ob ich so endlich einmal 2 UARTS gleichzeitig
zum laufen bekomme.
>also ich denke, ich hab da einen defekten ATmega644P.
So schnell geht ein ATMega nicht kaputt.
Das könnte z.B. auch an deiner Spannungsversorgung liegen.
Volker schrieb:> alram schrieb:>> low: 0xFF>> CKSEL3..0 steht also auf low power crystal oscillator?> Würde ich mal auf full swing crystal oscillator setzen.
low steht nun auf 0xF7.
und was ist nun? >> es funktioniert. danke Volker!
wieder einmal wurde bewiesen: immer wenn man glaubt das ding sei defekt,
sitzt das problem vor dem PC. peinlich
danke an alle, die mitgeholfen haben.
vG Alram