Forum: Mikrocontroller und Digitale Elektronik Komisches Verhalten bei CPU-Frequenz und UART


von Stephan K. (dustpuppy)


Lesenswert?

Hi,
ich habe ein sehr seltsames Problem.
Ich benutze eine Atmega168 mit internem Quarz und Clock durch 8, also 
mit 1 Mhz Frequenz.
Es ist voellig egal, was ich bei F_CPU, SYSCLOCK, X_TAL im Source 
einstelle, mein Uart laeuft nur mit 4800Baud. Ich verwende die Lib von 
Peter Fleury. Es ist auch egal, ob ich im Source 1 als Frequenz angebe 
oder eine utopische hohe Zahl und dann neu compilliere. Im Makefile gebe 
ich keine Frequenz an, sondern definitiv im Source.
Durch dieses komische Verhalten habe ich das Gefuehl, dass saemtliche 
Berechnungen fuer Timer, usw falsch sein muessten.

Was kann das sein?

Gruesse

Dusty

von holger (Gast)


Lesenswert?

>Was kann das sein?

Du brennst immer eine falsche HEX Datei
die mit deinem Programm nichts zu tun hat.

von Stephan K. (dustpuppy)


Lesenswert?

Noe. Hab ich auch als ersten Verdacht gehabt. Das Hex ist aber das 
richtige.

von ... (Gast)


Lesenswert?

Stephan Kempa schrieb:
> Atmega168 mit internem Quarz
Wo hast Du den her? Extra von Atmel produzieren lassen?
Offiziel gibs sowas jedenfalls nicht.

Aber vermutlich läuft auch Dein Atmega168 wie alle anderen mit dem 
internen RC-Oszillator.

Schau ins Datenblatt, insbesondere die Abschnitte "19.8.3 Asynchronous 
Operational Range" und "19.11 Examples of Baud Rate Setting". Dann 
sollte Dir einiges klarer werden.

von Klaus D. (kolisson)


Lesenswert?

das ist ja komisch.
Warum läuft der denn ständig mit 4800 ?
Was hast du denn sonst noch so versucht ?

K.

von Karl H. (kbuchegg)


Lesenswert?

Stephan Kempa schrieb:

> Es ist voellig egal, was ich bei F_CPU, SYSCLOCK, X_TAL im Source
> einstelle,

und wo genau stellst du das ein?

von Stephan K. (dustpuppy)


Lesenswert?

Ich habe folgendes in meinem Source stehen, bevor irgendwelche anderen 
Header-Dateien eingebunden werden, also ganz am Anfang.
1
#ifndef F_CPU
2
#define F_CPU     1000000L
3
#endif
4
#define SYSCLOCK  F_CPU
5
6
#define XTAL          F_CPU

Bei der Lib von Peter Fleury wird der Uart mit diesem Aufruf 
initialisiert.
1
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

UART_BAUD_SELECT ist als folgendes Macro in der Lib definiert.
1
#define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)


Also wird die tatsaechliche Baudrate doch dadurch berechnet, oder lieg 
ich da falsch. Es ist aber egal, was ich bei F_CPU eintrage.
Durch diese Verhalten glaube ich halt, dass alle Berechnungen die auf 
F_Cpu bassieren dann falsch sind. Auch solche, wie _delay_ms und andere.

von Willi (Gast)


Lesenswert?

Stephan Kempa schrieb:
> Ich habe folgendes in meinem Source stehen,

Papier ist geduldig. Du mußt es auch dem Prozessor sagen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Stephan Kempa schrieb:
> Ich habe folgendes in meinem Source stehen, bevor irgendwelche anderen
> Header-Dateien eingebunden werden, also ganz am Anfang.
>
1
> #ifndef F_CPU
2
> #define F_CPU     1000000L
3
> #endif
4
>

Kommentiere mal 2 Zeilen aus und ändere die mittlere auf 1L:
1
// #ifndef F_CPU
2
#define F_CPU     1L
3
// #endif

und schau nach, ob der Compiler dann meckert (irgendwas mit 
"redefined"). Wenn ja, wird das F_CPU irgendwo anders gesetzt. Das hat 
dann wg. dem "#ifndef F_CPU" Vorrang. Die Stelle gilt es dann zu finden.

von Uwe (Gast)


Lesenswert?

Die richtige Baudrate wird durch das Makro aus der Taktfrequenz 
berechnet egal welchen Takt du einstellst (im Source). Wenn du 4800 Baud 
einstellst, wird diese abhängig vom CPU Takt berechnet. Und damit 
bleiben es immer 4800 Baud egal welchen Takt du einstellst.

ps: der interne Oszillator ist kein Quarz sondern ein RC Oszillator. 
Dieser ist stark Betriebsspannungabhängig (und auch Temperatur) und 
daher ungeeignet um eine Baudrate einzustellen. Es sei denn du benutzt 
die Baudrate deines PCs als Zeitnormal und stellst damit das AVR 
Zeitnormal nach (oder paßt den Baudraten Divisor an).

von Stephan K. (dustpuppy)


Lesenswert?

