www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART & ATmega324P20PU


Autor: Carsten (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hey Jungs,

ich habe folgendes Problem, ich möchte ein Signal auf eine EIA-232 
Schnittstelle bringen. Als Compiler benutze ich AVR Studio und meine 
Empfangssoftware heißt "Terminal".Als Baudrate sind dort 9600 
eingestellt.

Ich bin dem Tutorial auf der Homepage für UART gefolgt.
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Allerdings ist mir schon früh aufgefallen, dass für meinen yC die 
Bezeichnungen nicht stimmen. Ich habe daher im Datenblatt nachgeschaut 
und nun sieht es so aus:
#include "baud.c"
#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#include <inttypes.h>

//Prototypes
void uart_init(void);


int main(void)
{
uart_init();

while(!(UCSR0A & (1<<UDRE0)))
{

}

UDR0 = 'x';


return 0;
}

void uart_init(void)
{
  UCSR0B |= (1<<TXEN0);  // UART TX einschalten
  UCSR0C |= (1<<UMSEL00);  // Asynchron 8N1 
 
   UBRR1H = UBRR_VAL >> 8;
    UBRR1L = UBRR_VAL & 0xFF;
}

Es kommt allerdings nichts an. Ich bin mir auch extrem unsicher, ob 
meine Änderungen nach dem Datenblatt stimmen. Die Datei "baud.c" ist 
einfach die Berechnung von dem Link ("UART initialisieren"). Der Rest 
ist von weiter unten kopiert und verändert.

In der vorletzten Zeile habe ich 2 Sachen löschen müssen, weil ich dazu 
im datenblatt kein pendant gefunden habe

Danke schonmal im Voraus!

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> #include "baud.c"

ein .c Datei includieren, so was habe ich noch nie gesehen. Geht so was 
überhaupt?

Autor: Michael Frangenberg (startrekmichi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich schrieb:
>> #include "baud.c"
>
> ein .c Datei includieren, so was habe ich noch nie gesehen. Geht so was
> überhaupt?

Klar, warum nicht?

@Carsten:
Was hast du da löschen müssen?

Autor: gerd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich schrieb:
> ein .c Datei includieren, so was habe ich noch nie gesehen. Geht so was
> überhaupt?

Geht, ist aber "unschön".

- gerd

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 

die letzten beiden zuweisungen musste ich weglassen und dazu habe ich 
nicht gefunden

Autor: Michael Frangenberg (startrekmichi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Carsten schrieb:
>
UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1 
>
> die letzten beiden zuweisungen musste ich weglassen und dazu habe ich
> nicht gefunden

Und das ist genau dein Problem.
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
Und lass das "UMSEL00" weg.

Steht bei mir übrigens in der Register Description des USART im 
Datenblatt (Seite 193)

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leider kommt immer noch nichts an. Liegt das evtl am ext. Quarz?

Hast du noch einen Link zu dem Datenblatt?

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> UCSRC |= (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);  // Asynchron 8N1
>
> die letzten beiden zuweisungen musste ich weglassen und dazu habe ich
> nicht gefunden

Kuckst Du Datenblatt [1] Kapitel 16 "USART" (Hint: URSEL gibbet nicht im 
m324p). Zum Debuggen würde ich etwas mehr senden als nur ein einzelnes 
'x'. Und anschließend [2].

HTH

[1] http://atmel.com/dyn/resources/prod_documents/doc8011.pdf
[2] http://www.mikrocontroller.net/articles/AVR_Checkl...

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
korrigiere:

es kommt was an: nur anstatt einem "a" kommt ein "Á"


-.-

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich schreibe morgen weiter, bin jetzt erstmal weg, danke schonmal!!

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sooooo

ich habe mir das Kapitel UART im Datenblatt durchgelesen. Allerdings bin 
ich mir bei den Fuses noch nicht sehr sicher. Wenn ich nun auf Seite 197 
gucke sehe ich die UBBR Werte für meinen externen 16 Mhz Quarz oder? Nur 
wo muss ich die dann setzen?

Muss ich dann meine F_CPU auch auf die 16 Mhz setzen?

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zusätzlich: bei einer eingegeben Frequenz in der baud.c von 1 Mhz(soweit 
ich weiß ist das die interne Frequenz) kommt nur "<0><0>" oder anderer 
Mist raus.

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Allerdings bin ich mir bei den Fuses noch nicht sehr sicher.

Ich habs gesehen im anderen Fred - gut dass bei euch ein Parallelprommer 
im Haus ist.. aber damit bist Du nicht alleine, schau Dir mal [1] an, 
dort ist auch ein sehr praktischer Fuse-Rechner verlinkt.

> Wenn ich nun auf Seite 197 gucke sehe ich die UBBR Werte für meinen
> externen 16 Mhz Quarz oder?

Ja. Dazu muss der Quarz 1. auch in Verwendung und 2. die CKDIV8-Fuse 
adäquat gesetzt sein. Geht übrigens auch flexibler (zumindest wenn man 
einen anständigen Präprozessor hat), siehe Code in [2].

> Nur wo muss ich die dann setzen?

Irgendwo(tm) bevor Du den UART aktivierst. Vorzugsweise macht man das 
gesammelt in einer eigenen Funktion, z.B. 'uart_init()', die die 
Register passend beschreibt und anschließend den UART (nebst ggf. dessen 
IRQs) aktiviert.

> Muss ich dann meine F_CPU auch auf die 16 Mhz setzen?

'Müssen' ist relativ :-) Es ist zumindest zweckmäßig, auch F_CPU auf den 
tatsächlichen Wert zu setzen. Alles andere wäre ein guter Kandidat für 
'code obfuscation'.

> bei einer eingegeben Frequenz in der baud.c von 1 Mhz(soweit
> ich weiß ist das die interne Frequenz) kommt nur "<0><0>" oder anderer
> Mist raus.

Das überrascht mich garnicht :-) Erstens ist der interne Takt recht 
ungenau (den müsste man erst kalibrieren, und dann ist er Temperatur- 
und Spannungsabhängig) und zweitens kann die UART-Einheit 9600 Baud 
nicht gut aus einem Takt von 1MHz erzeugen - das schleppt einen 
systemischen Fehler von etwa 7.5% ein [3], das ist zu viel.

HF

[1] http://www.mikrocontroller.net/articles/AVR_Fuses
[2] http://www.mikrocontroller.net/articles/AVR-GCC-Tu...
[3] http://www.wormfood.net/avrbaudcalc.php

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke ersteinmal für deine antwort:

g457 schrieb:
> Ja. Dazu muss der Quarz 1. auch in Verwendung und 2. die CKDIV8-Fuse
>
> adäquat gesetzt sein. Geht übrigens auch flexibler (zumindest wenn man
>
> einen anständigen Präprozessor hat), siehe Code in [2].

In verwendung heißt, dass ich bei AVR Studio unter "Fuses"-> "SUT_CKSEL" 
einen Ext. Crystal Osc. 8.0 -    MHz auswähle oder? Welche Startuptime 
muss ich da wählen? 4.1ms,0ms, 65 ms? 258 CK,lK CK, 16K CK?

Was meinst du mit Adequat gesetzt sein? Muss ich dann einfach nur im 
selben Menü bei AVR Studio das Häkchen bei CKDIV8 setzen?

den Code habe ich mal in die Datei kopiert: sieht jetzt so aus:
#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#include <inttypes.h>

/* 
  UART-Init: 
Berechnung des Wertes für das Baudratenregister 
aus Taktrate und gewünschter Baudrate
*/
 
#ifndef F_CPU
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
   F_CPU im Makefile definiert werden, eine nochmalige Definition
   hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
   #ifndef/#endif 
 
   Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio 
   verwendet wird und dort eine andere, nicht zur Hardware passende 
   Taktrate eingestellt ist: Dann wird die folgende Definition 
   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) 
   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
   noch nicht definiert: */
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 16000000"
#define F_CPU 16000000UL  // Systemtakt in Hz - Definition als unsigned long beachten 
                         // Ohne ergeben sich unten Fehler in der Berechnung
