Forum: Mikrocontroller und Digitale Elektronik UART "kauderwelsch"


von Martin K. (thereallife)


Lesenswert?

Moin Leute,
ich sitze grade zum ersten mal am UART und muss gestehen 
hundertprozentig klar ist mir das ganze noch nicht.
Aber gut mit etwas hin und hergezappel und dem Tutorial gelesen, bekomme 
ich schonmal eine Ausgabe über den TX hin,
kurz zu meinem Aufbau:
Ich habe einen ATmega32A, dessen TX in den TX pin vom Arduino UNO 
gesteckt ist, die Masse habe ich von beiden ebenfalls verbunden.

Mein Code sieht folgendermaßen aus:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#ifndef F_CPU
4
#define F_CPU 1000000UL
5
#endif
6
#include <stdio.h>
7
#define BAUD 9600L 
8
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
9
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
10
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) // Fehler in Promille
11
12
13
int uart_putchar(char c, FILE *stream)
14
{
15
  loop_until_bit_is_set(UCSRA, UDRE);
16
  UDR = c;
17
  return 0;
18
}
19
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
20
21
22
23
#include <util/delay.h>
24
25
void USART_Init( unsigned int baud )
26
{
27
  UBRRH = UBRR_VAL >>8;
28
  UBRRL = UBRR_VAL & 0xFF;
29
  UCSRB = (1<<RXEN)|(1<<TXEN);
30
  UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
31
}
32
33
34
int main(void)
35
{
36
  stdout = &mystdout;
37
  USART_Init(BAUD);
38
  while(1)
39
  {
40
    _delay_ms(1000);
41
    printf("Hallo");
42
  }
43
}

Im Seriellen Monitor von Arduino kommt allerdings nur Kauderwelsch 
heraus:
÷÷÷××÷÷÷÷÷÷÷÷×÷÷÷Ö÷õ÷÷÷÷÷÷÷÷÷÷÷÷÷þ×÷÷÷÷õö÷÷ö÷÷õ÷÷õ÷÷ç÷÷ç÷÷ö÷÷÷÷÷÷÷÷÷÷÷÷÷ 
÷÷÷÷÷þ÷÷÷÷þ÷÷Ö÷þ÷Öõ÷÷õ÷÷þ÷þ÷÷÷Öþ÷÷÷÷Ö÷÷÷÷þ÷÷÷÷×÷÷÷þ÷÷÷÷÷÷÷÷Ö÷÷÷÷÷÷÷÷÷÷ö÷ 
÷÷

Die Baudrate ist im Seriellen Fenster von arduino ebenfalls auf 9600.

Ich denke mal irgendwo hab ich die Baudrate falsch berechnet oder etwas 
vergessen, sehen tu ich den fehler allerdings nicht.

Wäre super wenn mir da jmd weiterhelfen könnte.

Grüße
Martin

von Georg G. (df2au)


Lesenswert?

Interner RC Oszillator verwendet? Der liegt manchmal etwas daneben.

von spess53 (Gast)


Lesenswert?

Hi

>Interner RC Oszillator verwendet? Der liegt manchmal etwas daneben.

Braucht es nicht. Bei 1MHz und 9600Bd beträgt der Baudratenfehler 7%.

MfG Spess

von nichtGast (Gast)


Lesenswert?

Martin Kathke schrieb:
> Ich habe einen ATmega32A, dessen TX in den TX pin vom Arduino UNO
> gesteckt ist

TX sollte mit RX verbunden werden, wenn ich mich recht erinnere. Aber da 
du ja anscheinend schon was empfängst hast du dich wohl verschrieben.

von Martin K. (thereallife)


Lesenswert?

nichtGast schrieb:
> TX sollte mit RX verbunden werden, wenn ich mich recht erinnere. Aber da
> du ja anscheinend schon was empfängst hast du dich wohl verschrieben.

Bist du dir da sicher?!
Ich habe den Arduino UNO als DIL Variante und habe den Prozessor einfach 
abgezogen und Kabel von meinem ATmega32A rübergezogen.
Hab in DatenBlatt geschaut wo TX und RX liegen und entsprechend 
verbunden.
Ich will ja nur den kleinen Chip vom Arduino als Serielle Schnittstelle 
zum debuggen nutzen ;)

Georg G. schrieb:
> Interner RC Oszillator verwendet?

nein
hab auch leider kein quarz da

von spess53 (Gast)


Lesenswert?

Hi

>Ich will ja nur den kleinen Chip vom Arduino als Serielle Schnittstelle
>zum debuggen nutzen ;)

Begreife es endlich: 9600Bd gehen nicht mit deinem Programm. Die einzige 
Möglichkeit wäre Doublespeed. Dazu must du aber die Baudratenberechnung 
ändern.

MfG Spess

von Martin K. (thereallife)


Lesenswert?

spess53 schrieb:
> Begreife es endlich: 9600Bd gehen nicht mit deinem Programm. Die einzige
> Möglichkeit wäre Doublespeed. Dazu must du aber die Baudratenberechnung
> ändern.
>
> MfG Spess

