[Arduino] Quarz-Genauigkeit (AVRGCC)

Gast #3102777
Lesenswert?

Hallo,

ich habe folgendes Testprogramm eingespielt, das die LED eigentlich mit 
488 Hz und paar Zerquetschten flackern lassen sollte. Leider sind meine 
Zerquetschten viel zu klein und ich messe um die 487 Hz.
Mal die Periodenzeiten gemessen und statt der 2,048 ms messe ich 2,0507 
ms.

Kann der Quarz echt über 1300 ppm daneben liegen?

Hardware-Plattform ist ein Sainsmar Arduino Uno R2 mit winzigem Quarz im 
6-poligen Gehäuse.

Das Programm arbeitet interruptgesteuert und sollte eigentlich richtig 
sein.

Beste Grüße, Marek

P.S. Gemessen mit ELV FC7008
1
/*
2
  Experimente mit Timern
3
  Timer0 im Normal Mode und Port-Toggle per Interrupt
4
  DB1BMN
5
  2013-03-25
6
*/
7

8
#include<avr/io.h>
9
#include<avr/interrupt.h>
10

11
#define LEDPORT     PORTB
12
#define LEDPORT_ddr DDRB
13
#define LEDPORT_in  PINB
14
#define LED         PB5
15

16

17
ISR (TIMER0_OVF_vect)
18
{
19
  /* Interrupt Aktion alle
20
  (16MHz/64)/256 Hz = 976,5625 Hz
21
  
22
  1/976,5625 s = 1,024 ms  
23
  */
24

25
  LEDPORT_in  |=  (1<<LED); // Toggle LED
26
}
27

28

29
int main(void)
30
{
31

32
  // Port für LED konfigurieren
33
  LEDPORT_ddr |=  (1<<LED);
34
  
35
  // Timer0 Normal Mode (Mode 0; default)
36
  // (WGM02 WGM01 WGM00) = 000
37
  TCCR0A  &=  ~(1<<WGM01)
38
          &   ~(1<<WGM00);
39
  TCCR0B  &=  ~(1<<WGM02);
40

41
  
42
  // Timer0 Prescaler 64
43
  TCCR0B |= (1<<CS01)
44
         |  (1<<CS00);
45
  // Ab hier läuft der Timer mit 16 MHz / 64 = 250 kHz (Ticks)
46
  // und erzeugt alle 256 Ticks einen Overflov
47

48
  // Timer0 Overflow Interrupt einschalten
49
  TIMSK0  |=  (1<<TOIE0);
50

51
  // alle Interrupts freigeben
52
  sei();
53

54

55
  while(1)
56
  {
57
    // NOP
58
  }
59
  return 0;
60
}
Gast #3103015
Lesenswert?

Marek N. schrieb:
> Hallo,
>
> ich habe folgendes Testprogramm eingespielt, das die LED eigentlich mit
> 488 Hz und paar Zerquetschten flackern lassen sollte. Leider sind meine
> Zerquetschten viel zu klein und ich messe um die 487 Hz.
> Mal die Periodenzeiten gemessen und statt der 2,048 ms messe ich 2,0507
> ms.
>
> Kann der Quarz echt über 1300 ppm daneben liegen?

Normal nicht, bei schlechter Beschaltung von Quarzen und den verkehrten 
Typen ist aber ALLES möglich! 1300ppm ist aber unwahrscheinlich.

Aber auch die besten Scopes (hier bei usn Agilent) haben eine Abweichung 
von bis zu 30ppm und mehr. Um Dein Messgerät zu kalibrieren benötigts Du 
einen genauen VCTCXO, damit weisst Du dann wie Dein Scope/Messgerät 
abweicht. Bei den meisten Messgeräten ist halt auch nur ein Quarz 
drinnen.

rgds
Gast #3103215
Lesenswert?

Hallo,

ja, es handelt sich tatsächlich um so einen kleinen Köttel: 
http://www.reichelt.de/Filter/CSTCE-16-0/3/index.html?;ACTION=3;LA=446;ARTICLE=89705;GROUPID=3175;artnr=CSTCE+16%2C0
Dieser darf ja sogar 5000 ppm daneben liegen. Gut, dann werde ich nen 
richtigen Quarz einbauen. Wundere mich eh, warum die für den USB-ATmega 
so einen verwendet haben, offenbar ist das Timing dort strenger.


Jörg Wunsch schrieb:
> sondern:
>
1
LEDPORT_in  =  (1<<LED); // Toggle LED
>
> Ansonsten toggeln auch alle die Ausgänge, deren Eingänge gerade
> eine 1 zurücklesen.

Nachvollzogen und verstanden. Vielen Dank!

Beste Grüße, Marek
Moderator Persönliche Seite #3103275
Lesenswert?

