Verständnisproblem zu Zeitangaben im Quellcode

OP #1899899
Lesenswert?

Hallo, ich hab ein Verständnisproblem zu Zeitangaben im C Code.

Ich programmiere mit AVR-Studio und beschreibe den µC auf dem STK500.
Hab etwa ein halbes dutzend ATTiny13, 23 & 25 ausprobiert.
Gemessen habe ich mit einem USB-Speicheroskar und Analogoskar, in beiden 
fällen identische Ergebnise.


Im Quellcode steht:
#define send1()    leds_on();    _delay_us(13.15);    leds_off(); 
_delay_us(13.15);

Das sollte eine Frequenz von 38khz ergeben.


Was das Osziloskop anzeigt findet man im Anhang.
Positive für 107us.
Negative für 112us.
Frequenz 4,6khz.

Nun versteh ich nicht wo der Fehler ist! Muss ich den Takt 
berücksichtigen und die Zeitangaben per hand Korrigieren? Wäre sowas 
nicht Aufgabe des Kompilors? So kenne ich das zumindestens von anderen 
Programmiersprachen.
Hab schon mal die Optimierungseinstellungen von AVR Studio 
durchprobiert, das hat den Wert zwar minimal (Nachkommastelle) 
verändernt, brachte aber keine Verbesserung.

Oder liegt diese Ungenauigkeit an Laufzeiten?
Oder hab ich mich einfach verrechnet?


Was ich auch nicht verstehe ist dass das negative Signal länger als das 
Positive ist, und das sogar wenn ich die beiden Signale tausche.
Das spricht ja eigentlich dafür das es nicht an der Laufzeit liegt.


mfg
Zergi
Angehängte Dateien:
OP #1899931
Lesenswert?

Ne, die war nicht deaktiviert.
Bis gerade hatte ich angenommen dass das setzen von F_CPU 
ausschlaggebend wäre.

Hatte daher auch den CPU Takt auf 8MHZ gesetzt und hatte 8x schnellere 
Zeitwerte.




Das verstehe ich jetzt aber gar nicht.

Warum habe ich unterschliedliche Zeiten wenn ich den Takt selber auf 
8MHZ setze, als wenn CKDIV8 (durch Deaktivierung) es macht?


Edit: Die Frequenz liegt dann bei 28,8khz.
Gast #1899937
Lesenswert?

Hi

>Bis gerade hatte ich angenommen dass das setzen von F_CPU
>ausschlaggebend wäre.

Das interessiert nur den Compiler. Den Controller musst du schon selbst 
auf die richtige Frequenz stellen.

MfG Spess
OP #1899959
Lesenswert?

Huhu,


also angenommen der Kompilor denkt der µC rechnet richtig und übergibt 
irgendeine Zahl an den µC.
Der rechnet aber nur mit 1/8 Leistung. Müsste die Frequenz dann nicht 8x 
höher sein?

Das wäre ja dann (ungefähr) das was mit das Osziloskop anzeigt wenn ich 
keinen F_CPU Wert angebe.

Aber wenn ich einen Takt angebe liegt die Frequenz ca. 25% unter dem 
Wert den der µc überhaupt nicht kennt.



F_CPU: NIX
Frequenz soll: 38khz
Frequenz ist: 4,5khz

F_CPU: 8kk
Frequenz soll: 38khz
Frequenz ist: 28khz


Ist zwar schön das ich jetzt weiß wie ich den Fehler wegbekomme, aber 
rein rechnerisch versteh ich es nicht.


mfg
Dominik
Gast #1899984
Lesenswert?

Dominik K. schrieb:

> also angenommen der Kompilor denkt der µC rechnet richtig und übergibt
> irgendeine Zahl an den µC.
> Der rechnet aber nur mit 1/8 Leistung. Müsste die Frequenz dann nicht 8x
> höher sein?

Wenn der Prozessor seine Warteschleifen nur mit 1/8 der erwarteten 
Geschwindigkeit dreht, warum sollte das dadurch erzeugte Signal dann das 
8-fache der erwarteten Geschwindigkeit haben?

> Das wäre ja dann (ungefähr) das was mit das Osziloskop anzeigt wenn ich
> keinen F_CPU Wert angebe.

Wenn du keine F_CPU angibst, müßte der Compiler eigentlich mit einem 
Fehler abbrechen.

> Aber wenn ich einen Takt angebe liegt die Frequenz ca. 25% unter dem
> Wert den der µc überhaupt nicht kennt.

Verstehe nicht, was du meinst. Was für ein "Wert den der µC überhaupt 
nicht kennt"?