Verstehe leider nur Bahnhof :S

von Klaus 2. (klaus2m5)


Lesenswert?

Martin Kathke schrieb:
> Georg G. schrieb:
>> Interner RC Oszillator verwendet?
>
> nein
> hab auch leider kein quarz da

WAS VERWENDEST DU? Lass Dir nicht alles aus der Nase ziehen.

Und Spess hat natürlich Recht, bei 1Mhz wird das mit 9600 Baud sowieso 
nichts.

: Bearbeitet durch User
von Martin K. (thereallife)


Lesenswert?

Klaus 2m5 schrieb:
> WAS VERWENDEST DU? Lass Dir nicht alles aus der Nase ziehen.

Wenn ich keinen Quarz habe werde ich wohl den Internen Oszillator nutzen 
und da oben im Code #define F_CPU 1000000UL steht, läuft der wohl mit 
1mHz ;)
Oder versteh ich dich falsch und du wolltest andere Informationen?

Klaus 2m5 schrieb:
> Und Spess hat natürlich Recht, bei 1Mhz wird das mit 9600 Baud sowieso
> nichts.

Und auf was müsste ich gehen das es läuft?
im Tutorial machen sie das auch mit 1MHz

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Verstehe leider nur Bahnhof :S

Dann lies die Antworten:

Beitrag "Re: UART "kauderwelsch""

MfG Spess

von Rafl (Gast)


Lesenswert?

Martin Kathke schrieb:
> läuft der wohl mit
> 1mHz
1 Milliherz? Dann ist klar wieso der UART nicht richtig funktioniert...

von Martin K. (thereallife)


Lesenswert?

Rafl schrieb:
> 1 Milliherz? Dann ist klar wieso der UART nicht richtig funktioniert...

Tippfehler...

von Martin K. (thereallife)


Lesenswert?

Hab die Geschwindigkeit einfach mal auf 8Mhz angehoben.
Jetzt läufts. Wüsste denoch gerne warum das auf 1Mhz nicht läuft 
schließelich machen die das im Tutorial ja auch

von Klaus 2. (klaus2m5)


Lesenswert?

Martin Kathke schrieb:
> Und auf was müsste ich gehen das es läuft?
> im Tutorial machen sie das auch mit 1MHz
>
> http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART

Du hast leider einen wesentlichen Teil weggelassen, nämlich die 
Umschaltung auf double speed:
1
#include <avr/io.h> 
2
#define F_CPU 1000000 /* evtl. bereits via Compilerparameter definiert */
3
#define BAUD 9600
4
#include <util/setbaud.h>
5
 
6
void uart_init(void)   
7
{
8
   UBRRH = UBRRH_VALUE;
9
   UBRRL = UBRRL_VALUE;
10
   /* evtl. verkuerzt falls Register aufeinanderfolgen (vgl. Datenblatt)
11
      UBRR = UBRR_VALUE;
12
   */
13
#if USE_2X
14
   /* U2X-Modus erforderlich */
15
   UCSRA |= (1 << U2X);
16
#else
17
   /* U2X-Modus nicht erforderlich */
18
   UCSRA &= ~(1 << U2X);
19
#endif

von spess53 (Gast)


Lesenswert?

Hi

>Und auf was müsste ich gehen das es läuft?
>im Tutorial machen sie das auch mit 1MHz

Ich sehe dort

#define F_CPU 4000000UL

MfG Spess

von Martin K. (thereallife)


Lesenswert?

Danke euch!

von holger (Gast)


Lesenswert?

>Hab die Geschwindigkeit einfach mal auf 8Mhz angehoben.
>Jetzt läufts. Wüsste denoch gerne warum das auf 1Mhz nicht läuft
>schließelich machen die das im Tutorial ja auch

Weil

#define F_CPU 1000000UL

den Takt nicht umstellt. Das ist nur eine Angabe
wie hoch der Takt ist. DU musst schon selber dafür
sorgen das diese Angabe auch stimmt.

von Holger L. (max5v)


Lesenswert?

Übrigens, wenn du noch Probleme bei der Übertragung haben solltest, 
speziell mit der Anzahl der übertragenen Datenbits, solltest du dir 
diese Zeile noch einmal anschauen.

Martin Kathke schrieb:
> UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);

von c-hater (Gast)


Lesenswert?

spess53 schrieb:

>>Interner RC Oszillator verwendet? Der liegt manchmal etwas daneben.
>
> Braucht es nicht. Bei 1MHz und 9600Bd beträgt der Baudratenfehler 7%.

Richtig.

Wenn aber zufällig der interne Taktgeber seine 10% Toleranz der 
Werkskalibrierung in die richtige Richtung ausnutzt, geht's dann doch 
wieder...

Und wenn man sich nicht auf die Werkskalibrierung verläßt, sondern das 
selber gezielt macht, geht's sogar ganz sicher. Jedenfalls solange die 
Temperatur sich nicht nennenswert ändert. Und sogar dagegen kann man was 
machen, denn der Tiny24 besitzt ja einen internen Temperatursensor und 
eine interne Referenzspannungsquelle.

