Hallo zusammen
Ich habe derzeit ein komisches Verhalten beim ATmega16. Folgende
Konfiguration:
- ATmega16 @4MHz internen Oszillator
- Kommunikation über RS232 @ 19200Baud
Nun zu meinem Problem:
Ich versuche derzeit die FAT32 Lib von hier zu verwenden:
http://www.mikrocontroller.net/articles/AVR_FAT32
Es tritt jetzt jedoch ein Fehlverhalten des Controllers auf das ich
nicht nachvollziehen kann.
Wenn ich folgenden Code verwende
1
intmain(void){
2
u8Flag=0;
3
//Datei die auf SD Karte angelegt werden soll
4
unsignedcharfile_name[]="test.txt";
5
//String der in die Datei geschrieben werden soll
6
unsignedcharstr[]="Hallo Datei!";
7
8
unsignedlongintseek;
9
10
_delay_ms(200);//dummy delay
11
gvUsartConfig(&tdsUsartConfig);
12
MAKRO_USART_ENABLE_CHANNELS(USART_TX);
13
14
timer0_init();
15
vPortInit();
16
17
gvUsartPutStringPolling("Startup\n");
18
gvUsartPutCharPolling(TERM_CARRIAGE_RETURN);
19
20
if(FALSE==mmc_init()){
21
gvUsartPutStringPolling("No SD Card!\n");
22
//gvUsartPutCharPolling(TERM_CARRIAGE_RETURN);
23
return1;
24
}
25
/*
26
Ab hier alles gleich
27
*/
Hier einmal kurz die Funktionen für das senden:
1
voidgvUsartPutCharPolling(constuint8_tu8Char){
2
while(!(UCSRA&(1<<UDRE)));//wait until transmission possible
3
UDR=u8Char;//write char into transmit buffer
4
}
1
voidgvUsartPutStringPolling(constchar*u8String){
2
while(*u8String!='\0'){
3
gvUsartPutCharPolling((uint8_t)*u8String);
4
u8String++;
5
}
6
}
Wenn ich keine SD-Karte anschließe habe ich das gewünschte Verhalten=>
Das Programm startet immer wieder neu da mmc_init einen Fehler
zurückliefert.
Nun aber zu meinem seltsammen verhalten:
Wenn ich die Codezeile
1
gvUsartPutCharPolling(TERM_CARRIAGE_RETURN);
herausnehme wird gar nichts mehr über RS232 herausgesendet, nicht einmal
irgendwelcher Unsinn.
Dieser Fehler tritt auch bei noch minimalistischeren Code auf (Nur
initialisierung und dann senden). Manchmal nimmt er alles an, dann beim
hinzufügen eines weiteren sendebefehls geht wieder gar nichts usw.
Ich kann mir nicht erklären woher dieser Fehler nun kommt. Das einzige
das ich mir erklären kann ist das der Controller in irgendeinen Reset
wegen eines Fehler reinspringt. Leider habe ich keinen Debugger um der
Vermutung nachzugehen.
Hatte mal jmd. ein ähnliches Problem und hat eine Lösung gefunden?
Der interne Oszillator ist zu ungenau. Ohne Kalibrierung ist er
ungeeignet zum Takten einer UART. Die Kalibrierung sollte der Controller
regelmäßig selbst gegen eine Taktreferenz vornehmen. Die Alternative ist
das Verwenden eines Quarzes.
Grüße,
Peter
Salut ..
gvUsartConfig(&tdsUsartConfig);
MAKRO_USART_ENABLE_CHANNELS(USART_TX);
ist vielleicht schuld? Dummerweise hat meine Glaskugel gerade just in
dem Moment die Batterien leer gehabt ^^
Peter Diener schrieb:> Der interne Oszillator ist zu ungenau. Ohne Kalibrierung ist er> ungeeignet zum Takten einer UART. Die Kalibrierung sollte der Controller> regelmäßig selbst gegen eine Taktreferenz vornehmen. Die Alternative ist> das Verwenden eines Quarzes.
Die Übertragung funktioniert aber einwandfrei, wenn ich das Carriage
Return drinnen lasse kann ich Stundenlang senden ohne Probleme. Aber
sobald diese Codezeile herausgenommen wird geht gar nichts mehr.
A.N. schrieb:> gvUsartConfig(&tdsUsartConfig);> MAKRO_USART_ENABLE_CHANNELS(USART_TX);>> ist vielleicht schuld? Dummerweise hat meine Glaskugel gerade just in> dem Moment die Batterien leer gehabt ^^
Das kann ich mir nicht denken, denn dann dürfte es ja nie funktionieren.
Es funktioniert aber solange ich ein Carriage return versende. Sobald
keines mehr versendet wird gibt es Probleme.
Als weiterer Hinweis:
Die Funktionen zur Intialisierung und aktivieren des Uart funktionieren
in anderen programmen auf anderen ATmegas einwandfrei. Nur dieser ATmega
macht derzeit Probleme.
Bei Timingfehlern an einer UART sind Fehlerbilder wie dieses nicht
ungewöhnich. Meine Meinung ist unverändert, dass es mit großer
Wahrscheinlichkeit am Oszillator liegt.
Grüße,
Peter
Albert ... schrieb:> Wenn ich keine SD-Karte anschließe habe ich das gewünschte Verhalten=>> Das Programm startet immer wieder neu da mmc_init einen Fehler> zurückliefert.
Welche Toolchain verwendest du? Bei avr-gcc/AVRLibc wäre ein Neustart
bei return aus main ein Fehlverhalten.
Dein Controller hat bloß 1k RAM. Eine FAT32-Lib zusammen mit der
Tatsache, dass du dir über RAM-Verbrauch wohl keine allzu großen
Gedanken machst (wenn ich die ganzen Strings im RAM sehe), ich schätze
dir wird einfach das RAM ausgegangen sein. Und wenn der Stack in die
Variablen läuft, gibt das dann alle möglichen Effekte.
Stefan Ernst schrieb:> Dein Controller hat bloß 1k RAM. Eine FAT32-Lib zusammen mit der> Tatsache, dass du dir über RAM-Verbrauch wohl keine allzu großen> Gedanken machst (wenn ich die ganzen Strings im RAM sehe), ich schätze> dir wird einfach das RAM ausgegangen sein. Und wenn der Stack in die> Variablen läuft, gibt das dann alle möglichen Effekte.
Der RAM-Verbrauch liegt bei 703 Bytes (68.7%). Da glaube ich nicht das
es zu einem Stack-Überlauf kommt. Oder doch?
Es kommt darauf an, was alles dynamisch allokiert wird.
Ich finde es trotzdem komisch, dass beim Senden eines \n nach
gvUsartPutStringPolling("Startup\n");
das "Startup" nicht mehr angezeigt wird. Das deutet auf einen
Timingfehler hin, den der PC ab einer bestimmten Anzahl kontinuiertlich
übertragenen Zeichen erkennen kann und den ganzen Puffer verwirft.
Mich würde mal die Implementierung der UART Initialisierung
interessieren.
Grüße,
Peter
>uint8_t u8Baudrate>PGM_P pgm_pData = (PGM_P)ptdsUsartConfig;>UBRRH = pgm_read_word(pgm_pData) >> 8; //set higher baudrate value first>UBRRL = pgm_read_word(pgm_pData) & 0xFF; //set second baudrate value>pgm_pData++;
pgm_pData wird als Pointer auf das erste Element in dem Struct
initialisiert, das ist u8Baudrate. Das Ziel ist also ist 8 Bit groß.
Dann wird versucht, ein 16 Bit breites Wort an dieser Stelle zu lesen.
Und danach der Pointer um 1 Byte hochgestellt. Das passt doch alles
nicht zusammen.
Grüße,
Peter
Da wird einfach alles per pgm_read_word gelesen, obwohl alles nur
uint8_t ist.
Die ganze Vorgehensweise, die einzelnen Elemente der Struct über einen
fortlaufenden Pointer zu lesen, ist äußerst fragwürdig. Und zudem auch
völlig überflüssig, und auch noch komplizierter und unübersichtlicher,
als der normale Weg.
PS: Und was ist eigentlich mit der Frage nach der Toolchain und den
Neustarts?
Peter Diener schrieb:> pgm_pData wird als Pointer auf das erste Element in dem Struct> initialisiert, das ist u8Baudrate. Das Ziel ist also ist 8 Bit groß.> Dann wird versucht, ein 16 Bit breites Wort an dieser Stelle zu lesen.> Und danach der Pointer um 1 Byte hochgestellt. Das passt doch alles> nicht zusammen.
Da hast du natürlich recht, habe nun Baudrate auf 16 Bit geändert und
die Initialisierung angepasst.
Mich wundert es nur das es bei anderen Projekten geklappt hatte.
Und genau das führt dazu, dass in UBRR nicht das steht, was dort
hingehört, sondern etwas anderes, das sich zum Teil auch aus u8Mode
zusammensetzt.
Daher kommt der Timingfehler, die UART läuft also mit der falschen
Baudrate. Auch die anderen vorgenommenen Konfigurationen sind von diesem
Grundlegenden Fehler betroffen.
Grüße,
Peter
Stefan Ernst schrieb:> PS: Und was ist eigentlich mit der Frage nach der Toolchain und den> Neustarts?
Als Toolchain verwende ich Eclipse+WinAVR. Das mit dem return hatte ich
aus dem Beispiel zur FAT32 Lib herausgenommen und nicht weiter
hinterfragt.
Und auch das ist Unsinn. Du kannst bei UCSRC nicht mit "|=" arbeiten,
weil dabei der Inhalt aus UBRRH genommen und verodert wird.
Sorry, aber die ganze Funktion ist ziemlicher Murks.