Marek N. schrieb:
> Wundere mich eh, warum die für den USB-ATmega
> so einen verwendet haben, offenbar ist das Timing dort strenger.

Ja, das USB-Timing ist ziemlich strikt.  Für ein lowspeed-Device
genügt die Toleranz eines Keramikschwingers noch, für ein
fullspeed-Device aber nicht mehr.

Thomas Eckmann schrieb:
> HÄÄ????

Du solltest vorsichtiger in deinen Äußerungen werden …

> Was wird denn da zurückgelesen?

PINB

> Daraus: PINB |= (1 << 2);
> wird das: sbi  0x16, 2
> und dann toggelt PB2 und nichts anderes.

Nein.  Es toggelt auch alle die Pins, die beim Rücklesen von PINB eine
1 haben.

Hinweis: SBI ist eine read-modify-write-Operation …
#3103316
Lesenswert?

Jörg Wunsch schrieb:
> Nein.  Es toggelt auch alle die Pins, die beim Rücklesen von PINB eine
> 1 haben.
> Hinweis: SBI ist eine read-modify-write-Operation …

Also konkret:
Wenn PD7 1 ist und PD6 mit sbi (PIND|=(1<<6) toggelt, toggelt PD7 auch 
und wird 0. Danach toggelt er dann nicht mehr, weil er ja 0 ist?

Ich hoffe jetzt, daß ich das falsch verstanden habe, sonst kann ich 
meine Controller alle wegschmeissen, weil die kaputt sind.

mfg.
Moderator Persönliche Seite #3103331
Lesenswert?

Falk Brunner schrieb:

> Da bleibt die
> Quizzfrage, was der Compiler aus
>
> PINB |= (1 << 2);
>
> macht?
>
> sbi PINB, 2
>
> oder
>
> in r16, PINB
> ORI r16, 0x04
> out PINB, r16
>
> Hmmm?

Das bleibt bezüglich der Wirkung jedoch gleich.

Darauf, dass SBI ein read-modify-write ist, welches sich stets auf das
ganze Register bezieht (wie sonst sollte man es auch implementieren?),
wird an anderer Stelle in den Datenblättern teilweise hingewiesen: wo
es um das Löschen von Interruptflags geht.  Wimre beim ADC, bei dem
das Interruptflag ja in einem normalen Steuerregister steht.

Thomas Eckmann schrieb:
> Wenn PD7 1 ist und PD6 mit sbi (PIND|=(1<<6) toggelt, toggelt PD7 auch
> und wird 0. Danach toggelt er dann nicht mehr, weil er ja 0 ist?

Ja, aber selbst das Zurückschalten auf 0 dürfte ja nicht beabsichtigt
gewesen sein.
#3103340
Lesenswert?

@  Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite

>Darauf, dass SBI ein read-modify-write ist,

OK.

> welches sich stets auf das
>ganze Register bezieht (wie sonst sollte man es auch implementieren?),

Einspruch! Das KANN man mittels Hardware-Bitmaske machen, die sowieso 
gebraucht wird, um das einzelne Bit anzusprechen!

Wie es REAL aufgebaut ist, weiß nur Atmels Hardwareabteilung.
Moderator Persönliche Seite #3103509
Lesenswert?

Thomas Eckmann schrieb:
> Aber PD7 wird nicht 0.

OK, dann ist SBI auf PINx offenbar anders implementiert als auf anderen
Registern (schön, wenn alles so konsistent ist ;-).

Trotzdem ist ein |= auf PINx gefährlich: ob es den gewünschten Zweck
erfüllt oder nicht, hängt nun davon ab, ob der Compiler es als SBI
umsetzt oder nicht, und damit beispielsweise von den Optimierungs-
einstellungen.  Die explizite Zuweisung nur des zu toggelnden Bits
ist dagegen sicher, dass sie genau das tut.
#3103590
Lesenswert?

Jörg Wunsch schrieb:
> Trotzdem ist ein |= auf PINx gefährlich: ob es den gewünschten Zweck
> erfüllt oder nicht, hängt nun davon ab, ob der Compiler es als SBI
> umsetzt oder nicht,
Ach komm. Daß der Compiler das bei -0s richtig auf sbi umsetzt und es 
ohne Optimierung nicht tut, weisst du besser als ich.
Und solange man das weiss, kann man das auch bedenkenlos einsetzten.
Wenn man allerdings Zweifel daran hat, ist die Lösung nicht, es mit "=" 
sondern sbi mit Inline-Assembler zu implementieren.
Sonst würde das nämlich bedeuten, daß man diese performantere Variante 
des Toggelns in C gar nicht nutzen kann.

mfg.
Moderator Persönliche Seite #3103610
Lesenswert?

Thomas Eckmann schrieb:
> Sonst würde das nämlich bedeuten, daß man diese performantere Variante
> des Toggelns in C gar nicht nutzen kann.

Jetzt muss ich mal fragen: häh?

Warum kann man diese denn nicht benutzen?

Ein simples

PINB = 1;

toggelt völlig problemlos PB0, egal ob mit oder ohne Optimierungen.
(Ohne Optimierung allerdings kaum wirklich performanter, als wenn
man gleich PORTB ^= 1; schreibt.)
#3103611
Lesenswert?

@  Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)

>Jörg Wunsch schrieb:
>> Trotzdem ist ein |= auf PINx gefährlich: ob es den gewünschten Zweck
>> erfüllt oder nicht, hängt nun davon ab, ob der Compiler es als SBI
>> umsetzt oder nicht,

Sehe ich auch so. Es ist syntaktisch ein-eindeutig.

>Ach komm. Daß der Compiler das bei -0s richtig auf sbi umsetzt und es
>ohne Optimierung nicht tut, weisst du besser als ich.

Jetzt wissen wir es alle.

>Und solange man das weiss, kann man das auch bedenkenlos einsetzten.

Nö. Das ist eine schöne Stolperfalle, hier ausnahmsweise mal umgekehrt. 
Ohne Optimierung läuft sie NICHT, nur mit Optimierung. Sowas STINKT nach 
Schuß ins Knie und unsauberen Methoden.

>Wenn man allerdings Zweifel daran hat, ist die Lösung nicht, es mit "="
>sondern sbi mit Inline-Assembler zu implementieren.

Quark.

>Sonst würde das nämlich bedeuten, daß man diese performantere Variante
>des Toggelns in C gar nicht nutzen kann.

Quark die IIte. Siehe oben!
#3103673
Lesenswert?

Jörg Wunsch schrieb:
> PINB = 1;
ergibt aber
  PINB = 1;
  3c:  81 e0         ldi  r24, 0x01  ; 1
  3e:  86 bb         out  0x16, r24  ; 22

Aber das will ich nicht haben.

Ich will das:
PINB |= 1;
  3c:  b0 9a         sbi  0x16, 0  ; 22

weil es kürzer ist.

Ein simples PORTB ^= 1; tut es übrigends auch.

Falk Brunner schrieb:
> Quark.
Ja ne is klar.
Mit Quark scheinst du dich auszukennen:
> Nö. Das ist eine schöne Stolperfalle, hier ausnahmsweise mal umgekehrt.
> Ohne Optimierung läuft sie NICHT, nur mit Optimierung. Sowas STINKT nach
> Schuß ins Knie und unsauberen Methoden.

> Ohne Optimierung läuft sie NICHT, nur mit Optimierung.
Wo ist das Problem, solange ich das weiss?

mfg.
#3103689
Lesenswert?

@  Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)


