Forum: Mikrocontroller und Digitale Elektronik RS232 / UART mit Atmega8 auf Pollin Evaluation Board


von T. F. (n3ssaja)


Lesenswert?

Hallo zusammen,
ich besitze jetzt das Pollin Evalutation Board und bin gerade dabei die 
RS232 Schnittstelle mit einem Atmega8 in Betrieb zu nehmen.
Die Baudrate soll 9600 sein. Diese habe ich dann mittels der CPU 
Taktfrequenz für die Register UBRR umgerechnet (vgl. Code). Als Test 
schicke ich das ASCII Zeichen "B" und lese es am PC mit einem Terminal 
Programm aus.
Das erstaunliche ist aber dass beim Auslesen mit 9600 Baud am Terminal 
kein "B" ankommt. Erst wenn ich am Terminal Programm eine Baudrate von 
600 einstelle wird das Zeichen richtig übertragen.
Wodrann kann das liegen? Verwendet der Mikrocontroller eine andere 
Taktfrequenz für die RS232 Schnittstelle?
Wäre schon wenn ihr mir weiterhelfen könnt.
1
#include <avr/io.h>
2
3
4
#define F_CPU       16000000UL
5
#define BAUD        9600UL
6
#define UBRR_BAUD   ((F_CPU+(BAUD*16UL))/(BAUD*16UL))-1   
7
8
9
void init_uart(void)
10
{  
11
  // Baudrate einstellen 
12
    UBRRH = (uint8_t) (UBRR_BAUD>>8);
13
    UBRRL = (uint8_t) (UBRR_BAUD);
14
15
    // Aktivieren von receiver und transmitter
16
    UCSRB = (1<<RXEN)|(1<<TXEN);                    
17
18
    // Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
19
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); 
20
}
21
22
23
24
void transmit_uart(unsigned char data)
25
{
26
  while(!(UCSRA & (1<<UDRE)))
27
      ; 
28
  UDR = data;
29
}
30
31
32
33
int main(void)
34
{
35
  unsigned char data = 66; //entspricht einem "B"
36
  init_uart();
37
    
38
  while (1)
39
  {  
40
    transmit_uart(data);
41
    delay_ms(1500);    
42
  }
43
  return 0;
44
}

von Hc Z. (mizch)


Lesenswert?

Dann läuft Dein ATmega8 mit einem sechzehntel der gewünschten 
Quarzfrequenz, nämlich mit den internen 1 MHz.  Beschäftige Dich mit 
Fuses, um ihn umzustellen.  Die Frequenz hat er nämlich im 
Auslieferungszustand.

von g457 (Gast)


Lesenswert?

> #define UBRR_BAUD   ((F_CPU+(BAUD*16UL))/(BAUD*16UL))-1
                                                       ^^
> UBRRH = (uint8_t) (UBRR_BAUD>>8);
                              ^^^

..autschgerl..

von T. F. (n3ssaja)


Lesenswert?

@Hc Zimmerer:
Das man noch spezielle Fuse Bits setzen muss war mir nicht bewusst. 
Danke für den Tip, werde direkt nachschauen.

@g457:
Keine Ahnung was du mir mit deinem Beitrag sagen willst?! Wohl einfach 
zu schnell getippt, denn der Code ist korrekt. Vielleicht beim nächsten 
mal etwas ausführlicher antworten.

von g457 (Gast)


Lesenswert?

> Keine Ahnung was du mir mit deinem Beitrag sagen willst?! [..] denn der
> Code ist korrekt.

Nur zufällig tut er das was Du augenscheinlich willst dass er tut. Setzt 
statt des Shift-Operators mal einen Operator mit einer höheren Präzedenz 
ein, z.B. '/', und mach dann aus der 8 ein 256 - das bewirkt auf den 
ersten Blick das selbe (8 Stellen nach rechts schieben ist semantisch 
äquivalent mit Teilen durch 256). Aber hier wäre das eben nicht 
wirkungsäquivalent. Deswegen bei zusammengesetzen Defines ∗immer∗ eine 
Klammer aussen rum setzen, das spart (später) viel Sucharbeit. Hier 
gehts zufällig gut, ein ander mal Suchst Du dir einen Wolf.

Der eigentliche Fehler (falsche Taktquelle) wurde ja schon genannt.

HTH und nix für ungut.

von T. F. (n3ssaja)


Lesenswert?

Hi g457,

das sehe ich ein. Demzufolge müsste es:
1
#define UBRR_BAUD   (((F_CPU+(BAUD*16UL))/(BAUD*16UL))-1)
2
UBRRH = (uint8_t) (UBRR_BAUD/256);
lauten?

Die Fuse Bits einstellungen hab ich jetzt in AVR Studio gefunden. Da ich 
ein ext. 16MHZ Quarz benutze habe ich das Fuse Bit jetzt auf:

Ext. Crystal/Resonator High Freq.; Start-up time: 16K CK + 0 ms

gesetzt. Die Übertragung der Baudrate klappt jetzt einwandfrei. Jedoch 
habe ich jetzt das Problem das ich meinen ATmega nicht mehr per ISP mit 
neuen Code in AVR beschrieben kann? Wahrscheinlich habe ich jetzt keine 
möglichkeit mehr die Fusebits umzustellen oder?

von Hc Z. (mizch)


Lesenswert?

Das sollte schon klappen, wenn Du nur die Taktfuses umgesetzt hast. Es 
sei denn, Du hättest die RSTDSBL-Fuse (o.ä.) gesetzt.  Dann allerdings 
hättest Du den Reset abgeklemmt, und den brauchst Du zum Programmieren.

