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-Tutorial/Der_UART#Die_Hardware
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:
1
#include"baud.c"
2
#include<avr/io.h>
3
#include<util/delay.h>
4
#include<stdint.h>
5
#include<inttypes.h>
6
7
//Prototypes
8
voiduart_init(void);
9
10
11
intmain(void)
12
{
13
uart_init();
14
15
while(!(UCSR0A&(1<<UDRE0)))
16
{
17
18
}
19
20
UDR0='x';
21
22
23
return0;
24
}
25
26
voiduart_init(void)
27
{
28
UCSR0B|=(1<<TXEN0);// UART TX einschalten
29
UCSR0C|=(1<<UMSEL00);// Asynchron 8N1
30
31
UBRR1H=UBRR_VAL>>8;
32
UBRR1L=UBRR_VAL&0xFF;
33
}
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!
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?
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?
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.
> 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-Tutorial/Der_UART
[3] http://www.wormfood.net/avrbaudcalc.php
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:
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<stdint.h>
4
#include<inttypes.h>
5
6
/*
7
UART-Init:
8
Berechnung des Wertes für das Baudratenregister
9
aus Taktrate und gewünschter Baudrate
10
*/
11
12
#ifndef F_CPU
13
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
14
F_CPU im Makefile definiert werden, eine nochmalige Definition
15
hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
16
#ifndef/#endif
17
18
Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio
19
verwendet wird und dort eine andere, nicht zur Hardware passende
20
Taktrate eingestellt ist: Dann wird die folgende Definition
21
nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?)
22
von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
23
noch nicht definiert: */
24
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 16000000"
25
#define F_CPU 16000000UL // Systemtakt in Hz - Definition als unsigned long beachten
26
// Ohne ergeben sich unten Fehler in der Berechnung
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.
> 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:
1
while (1)
2
{
3
while(!(UCSR0A & (1<<UDRE0)))
4
{}
5
6
UDR0 = 'e';
7
_delay_ms(100); // <- hierfür brauchts noch ein #include <util/delay.h>
Danke für die Tipps, nach einigem rumprobieren habe ich das Problem
gefunden. Ich muss in der Zeile
1
#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
..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
1
#if F_CPU == 16000000UL
2
#error ..iss wirklich 16MHz
3
#else
4
#error ..Pustekuchen..
5
#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.