Forum: Mikrocontroller und Digitale Elektronik Wie kann ich die UART des ATmega168 debuggen? - empfange nur Nullen.


von Reto H. (huberret)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe ein Problem mit der UART Schnittstelle an einem ATmega168. Da 
bin ich wohl nicht der einzige, aber die bisherigen Beitrage haben mir 
leider nicht weitergeholfen...

Zuerst zur Hardware: am RX der UART Schnittstelle hängt ein DCF Modul, 
welches mir eine Zeit senden sollte. Das manual sagt folgendes:
______________________________________________________________________ 
__

Antworten des Funkuhrmoduls

Schnittstellenparameter
Geschwindigkeit: 300 bps
Datenbits: 7
Paritätsbit: gerade
Stoppbits: 2

Funktion der Datenausgabe
Eine Antwort des Funkuhrmoduls besteht aus einer Folge von ASCII-Zeichen 
und einem abschließenden Zeichen „CR“.
Der Wertevorrat ist auf die Ziffern 0 ... 9 und die Zeichen : ; < = > ? 
beschränkt. Die Informationen sind stets in den niederwertigen vier Bits 
enthalten. Bit4 und Bit5 eines jeden geantworteten Zeichens sind stets 
gleich Eins, Bit6 ist gleich Null und Bit7 ist immer entsprechend der 
geraden Parität des Zeichens gesetzt. Damit ergeben sich die 
obengenannten 16 Zeichen des Wertevorrates.
______________________________________________________________________ 
__

Das RX Signal an Pin 30 des ATmega168 habe ich mir angeschaut (siehe 
Anhang). Sieht meiner Meinung nach ok aus, Daten kommen und die 300bps 
scheinen auch zu stimmen (kleinste Pulsbreite von 3.33ms).

Nun zum Code: In meiner main routine setze ich erst ein paar Ausgänge, 
welche ich für andere Zwecke brauche (sollte wohl keinen Einfluss auf 
die UART haben), dann kommt der Aufruf der UART init routine und 
schliesslich warte ich auf ein Zeichen (die oberen 4bit lösche ich, 
siehe Beschreibung DCF Modul oben)...
1
#define F_CPU   8000000
2
#define BAUD    300
3
#define UBRR    F_CPU/16/BAUD-1
4
5
#include <avr/io.h>
6
#include <util/delay.h>
7
#include <stdint.h>
8
#include "functions.c"
9
10
 