#endif
 
#define BAUD 9600UL      // Baudrate
 
// 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 


//Prototypes
void uart_init(void);


int main(void)
{
uart_init();

while(!(UCSR0A & (1<<UDRE0)))
{

}

UDR0 = 'e';


return 0;
}

void uart_init(void)
{
    UCSR0B |= (1<<TXEN0);  // UART TX einschalten
    UCSR0C |= (1<<UCSZ00)|(1<<UCSZ01);  // Asynchron 8N1 
 
    UBRR0H = UBRR_VAL >> 8;
     UBRR0L = UBRR_VAL & 0xFF;
}

Allerdings wirft er dann den Error(der ja auch gewollt ist) raus, dass 
die Baudrate zu sehr abweicht.

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe mittlerweile auch schonmal getestet, ob der Quarz verwendet 
wird. Habe dazu die LED Blink funktion übernommen, 16 Mhz eingestellt 
und dann noch zusätzlich bei AVR Studio unter "Fuses"-> "SUT_CKSEL"
einen "Ext. Crystal Osc. 8.0 -    MHz;Startuptime 258 CK,+4.1ms" 
ausgewählt und zusätzlich bei CKDIV8 keinen Haken gesetzt.

Die LED blinkt exakt jede Sekunde.

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Allerdings wirft er dann den Error(der ja auch gewollt ist) raus, dass
> die Baudrate zu sehr abweicht.

Das sollte eigentlich nicht. 16MHz und 9600 Baud, da sollte der Fehler 
bei etwa 0.2% liegen (das ist noch im grünen Bereich).

Achja wie Du die Fuses korrekt setzen musst (willst..), das steht im 
Datenblatt (Kapitel 6 'System clock and clock options'). Mit der 
langsamsten Startup-time macht man sicher nichts verkehrt.

..und schick mal etwas mehr als immer nur ein einzelnes Zeichen, z.B. 
so:
while (1)
{
   while(!(UCSR0A & (1<<UDRE0)))
   {}
  
   UDR0 = 'e';
   _delay_ms(100);  // <- hierfür brauchts noch ein #include <util/delay.h>
}

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Tipps, nach einigem rumprobieren habe ich das Problem 
gefunden. Ich muss in der Zeile
#define BAUD 9600UL      // Baudrate

den Wert auf 600 setzen. Dann funktioniert alles, wenn ich im 
Empfangsprogramm 9600 auswähle. Irgendwo scheint da ein Faktor in der 
Berechnung nicht zu stimmen. Mir egal, es funktioniert!

danke an alle

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Das ist ein Faktor von 16. Sollte zu Denken geben. Steht bei dir noch 
irgendwo 1MHz als Controllertakt?

MfG Spess

Autor: Carsten (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber wo sollte das sein, wenn nicht im Programm selbst? Im Makefile ist 
auch nichts erkenbares ind er Hinsicht zu finden

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
..Faktor 16.. das könnte auch CKDIV8 mit Double-speed-UART sein.. 
irgendwo(tm) ist da jedenfalls noch der Wurm drin :-)

Achja wenn du wissen willst, ob Dein F_CPU tatsächlich auf 16MHz steht 
(oder doch noch irgendwo versaut wird), dann füg bei der 
Baudratenberechnung (und ggf. auch mal bei der 
LED-blinkt-im-Sekundentakt-Routine) ein Statement à la
#if F_CPU == 16000000UL
#error ..iss wirklich 16MHz
#else
#error ..Pustekuchen..
#endif

Warum der Umweg? Tja, leider war es den Erfindern von C/.. nicht 
möglich, eine gute Lösung für das 'Ich will wissen welchen Wert mein 
Define hier an genau dieser Stelle im Code tatsächlich hat'-Problem zu 
finden. Kleiner (nerviger) Workaround und man kanns zumindest auf 
gewünschte (bekannte) Werte abtesten.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.