> F_CPU: NIX
> Frequenz soll: 38khz
> Frequenz ist: 4,5khz

Das ist etwas mehr als Faktor 8.

> F_CPU: 8kk
> Frequenz soll: 38khz
> Frequenz ist: 28khz
>
>
> Ist zwar schön das ich jetzt weiß wie ich den Fehler wegbekomme, aber
> rein rechnerisch versteh ich es nicht.

Deine Funktionen leds_on() und leds_off() brauchen auch Zeit.
#1900129
Lesenswert?

Lies Dir doch erstmal im Datenblatt "6. System Clock and Clock Options" 
durch.
Dann weißt Du, wie Du welchen Takt Du einstellen kannst (Fuse Bits 
setzen).
Und den mußt Du dann natürlich auch Deinem Compiler bekannt geben.

Die AVR-GCC Lib nimmt bei fehlender Angabe 1MHz an (gibt zwar ne Warnung 
aus, daß sie das tut) und das ist eben oftmals falsch.

Besonders beim ATtiny13, der ist default auf 1,2MHz.

Und der interen RC-Oszillator ist natürlich nicht quarzstabil.


Peter
Gast #1902111
Lesenswert?

Dominik K. schrieb:
> Muss der µC aber nicht, wenn er mit 1 MHZ rechnet obwohl der Compiler
> von 8MHZ ausgeht um das 8fache daneben liegen?

Ja.

> Das ist das was ich nicht verstehe.

Wie und wo hast du das F_CPU denn angegeben?

> 38khz und 28khz ist aber nicht wirklich Faktor 8.

Allerdings.

> Oder zählt diese Abweichung jetzt schon unter "ungenau"?

Für einen Faktor von 1 wäre diese Abweichung plausibel.
Persönliche Seite #1902197
Lesenswert?

Du hast doch sicher noch eine Schleife drin und das Send steht in der 
Schleife. Damit kommen bei 1 MHz mind. 4 us pro Schleife für den 
Rücksprung hinzu (einfaches RJMP). Diese Zeit addiert sich zu dem Delay 
dazu.

Deine ersten Messungen sind ziemlich gut 107 us => 112 us sind fast die 
4 us. Und ich denke dein AVR lief am Anfang mit 1 Mhz Werkseinstellung.

Nach der Umstellung auf 8 MHz musst du an den Rücksprung und an den Code 
innerhalb der led_on/led_off Funktionen denken. Die knapsen auch 
Laufzeit ab.

Um das zu justieren, könntest du mal ein Toggeln versuchen

DDRB = (1<<PINB1);
while(1)
{
   PINB = (1<<PINB1); // 1 schreiben toggelt PORTB1 auf modernen AVR
                      // Anzahl Takte nachsehen
   _delay_us(12.65);  // - Feintuning für Rücksprung,,, - s.o.
}

Das ist aber müßig. Setze eine PWM auf, die kann per Hardware einen Pin 
(OC1A oder OC1B...) locker mit 38 kHz toggeln. Das gibt dir die 
Trägerfrequenz der LED. Dann schaltest du die LED plus Vorwiderstand 
zwischen diesen Pin und einen anderen O-Pin als geschaltete Stromsenke. 
HIGH an diesem Pin: LED aus, LOW an diesem PIN: LED an. Das moduliert 
das Datentelegramm auf die Trägerfrequenz.
Persönliche Seite #1902203
Lesenswert?

> Was, wie??

"Bei den neueren AVR (wie z. B. ATtiny13, ATtiny2313, ATtiny24/44/84, 
ATtiny25/45/85, ATmega48/88/168, usw.) kann man als Ausgang 
konfigurierte Pins toggeln (PORTx zwischen 0 und 1 „umschalten“), indem 
man eine 1 an die entsprechende Bit Position des PINx Register 
schreibt."
http://www.mikrocontroller.net/articles/AVR-Tutorial:_IO-Grundlagen#Zusammenfassung_der_Portregister
Gast #1902225
Lesenswert?

Michael H. schrieb:
> Klingt fast wie ein Maskenfehler, der als Feature verkauft wird.

Aber ein sinnvolles Feature.

PORTB ^= ...

braucht mehrere Takte, lesen von PortB, XOR, schreiben von PortB. Und 
kann dummerweise von einem IRQ unterbrochen werden. Wenn der IRQ jetzt 
auch was an PORTB verändern wollte, geht seine Änderung gleich nach dem 
RETI wieder verloren.
Beim Togglen über den den PINB write kann das nicht passieren.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren