UART mit mega168 produziert falsche Daten

sthomson

Neues Mitglied
29. Mai 2010
1
0
0
Sprachen
Hallo

Ich arbeite mit einem myAVR Board MK1 LPT und dem myAVR Workpad.
Der mega 168 wird dort über einen 3686400 Hz Quarz getacktet.

Um die UART Ein- und Ausgabe an einem mega168 zu testen habe ich mir Funktionen für UART Eingabe und Ausgabe in C zusammengstellt.
In der Hauptschleife übergebe ich den Wert dann einfach.

Der Test liefert dann allerding höchst merkwürdige Ergebnisse. :confused: Der Ausgabewert stimmt nicht mit dem Eingabewert überein. Ich schicke z.B. 0x47 und es kommt eine 0xF8 zurück.

Woran liegt das? Wenn ich das Ganze auf Basis des mega8 mache, klappt es wunderbar.

Was mache ich falsch? Bautrate 9600 und Parität 8N1 stimmen eigentlich.

Nachfolgend mal das Programm in C
VIelleicht sieht jemand woran es liegt.


Grüße
Sven




//-------------------------------------------------------------------------
// Titel : Test UART mit 168
//-------------------------------------------------------------------------
// Funktion :
// Schaltung :
//-------------------------------------------------------------------------
// Prozessor : ATmega168
// Takt : 3686400 Hz
// Sprache : C
// Datum : 28.5.2010
// Version : 1.0
// Autor :
// Programmer:
// Port :
//-------------------------------------------------------------------------
// created by myAVR-CodeWizard
//-------------------------------------------------------------------------
//
#define F_CPU 3686400
#include <avr\io.h>
#include <avr\interrupt.h>
#define BAUD 9600
//--------------------------------------------------------------------
// USART_RX_vect - UART Interrupt bei Datenempfang komplett
//--------------------------------------------------------------------
ISR(USART_RX_vect)
{
// Hier Interruptbehandlung
}
//--------------------------------------------------------------------
// USART_UDRE_vect - UART Interrupt bei Senderegister leer
//--------------------------------------------------------------------
ISR(USART_UDRE_vect)
{
// Hier Interruptbehandlung
}
//--------------------------------------------------------------------
// USART_TX_vect - UART Interrupt bei Sendevorgang beendet
//--------------------------------------------------------------------
ISR(USART_TX_vect)
{
// Hier Interruptbehandlung
}

//----------------------------------------------------------------------
// Titel : C-Funktion Zeichen zu UART senden.
//----------------------------------------------------------------------
// Funktion : ...
// IN : char data
// OUT : ...
//----------------------------------------------------------------------
void uartPutChar(char data)
{
//warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
while (!(UCSR0A&32));
//sende
UDR0=data;
}
//----------------------------------------------------------------------
// Titel : C-Funktion Zeichen von UART holen.
//----------------------------------------------------------------------
// Funktion : ...
// IN : ...
// OUT : data
//----------------------------------------------------------------------
char uartGetChar()
{
char data=0;
//warte bis RX-complete RXC UCSRA / USR bei z.B.: AT090S2313
while (!(UCSR0A&128));
//empfangen
data=UDR0;
return data;
}
//----------------------------------------------------------------------
// Titel : C-Funktion Zeichenkette zu UART senden.
//----------------------------------------------------------------------
// Funktion : ...
// IN : char *buffer, Zeichenkette mit NUll abgeschlossen
// OUT : ...
//----------------------------------------------------------------------
void uartPutString(const char *buffer)
{
for (int i=0; buffer !=0;i++) uartPutChar (buffer);
}
//------------------------------------------------------------------------
// Initialisierungen
//------------------------------------------------------------------------
void init()
{
// UART initialisieren
sbi(UCSR0B,3); // TX aktiv
sbi(UCSR0B,4); // RX aktivieren
UBRR0=((F_CPU/BAUD)/16)-1; // Baudrate festlegen
sbi(UCSR0B,7); // UART Interrupt bei Datenempfang komplett
sbi(UCSR0B,5); // UART Interrupt bei Senderegister leer
sbi(UCSR0B,6); // UART Interrupt bei Sendevorgang beendet
//--- Interrupts erlauben ---
sei();
}