>> PINB = 1;
>ergibt aber
>  PINB = 1;
>  3c:  81 e0         ldi  r24, 0x01  ; 1
>  3e:  86 bb         out  0x16, r24  ; 22

Ohne Optimierung!

>Aber das will ich nicht haben.

>Ich will das:
>PINB |= 1;
>  3c:  b0 9a         sbi  0x16, 0  ; 22

MIT Optimierung!

>weil es kürzer ist.

2 Byte mehr im Flash, gleich Anzahl Takte ;-)

>> Ohne Optimierung läuft sie NICHT, nur mit Optimierung.
>Wo ist das Problem, solange ich das weiss?

Wenn du das nicht als Problem erkennst ist das dein Problem ;-)
Und das alles wegen einem einzigen | Zeichen.
Das wird ein neuer Sparklassiker, gleich nach den LED-Vorwiderständen . 
. .
Scheinbar greift das neue Sparpaket der Bundesregierung selbst hier im 
Forum schon!
Moderator Persönliche Seite #3103690
Lesenswert?

Thomas Eckmann schrieb:

> Ich will das:
> PINB |= 1;
>   3c:  b0 9a         sbi  0x16, 0  ; 22
>
> weil es kürzer ist.

Erbsenzähler. ;-)

> Ein simples PORTB ^= 1; tut es übrigends auch.

Allerdings noch länger.

Habe gerade gesehen, dass das Datenblatt die SBI-Variante in der Tat
sanktioniert:
1
Note that the SBI instruction can be used to toggle one single
2
bit in a port.

Damit ist es zumindest sicher, dass es sich immer so benimmt.

Hier das Gegenstück beim ADIF-Bit:
1
· Bit 4 ­ ADIF: ADC Interrupt Flag
2

3
[...] Beware that if doing a Read-Modify-Write on ADCSRA,
4
a pending interrupt can be disabled. This also applies if the SBI
5
and CBI instructions are used.
Moderator Persönliche Seite #3103698
Lesenswert?

Falk Brunner schrieb:
> Das wird ein neuer Sparklassiker, gleich nach den LED-Vorwiderständen

Ach, LED-Vorwiderstände habe ich auch schon eingespart. :-)  War mir
allerdings sicher, dass die Kanalwiderstände der Ausgangsstufen
dann problemlos deren Funktion übernehmen konnten.  Letztlich ist
es ja egal, an welcher Stelle die Energie verheizt wird.
#3103719
Lesenswert?

Jörg Wunsch schrieb:
> Allerdings noch länger.
Deswegen nimmt man ja auch PIN.

Falk Brunner schrieb:
> Wenn du das nicht als Problem erkennst ist das dein Problem ;-)
Es ist eben nicht mein "Problem".
Dann musst du auch den Takt auf einen festen Wert zementieren. Denn wenn 
man vergisst F_CPU zu definieren oder ggf. zu ändern, kann das noch viel 
schlimmere Auswirkungen haben, als festzustellen, daß sich plötzlich der 
Pullup von einem Taster in Wohlgefallen aufgelöst hat. Dann muss man 
natürlich wissen, woran es liegen kann. Aber das ist bei einer falschen 
Baudrate auch nicht anders.

Falk Brunner schrieb:
> Das wird ein neuer Sparklassiker, gleich nach den LED-Vorwiderständen .
Das ist ja nun wirklich Quark. Aber trotzdem nicht schlecht. Immerhin 
nicht vor den Vorwiderständen.

Jörg Wunsch schrieb:
> Damit ist es zumindest sicher, dass es sich immer so benimmt.
Siehste. Die Stelle wollte ich auch gerade rauskopieren.

mfg.
#3103727
Lesenswert?

@  Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite

>[...] Beware that if doing a Read-Modify-Write on ADCSRA,
>a pending interrupt can be disabled. This also applies if the SBI
>and CBI instructions are used.

MOMENT! Heißt dass, wenn ich per SBI/CBI auf ein ANDERES Bit als ADIF 
zugreife, dass ADIF gelöscht wird wenn es aktiv (=1) ist, weil die 
Maskierung der Bits in dem Befehl buggy ist? Also die Hardware die Daten 
des Registers liest, nur das eine Bit manipuliert und alles 
zurückschreibt, auch das schon gesetzte ADIF, was zu seiner Löschung 
führt? Hmm, Bug oder Feature? Ok, jetzt verstehe ich deinen Einwand.

Hmm, für normale Register ist das ja kein Problem, für Spezialregister 
mit "clear on 1" schon. Da für die einzelnen, unterschiedlichen 
Spezialregister extra Dekoder einzubauen wäre wahrscheinlich zu 
aufwändig, wenn gleich möglich.

Ist aber ein zusätzliches Argument FÜR

PINB = 1;

!!!
Moderator Persönliche Seite #3103743
Lesenswert?

Falk Brunner schrieb:
> MOMENT! Heißt dass, wenn ich per SBI/CBI auf ein ANDERES Bit als ADIF
> zugreife, dass ADIF gelöscht wird wenn es aktiv (=1) ist,

Ja.

> weil die
> Maskierung der Bits in dem Befehl buggy ist?

Nein.  Die ist nicht buggy.  Ein Bug wäre es, wenn das Verhalten
nicht so (oder gar anders) dokumentiert wäre.  Es ist aber so
dokumentiert, damit ist es per se kein Bug, sondern bestenfalls
unschön. ;-)

Immer dran denken: "An undocumented feature is called a bug."
Gast #3333558
Lesenswert?

Marek N. schrieb:
> Hallo,
>
> ja, es handelt sich tatsächlich um so einen kleinen Köttel:
> 
http://www.reichelt.de/Filter/CSTCE-16-0/3/index.html?;ACTION=3;LA=446;ARTICLE=89705;GROUPID=3175;artnr=CSTCE+16%2C0
> Dieser darf ja sogar 5000 ppm daneben liegen.

Beim UNO R3 bin ich auch über den keram. Resonator gestolpert, wo ich 
eigentlich Quarzstabilität erwartet hatte. Für Testaufbauten greife ich 
daher das quarzstabile 16MHz Taktsignal des ATmega16U2 ab. Nach dem 
Entfernen des Resonators reicht eine kurze Drahtverbindung auf der 
Platinenunterseite des UNO R3, um beide XTAL1 Siganle zu verbinden. 
Siehe Bild: 
http://www.mino-elektronik.de/bilder/Fmeter_6LED/UNO_R3_takt_1_5_1.jpg
Das ist keine perfekte Lösung, aber auf die Schnelle ohne Aufwand 
erledigt.

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