Forum: Mikrocontroller und Digitale Elektronik ATmega8 Clock Problem


von Thomas A. (t0mm3k)


Lesenswert?

Hallo zusammen,
habe eine simple Anfängerfrage mit der ich mich schon viel zu lange 
beschäftige. Da mein Programm nicht wie erwartet funktioniert hat, habe 
ich den Fehler eingekreist und festgestellt, dass meine Clock nicht so 
arbeitet, wie ich erwartet habe.
Daher habe ich mir folgendes Progrämmchen geschrieben, um die Frequenz 
zu überprüfen:
1
#define F_CPU 1000000
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
int main(void){
7
    DDRD |= (1<<DDD5);
8
    while(1){
9
        PORTD ^= (1<<PD5);
10
        _delay_ms(1000);
11
    }
12
}

Gebaut habe ich es mit:
1
$ avr-gcc -Os -mmcu=atmega8 -std=gnu99 main.c -o main.o
2
$ avr-objcopy -O ihex main.o main.hex
Dann die Fuses des ATmega8 auf 1MHz internal Osc.
1
$ avrdude -p m8 -c usbasp -U lfuse:w:0xe1:m -U hfuse:w:0xd9:m
Und abschließend das Programm geflasht:
1
$ avrdude -p m8 -c usbasp -U flash:w:main.hex
Ich benutze das AtmelEvalBoard von Pollin, einen Atmega8-16PU und einen 
USBASP programmer mit der fischl-firmware.

Die LED blinkt auch artig, ABER sie blinkt exakt vier mal so schnell wie 
sie soll. Statt 1000ms delay habe ich ein delay von exakt 250ms (auf die 
ms genau am Oszilloskop nachgemessen).
Auch wenn ich den externen Quarz mit 16MHz benutze (lfuse:0xcf und 
hfuse:0xd9) und das F_CPU define auf 16000000 anpasse, habe ich exakt 
das selbe verhalten (250ms delay, statt 1000ms).

Dieses Phänomen hatte ich noch nie. Ein zweiter Atmega8 verhält sich 
exakt genauso.

Ich habe keine Idee mehr, woran das jetzt liegen könnte, bzw was ich 
falsch mache (habe bestimmt schon 2 Jahre kein AVR mehr programmiert und 
bin ziemlich eingerostet ... wollte jetzt wieder anfangen und jetzt 
sowas).

Ich hoffe ihr könnt mir helfen.

Vielen Dank euch schonmal.
Besten Gruß
t0mM3k

von spess53 (Gast)


Lesenswert?

Hi

>#define F_CPU 1000000

Wie sind deine Fuse-Einstellungen? Ich würde auf 8MHz Tippen.

MfG Spess

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

spess53 schrieb:
> Ich würde auf 8MHz Tippen.

Meine Gedanken gehen in die gleiche Richtung, nur müsste dann nicht das 
Delay eher 1/8tel statt der gemessenen 1/4tel Sekunde dauern?
Der Faktor 2 stört hier 'noch etwas'.

MfG

von spess53 (Gast)


Lesenswert?

Hi

>Meine Gedanken gehen in die gleiche Richtung, nur müsste dann nicht das
>Delay eher 1/8tel statt der gemessenen 1/4tel Sekunde dauern?
>Der Faktor 2 stört hier 'noch etwas'.

Ein Takt besteht aus 2 Halbwellen.

MfG Spess

von Jay W. (jayway)


Lesenswert?

Die Fuses sind jedenfalls für "1 MHz Int. Osc.", sagt der 
Fuse-Calculator.

DDRD |= (1<<DDD5);
              ^--Da ist ein Fehler. Übertragungsfehler oder echter 
Fehler im Code?

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

spess53 schrieb:
> Ein Takt besteht aus 2 Halbwellen.

Das kann Es aber nicht sein - bei 1MHz besteht der Takt ebenfalls aus 
zwei Halbwellen und dort müsste das delay passen, da als Makro und 
vorgegebenem Systemtakt entsprechend oft 'auf der Stelle getreten' wird.

Klar kann man jetzt das Programm so hinfrickelt, daß die gewünschte 
Wartezeit passt, auch wenn der Code was Anderes vermuten lassen würde - 
aber 'schön' ist Das nicht.

Oder von was hängt "delay" noch ab, außer von der angegebenen 
Taktfrequenz?

MfG

Jay W. schrieb:
> DDRD |= (1<<DDD5);
>               ^--Da ist ein Fehler. Übertragungsfehler oder echter

Müsste Das nicht einen Fehler erzeugen? DDD5 ist wohl zumindest nicht 
'von Haus aus' definiert so Mal annehm

von spess53 (Gast)


Lesenswert?

Hi