11
int main (void) { 
12
  DDRB |= (1 << DDB0);                // Setzen des Pins 0 als Ausgang
13
  DDRC  = 0xff;                           // 0xff: alle Pins Ausgänge
14
  DDRD |= (1 << DDD2) | (1 << DDD3) | (1 << DDD4) | (1 << DDD5) | (1 << DDD6) | (1 << DDD7);
15
                            // Pins 2-7 Ausgänge
16
                    
17
  init_USART0(UBRR);                  // initialisiere USART0
18
  
19
  while ('\r' != (receive_1byte_USART0() & 0x0f)) {}
20
21
  ... weiterer Verlauf des Programms...

Das Problem ist nun, dass mein Programm nur weiterläuft wenn ich auf 
eine 0 warte. Bei allen anderen Zahlen und auch dem "CR" (auf welches 
ich eigentlich warten wollte) bleibt es in der while Schleife hängen.

Hat jemand eine Idee wie ich das debuggen könnte?

Hier noch meine init- und Empfangsroutine:
1
void init_USART0(unsigned int baud)
2
{
3
    UBRR0 = baud;                  // Set Baudrate
4
    UCSR0C = (1<<USBS0)|(2<<UCSZ00)|(2<<UPM00);    // 2 Stop Bits, Character Size 7 bit, Even Parity
5
    UCSR0B = (1<<RXEN0);              // Receiver Enable
6
}
7
8
unsigned char receive_1byte_USART0(void)
9
{
10
    loop_until_bit_is_set(UCSR0A, RXC0);
11
    return UDR0;
12
}

Vielen Dank schon mal!

von spess53 (Gast)


Lesenswert?

Hi

Läuft dein AVR auch mit 8MHz?

MfG Spess

von Reto H. (huberret)


Lesenswert?

spess53 schrieb:
> Läuft dein AVR auch mit 8MHz?

Ja, mit
1
_delay_ms(10000);
 pausiert er für exakt 10s...

von guest (Gast)


Lesenswert?

// Berechnungen
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = 
kein Fehler.

#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu 
hoch!
#endif

von Michael (Gast)


Lesenswert?

Versuch einmal das Frequenz-Define über
1
#define F_CPU   8000000UL

einzustellen. Ohne das "UL" am Ende rechnet der Compiler evtl. mit 
16-bit-Werten, ich bin mir allerdings nicht sicher.

von Reto H. (huberret)


Lesenswert?

Leider hat weder die andere Schreibweise des Taktes noch die bessere 
Berechnung der Baudrate eine Änderung gebracht...
Hat noch wer ne Idee?

von Thomas E. (thomase)


Lesenswert?

Ganz einfach.

Nimm' den Sender in Betrieb und sende das empfangene Zeichen wieder 
zurück.

Schliess' das an Hyterperminal oder einen anderes Terminalprogramm 
deiner Wahl an und bring' das Ganze zum Laufen.

Deine Schnittstelleparameter kannst du im Terminal genauso einstellen.

mfg.

von Lutz (Gast)


Lesenswert?

Benutzt Du einen Quarz als Taktquelle?

von Lutz (Gast)


Lesenswert?

Reto H. schrieb:
> Die Informationen sind stets in den niederwertigen vier Bits
> enthalten.

Reto H. schrieb:
> while ('\r' != (receive_1byte_USART0() & 0x0f)) {}

Empfängst Du damit nicht erst ein halbes byte?

von Reto H. (huberret)


Lesenswert?

Lutz schrieb:
> Empfängst Du damit nicht erst ein halbes byte?

Ja, aber ich will mir auch nur die unteren 4 bit anschauen, denn da ist 
die Information drin. z.B.

'\r' = 0x0D =   1101
'0'  = 0x30 = 110000 => untere_4_bit => 0000 = 0x00
'1'  = 0x31 = 110001 => untere_4_bit => 0001 = 0x01
'2'  = 0x32 = 110010 => untere_4_bit => 0010 = 0x02

Wenn ich nur die unteren 4 bit anschaue habe ich die Zahl gleich als 
Wert und beim '\r' funktioniert der Empfang auch.

> benutzt Du einen Quarz als Taktquelle?

Nein den internen Takt. Kann das bei dieser tiefen baudrate ein Problem 
sein? Ich werde den tatsächlichen Takt mal messen...

Thomas Eckmann schrieb:
> Nimm' den Sender in Betrieb und sende das empfangene Zeichen wieder
> zurück.

Gute Idee (wenn der ATmega überhaupt was sinnvolles empfängt) muss nur 
einen Pegelwandler und eine serielle Schnittstelle auftreiben können 
(oder einen USB Adapter)...

von Glaskugel (Gast)


Lesenswert?

>Nein den internen Takt. Kann das bei dieser tiefen baudrate ein Problem
>sein? Ich werde den tatsächlichen Takt mal messen...

Na, abeeeerrrr!! Und dazu hast Du in den bisherigen Beiträgen hier 
nichts gefunden? Das kommt so zwei bis fünf mal die Woche vor.

von Falk B. (falk)


Lesenswert?

@Reto H. (huberret)

>> benutzt Du einen Quarz als Taktquelle?

>Nein den internen Takt.

MÖÖP! Fehler!

> Kann das bei dieser tiefen baudrate ein Problem
>sein?

Ja, denn die Prozentrechung ist da erbarmungslos.

http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART

Halte dich EXAKT an die Anweisungen im Artikel und du wirst Erfolg 
haben.

MfG
Falk

von Reto H. (huberret)


Lesenswert?

Problem gelöst! Aber es war nicht der Takt. Den habe ich gemessen und 
ich konnte nur eine Abweichung von 3 Promille feststellen...

Doch das DCF Modul hat eine fiese Eigenschaft:
1
"Am seriellen Eingang wird der Signalpegel invertiert bezüglich einer Standardschnittstelle (PC o.ä.) erwartet. Der Ausgangspegel an X4 ist nicht invertiert."

Einen PC habe ich ja nicht, sondern den uC, also nochmals invertieren:
=> Eingang nicht invertiert, Ausgang invertiert und schon klappt der 
Empfang!

Danke trotzdem für eure Hilfe!

von Lutz (Gast)


Lesenswert?

Reto H. schrieb:
> Den habe ich gemessen und
> ich konnte nur eine Abweichung von 3 Promille feststellen...

Nichts für ungut, aber das glaube ich Dir nicht. Der interne 
RC-Oszillator ändert sich ja schon um über 6 Promille bei 10 Grad 
Temperaturänderung. Seine "Werksgenauigkeit" liegt bei +/- 100 promille; 
der User kann ihn auf +/- 10 Promille kalibrieren. Du wußtest von all 
dem nichts und hast dann durch den Zufall des Jahres nur 3 Promille 
Abweichung???
Wenn es doch so war, solltest Du
a.) ganz schnell Lotto spielen, weil Du gerade eine Glückssträhne hast 
oder
b.) ganz vorsichtig am Straßenverkehr teilnehmen, weil Du gerade Dein 
Jahresglück auf einmal verbraucht hast

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.