@Frank
Das ist ja das Seltsame. Der Compiler meckert nix an. Hab das jetzt mal 
gemacht. Hier die Ausgaben des Compiler:
1
-------- begin --------
2
avr-gcc (GCC) 4.3.3    
3
Copyright (C) 2008 Free Software Foundation, Inc.
4
This is free software; see the source for copying conditions.  There is NO
5
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
6
7
8
Compiling: main.c
9
avr-gcc -c -mmcu=atmega168 -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 -Wp,-M,-MP,-MT,main.o,-MF,.dep/main.o.d main.c -o main.o       
10
11
Compiling: general.c
12
avr-gcc -c -mmcu=atmega168 -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=general.lst  -std=gnu99 -Wp,-M,-MP,-MT,general.o,-MF,.dep/general.o.d general.c -o general.o                                                                                                             
13
14
Compiling: io.c
15
avr-gcc -c -mmcu=atmega168 -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=io.lst  -std=gnu99 -Wp,-M,-MP,-MT,io.o,-MF,.dep/io.o.d io.c -o io.o                 
16
17
Compiling: uart.c
18
avr-gcc -c -mmcu=atmega168 -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=uart.lst  -std=gnu99 -Wp,-M,-MP,-MT,uart.o,-MF,.dep/uart.o.d uart.c -o uart.o       
19
20
Compiling: vt100.c
21
avr-gcc -c -mmcu=atmega168 -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=vt100.lst  -std=gnu99 -Wp,-M,-MP,-MT,vt100.o,-MF,.dep/vt100.o.d vt100.c -o vt100.o  
22
23
Compiling: sonic.c
24
avr-gcc -c -mmcu=atmega168 -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=sonic.lst  -std=gnu99 -Wp,-M,-MP,-MT,sonic.o,-MF,.dep/sonic.o.d sonic.c -o sonic.o  
25
26
Linking: main.elf
27
avr-gcc -mmcu=atmega168 -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o  -std=gnu99 -Wp,-M,-MP,-MT,main.o,-MF,.dep/main.elf.d main.o general.o io.o uart.o vt100.o sonic.o   --output main.elf -Wl,-Map=main.map,--cref    -lm -Ttext=0x0000                                 
28
29
Creating load file for Flash: main.hex
30
avr-objcopy -O ihex -R .eeprom main.elf main.hex
31
32
Creating load file for EEPROM: main.eep
33
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
34
        --change-section-lma .eeprom=0 -O ihex main.elf main.eep
35
avr-objcopy: --change-section-lma .eeprom=0x0000000000000000 never used
36
37
Creating Extended Listing: main.lss
38
avr-objdump -h -S main.elf > main.lss
39
40
Creating Symbol Table: main.sym
41
avr-nm -n main.elf > main.sym
42
43
Size after:
44
main.elf  :
45
section            size      addr
46
.text              4646         0
47
.bss                266   8388864
48
.stab              8580         0
49
.stabstr            962         0
50
.debug_aranges      192         0
51
.debug_pubnames     856         0
52
.debug_info        4540         0
53
.debug_abbrev      1632         0
54
.debug_line        3757         0
55
.debug_frame        784         0
56
.debug_str         1161         0
57
.debug_loc         1790         0
58
.debug_ranges       144         0
59
Total             29310
60
61
62
63
Errors: none
64
-------- end --------

Kein einziger Fehler.


@Uwe
Ans Macro wird aber doch F_CPU uebergeben. Also muesste doch bei 
aenderung auch das Ergebniss anders sein, oder seh ich den Wald vor 
lauter Baeumen nicht?
Beispiel:
F_CPU=1000000L
((1000000)/((4800)*16l)-1)=12.020833
F_CPU=8000000L
((8000000)/((4800)*16l)-1)=103.166

von Willi (Gast)


Lesenswert?

Bei den Mega48/88/168/328 liegt das Register UBRR bei 0xC4.

Die Fleury-Routinen kennen ich nicht. Schreiben die denn auch an diese 
Adresse?
Oder sprechen diese die Adresse 0x09 an, wo zum Beispiel UBRR vom 
ATmega16 und anderen ATmegas liegt?

von André A. (nummer5) Benutzerseite


Lesenswert?

Wenn du UART_BAUD_RATE auf 4800 stellst bekommst du egal für welches 
F_CPU immer eine Baudrate von 4800 das ist ja der Sinn der Berechnung. 
Wenn du eine andere Baudrate möchtest, musst du UART_BAUD_RATE 
entsprechend definieren.

>>F_CPU=1000000L
>>((1000000)/((4800)*16l)-1)=12.020833
>>F_CPU=8000000L
>>((8000000)/((4800)*16l)-1)=103.166

damit wird der Wert für den Baudratenteiler berechnet, der bei 
steigender CPU Frequenz größer werden muss um die gleiche Baudrate zu 
erhalten.

von ChrisB (Gast)


Lesenswert?

Für 1 MHz würd ich den UART aber auch nur mit 4800 baud betreiben, weil 
sonst die Abweichung größer 1% wird (siehe vorherige Antwort).
Hier eine Übersicht, welche Baudraten man mit welcher CPU Frequenz 
einstellen kann, ohne über 1% zu kommen:
 1MHz: 4800
 2MHz: 9600
 3MHz: 14400
 4MHz: 19200
 6MHz: 28800
 8MHz: 38400, 56000
 9MHz: 56000
11MHz: 38400, 57600, 115200
12MHz: 57600
...

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.