>Das kann Es aber nicht sein - bei 1MHz besteht der Takt ebenfalls aus
>zwei Halbwellen und dort müsste das delay passen, da als Makro und
>vorgegebenem Systemtakt entsprechend oft 'auf der Stelle getreten' wird

Bei richtigem Takt würde dein Programm eine Frequenz von 0,5 Hz und 
nicht 1Hz erzeugen.

MfG Spess

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

Hi

Der TE schrieb aber, daß das delay auf dem Oszi gemessen nur 1/4 der 
erwarteten Zeit beträgt - ich gehe davon aus, daß 'die Wartezeit bis 
Pegelwechsel' gemeint ist - halt ein delay und nicht die Periodendauer - 
und Da macht 1/4tel keinen Sinn.
Bei 1/8tel bin ich genau bei Dir (bei 8-fachem auch, dann aber 'in die 
andere Richtung'), nur 1/4tel kann nicht, oder der µC läuft mit 4MHz 
oder der delay-Timer läuft schneller, als erwartet - worauf ich mit 
meinem

Patrick J. schrieb:
> Oder von was hängt "delay" noch ab, außer von der angegebenen
> Taktfrequenz?

hin wollte.

MfG

von Jay W. (jayway)


Lesenswert?

Könnte es sein, dass der TO eine alte avr-libc verwendet? Ich habe da 
etwas gelesen:
"Die _delay_ms() und die _delay_us aus avr-libc 1.7.0 sind fehlerhaft. 
_delay_ms () läuft 4x schneller als erwartet."

von Thomas E. (thomase)


Lesenswert?

Jay W. schrieb:
> Könnte es sein, dass der TO eine alte avr-libc verwendet? Ich habe da
> etwas gelesen:
> "Die _delay_ms() und die _delay_us aus avr-libc 1.7.0 sind fehlerhaft.
> _delay_ms () läuft 4x schneller als erwartet."

Das steht hier im GCC-Tutorial.

von Thomas A. (t0mm3k)


Lesenswert?

Hallo zusammen,
erstmal Danke für die zahlreichen Antworten.

spess53 schrieb:
> Wie sind deine Fuse-Einstellungen? Ich würde auf 8MHz Tippen.

Das hatte ich in meiner Frage bereits geschrieben. Für 1MHz intern habe 
ich die Fuses auf lfuse:0xe1 und hfuse:0xd9 gestellt. Um den 16MHz Quarz 
zu nutzen dann lfuse:0xcf und hfuse:0xd9

Jay W. schrieb:
> DDRD |= (1<<DDD5);
>               ^--Da ist ein Fehler. Übertragungsfehler oder echter

Was ist daran falsch? DDD5 ist ist in avr/iom8.h definiert (hier ein 
Auszug:)
1
/* DDRD */
2
#define DDD7  7
3
#define DDD6  6
4
#define DDD5  5
5
#define DDD4  4
6
#define DDD3  3
7
#define DDD2  2
8
#define DDD1  1
9
#define DDD0  0

spess53 schrieb:
> Bei richtigem Takt würde dein Programm eine Frequenz von 0,5 Hz und
> nicht 1Hz erzeugen.

Damit hier keine Verwirrung entsteht, habe ich extra die exakten delays 
angegeben und nicht die frequenzen. Ich wollte eine Frequenz von 0,5Hz 
und erhalte aber 2Hz.

Jay W. schrieb:
> Könnte es sein, dass der TO eine alte avr-libc verwendet? Ich habe da
> etwas gelesen:
> "Die _delay_ms() und die _delay_us aus avr-libc 1.7.0 sind fehlerhaft.
> _delay_ms () läuft 4x schneller als erwartet."

Das klingt genau nach meinem Fehler. Komisch ist nur, dass ich meine 
avr-libc über den Paketmanager installiert habe und regelmäßige Updates 
meines Systems mache.
1
 $ aptitude show avr-libc
liefert mir jedenfalls die info, dass ich Version: 1:1.8.0+Atmel3.4.4-1 
installiert habe.

Aber ich werde hier mal nachforschen, da ich noch eine alte 
Arduino-Bibliothek auf dem System liegen habe. Könnte sein, dass mein 
Pfad so gesetzt ist, dass hier die falsche Bibliothek genutzt wird und 
nicht die aus dem Systemverzeichnis.

Danke erstmal für die vielen hilfreichen Hinweise. Ich werde heute Abend 
wieder berichten.
Besten Gruß

t0mM3k

*EDIT
Danke Jay W. genau das war der Fehler. Da ich zuletzt mit einem AVR32 
experimentiert habe, hatte ich das AVR32-Studio installiert. Dieses kam 
mit einer AVR Bibliothek von 2010. Da das AVR32-Studio in PATH vor 
meinen Systemordnern kam, hat er hier diese Version verwendet. 1000 Dank 
für diese Info.

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.