/////////////////////////////////////////////////////////////////////////////
// Main-Funktion
/////////////////////////////////////////////////////////////////////////////
main()
{
init(); // Initialisierungen
while (true) // Mainloop-Begin
{
char zeichen;

zeichen=uartGetChar();
uartPutChar(zeichen);


} // Mainloop-Ende
}
//---------------------------------------------------------------------------
 
Hallo Sven,
ich kann in deinem Sourcecode direkt keinen Fehler finden. Die Berechnung der Übertragungsrate habe ich nicht überprüft, ich gehe mal davon aus, dass diese stimmt, bzw. daß die Abweichung, wenn es eine gibt, innerhalb der zulässigen Fehlergrenzen liegt.

Was ich nicht verstehe, du hast mehrere Interrupts des USART aktiviert, in den ISR gibt es keinen Code (hast du hier noch etwas vorgesehen) und du pollst die Flags UsartReceiveComplete (RXC) und UsartDataReady (UDR). Deaktiviere mal die Interrupts, wenn du posst brauchst du diese ja eigentlich nicht.

Noch ein Tipp: Nutze am besten die Registerbit-Namen, also anstelle
while (!(UCSR0A&128)), schreibst du while(!UCSR0A & (1<<RXC0)) so wird dein Code leserlicher und auch schneller anpassbarer.


EDIT: Was mir gerade noch eingefallen ist: Das Fusebit CKDIV8 beim Mega168 hast du berücksichtigt? ;)

Gruß,
Dirk
 
Achtung: In die Falle bin ich vor 2 Wochen auch reingefallen .... exakt mit komischen Zeichen über RS232. Das dumme ist, dass diese FUSE via default eingeschaltet ist und der Mega mit 1/8 seiner Speed rennt. Weiß der Geier was das soll aber ......

Kaum macht mer's richtig, scho goats:cool:

Grüße,
Ma
 
Hallo Markus,
... Das dumme ist, dass diese FUSE via default eingeschaltet ist und der Mega mit 1/8 seiner Speed rennt. Weiß der Geier was das soll aber ...

im Clock Prescale Register (CLKPR), läßt sich der Prescaler für den Systemclock per Software umstellen.

Gruß,
Dirk

CLKDIV8: This feature should be used if the selected clock source has a higher frequency than the maximum frequency of the device at the present operating conditions. Note that any value can be written to the CLKPS bits regardless of the CKDIV8 Fuse setting.
 
Hi Drik,

danke für Deinen Kommentar. Der Hinweis auf das Datenblatt ist wichtig und wer lesen kann ist deutlich im Vorteil.

Aber Du weißt wie das ist, wenn man denkt man hätte a bissle ne Ahnung und von anderen Megas her kommt welche die Funktion nicht haben dann fällt man da automatisch rein.

Die Frage, warum das Ding via Default aktiv ist, ist aber immer noch nicht geklärt. Denn so muss man dem Mega168 erst SW verpassen und das Register beschreiben, bis es funktioniert.

Hmmmm, aber auf dem Weg haben wir wieder etwas gelernt.

Grüße,
Ma
 
Hi Markus,

auf CKDIV8 bin ich schon öfters reingefallen :rolleyes: Der Grund für CKDIV8 ist mir auch nicht hundertprozentig klar, ich nehme mal an, der Systemtakt vor dem Vorteiler darf auch bei low voltage hoch sein, zum Beispiel externer Quarz mit 16MHz. Der tatsächliche Systemtakt nach Vorteiler, mit dem der AVR läuft, muss dann verringert sein, dafür sorgt CKDIV8 (werkseitig eingestellt). ... vermute ich mal ;) Oder das Fusebit ist einfach da, damit wir ein bisschen mehr Spaß haben :D

Gruß,
Dirk
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)