von T. F. (n3ssaja)


Angehängte Dateien:

Lesenswert?

Nein ich habe wirklich nur die Clock umgestellt. Alles merkwürdig.
Im Anhang ist die Fehlermeldung zu sehen.
Vielleicht schafft mein ISP Programmer das jetzt einfach nicht mehr. 
Gibt es eine Möglichkeit den µC wieder auf Werkseinstellungen zurück zu 
setzen?

von Hc Z. (mizch)


Lesenswert?

Das sieht ja so aus, als würde der µC noch erkannt.  Demnach hast Du 
Dich nicht ausgesperrt.  Somit müsste es doch gehen, die Fuses auf den 
alten Wert zurückzusetzen?  Was das bringen sollte, ist mir allerdings 
rätselhaft.  Normalerweise machen niedrigere Taktfrequenzen 
Schwierigkeiten, wenn man vergisst, die ISP-Frequenz herunterzusetzen 
und nicht umgekehrt.

Schreib mal, mit welchem Programmer Du arbeitest, vielleicht hat dann 
jemand einen Tipp.

von g457 (Gast)


Lesenswert?

> das sehe ich ein. Demzufolge müsste es:
>
> #define UBRR_BAUD   (((F_CPU+(BAUD*16UL))/(BAUD*16UL))-1)
> UBRRH = (uint8_t) (UBRR_BAUD/256);

..müssen ist relativ :-) 'Dringend sollen' bis 'sehr zu empfehlen' 
triffts besser. Obiges Define ist jetzt (fast [1]) 'richtig' (also schön 
geklammert). Die Berechnung vom UBRRH ist auch 'richtig' und 
funktioniert so auch korrekt (und wie zu erwarten). Ob man (hier) 
Bitschieben oder Division bevorzugt ist letztenendes Geschmackssache - 
die Hauptsache ist dess es unmittelbar austauschbar und trotzdem 
semantisch äquivalent ist :-)

Ad ISP-Problem: Das hört sich sehr nach SPIEN oder RSTDISBL an, da hilft 
dann nur noch [2]. Oder ist nur das Programmiekabel abgerutscht?

HTH

[1] Zum impliziten Runden addiert man beim Dividenden die Hälfte des 
Divisors, hier also 'BAUD *16UL /2' oder kurz 'BAUD *8'.
[2] 
http://www.mikrocontroller.net/articles/AVR_Fuses#SPIEN.2C_DWEN_und_RSTDISBL

von T. F. (n3ssaja)


Lesenswert?

Der Programmer scheint mir nicht weit verbreitet zu sein. Angeboten 
wqird er auf http://www.obd-diag.de/
Name:  USB ISP Programmer für Atmel µC

Gibt es vielleicht einen Programmer den ihr mir empfehlen könnt, womit 
ich nicht derartige Probleme bekomme? Vielen Dank an dieser Stelle schon 
einmal für eure Mühe

von T. F. (n3ssaja)


Lesenswert?

Hey g457,

auch dir danke für die Hilfe. Habe noch ein fabrikneuen ATmega8 gehabt, 
damit klappts jetzt wieder wie gewohnt, also ist das Kabel definitiv 
nicht abgerutscht ;-)
Von den Fuse Bits werde ich jetzt vorerst meine Finger lassen. Für meine 
Versuche reicht vorerst der interne Takt von 1MHz.
Eine letzte Frage hätte ich noch. Wenn ich:
1
#define UBRR_BAUD   ((F_CPU+(BAUD*256UL))/(BAUD*256UL))-1
setze, erreiche ich es auch das ich am Hyperterminal mit den geforderten 
9600Baud auslesen kann. Ist diese Art der Manipulation gültig oder ist 
das eher gefuscht? ;-)

von g457 (Gast)


Lesenswert?

> Ist diese Art der Manipulation gültig oder ist das eher gefuscht? ;-)

Ähm. Letztenendes kannst Du machen was Du willst (naja fast..). Die 
Frage ist ob Du Dir selbst einen Gefallen tust damit.. Ich würds nicht 
machen.

Entweder den Wert fest eintragen (z.B. von [0] oder händisch 
ausgerechnet), mit einem entsprechenden Kommentar versehen, oder den 
Umgang mit den Fuses lernen (Drei kurze Anmerkungen hierzu: Erstens muss 
man bei manchen GUI-Programmer die Fuses erst explizit auslesen bevor 
man sie sinnvoll in-place ändern kann, zweitens unterscheiden sich die 
Anzeigelogiken gelegentlich (Atmel-Speak: 'Fuse programmieren == 
durchbrennen == 0, Fuse löschen == intakt == 1', 
$nichtsowirklichüberwältigendesoftware-Speak 'Fuse programmieren == 
intakt == 1, fuse löschen == durchbrennen == 0'), drittens lohnt es sich 
zumindest bei den Fuses den relevanten Teil vom Handbuch auszudrucken um 
mit Bleistift drauf rumzukritzeln.. ausserdem gibts recht praktische 
Fuse-Rechner, z.B. [1]).

Aber ich würde unter keinen Umständen eine solche Formel 'nur' 
dahingehend manipulieren, dass sie auf die derzeit speziellen Umstände 
passt. Die Manipulation findet man nämlich später nur schwer wieder :-)

Ooder viel Du setzt F_CPU auf den tatsächlchen Wert.. so einfach gings 
auch ;-)

[0] http://www.wormfood.net/avrbaudcalc.php
[1] http://www.engbedded.com/fusecalc/

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.