Also: mit der entsprechenden Software betrieben, genügt einmaliges 
Kalibrieren anhand eines bekannten Signals (ich würde eine Folge von 
ununterbrochen gesendeten 'U's empfehlen) während man das Teil mit einem 
Fön aufheizt. Danach läuft die Scheiße bis in alle Ewigkeit. Amen.

von Martin K. (thereallife)


Lesenswert?

holger schrieb:
> Weil
>
> #define F_CPU 1000000UL
>
> den Takt nicht umstellt. Das ist nur eine Angabe
> wie hoch der Takt ist. DU musst schon selber dafür
> sorgen das diese Angabe auch stimmt.

Ich weiß, allerdings geh ich davon aus, dass wenn er das in dem Tutorial 
macht seine Taktfrequenz auch auf 1Mhz steht.

Holger L. schrieb:
> Übrigens, wenn du noch Probleme bei der Übertragung haben solltest,
> speziell mit der Anzahl der übertragenen Datenbits, solltest du dir
> diese Zeile noch einmal anschauen.
>
> Martin Kathke schrieb:
>> UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0)

Das hab ich ich zwar direkt aus dem Datenblatt von Atmel übernommen aber 
ich werde es mir nochmal genauer anschauen, so ganz hab ich UART noch 
nicht verstanden. (Dich wundert wahrscheinlich die 3 beim UCSZO ?!) Ich 
lese nochmal nach ;)

@c-hater klingt interessant, aber ich bleib für mich erstmal bei den 
basics bis das sicher sitzt !

von Mike (Gast)


Lesenswert?

Martin Kathke schrieb:
> Ich weiß, allerdings geh ich davon aus, dass wenn er das in dem Tutorial
> macht seine Taktfrequenz auch auf 1Mhz steht.

Wenn du es nicht weißt, solltest du es überprüfen. Schreib ein kurzes 
Programm, in dem du eine LED z.B. im 1 Hz Rhythmus blinken läßt. Wenn 
sie das tatsächlich tut, stimmen Geschwindigkeitsangabe und 
Geschwindigkeit überein.

von Martin K. (thereallife)


Lesenswert?

Mike schrieb:
> Wenn du es nicht weißt, solltest du es überprüfen. Schreib ein kurzes
> Programm, in dem du eine LED z.B. im 1 Hz Rhythmus blinken läßt. Wenn
> sie das tatsächlich tut, stimmen Geschwindigkeitsangabe und
> Geschwindigkeit überein.

Damit überprüfe ich doch nur meine eigene Taktfrequenz?!
Und da bin ich mir sicher was ich in den Fuses eingestellt habe

von Mike (Gast)


Lesenswert?

Martin Kathke schrieb:
> Damit überprüfe ich doch nur meine eigene Taktfrequenz?!

Nein, wenn der Prozessor mit einer anderen Frequenz läuft, als du im 
Programm oder in der IDE als Prozessorfrequenz eingestellt ist, werden 
die daraus abgeleiteten Wert nicht zur tatsächlichen Taktfrequenz passen 
und die LED blinkt eben nicht in dem im Programm festgelegten Takt.

von Kaj (Gast)


Lesenswert?

Martin Kathke schrieb:
> Hab die Geschwindigkeit einfach mal auf 8Mhz angehoben.
> Jetzt läufts

Unter der Annahme das du im Code einfach aus
1
#define F_CPU 1000000UL
ein
1
#define F_CPU 8000000UL
gemacht hast, und es jetzt geht, würde ich vermuten das die CKDIV8-Fuse 
gesetzt ist...

von Holger L. (max5v)


Lesenswert?

Martin Kathke schrieb:
> Holger L. schrieb:
>> Übrigens, wenn du noch Probleme bei der Übertragung haben solltest,
>> speziell mit der Anzahl der übertragenen Datenbits, solltest du dir
>> diese Zeile noch einmal anschauen.
>>
>> Martin Kathke schrieb:
>>> UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0)
>
> Das hab ich ich zwar direkt aus dem Datenblatt von Atmel übernommen aber
> ich werde es mir nochmal genauer anschauen, so ganz hab ich UART noch
> nicht verstanden. (Dich wundert wahrscheinlich die 3 beim UCSZO ?!) Ich
> lese nochmal nach ;)

Entschuldige, ich wollte keine Verwirrung stiften, das war ein 
Schnellschuß.
Allerdings entzieht sich mir die Logik warum ausgerechnet in einem 
Beispielcode so ein Mist steht der anscheinend nur dafür da ist damit es 
hübsch aussieht.
Wenn man nur UCSZ1 setzten möchte schreibt man doch auch nicht 
(2<<UCSZ0).
Deshalb nutze ich persönlich nur die ausführliche Schreibweise :
UCSRC = (1<<URSEL)|(1<<USBS)|(1<<UCSZ0)|(1<<UCSZ1);

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.