Forum: Mikrocontroller und Digitale Elektronik Frequenzprobleme beim Bau eines Impulsgebers


von Sebastian S. (rudimentor)


Lesenswert?

Hallo,
folgendes Problem:
Ich habe ein Array mit 10 Einträgen in dem Bitmuster stehen z.B.: 
00010011, etc. Diese entsprechen zu einem Zeitpunkt dem Zustand eines 
Ports der als Ausgang geschaltet ist. Es soll ein Impulsgeber 
realisiert werden, wobei es vorkommen kann, dass mehrere Pins 
gleichzeitig den Zustand ändern. Weiterhin habe ich ein Array, ebenfalls 
10 Werte, in dem ich die Abstände zwischen den Zeitpunkten als Anzahl 
der "NOPs" festhalte.
"Abgespult" wird die Sequenz dann mittels einem CTC Timer, der die 
Grundfrequenz der Sequenz regelt und dann mittels Interrupt alle X Herz 
folgenden Code der Sequenz  durchläuft:
1
while(1){
2
  if (interrupt = 1){
3
  interrupt=0;
4
    for (i=0; i<10; i++){
5
    PORTX=Bitmuster[i];
6
       for (n=1; n<=Abstand[i];n++){
7
       asm volatile("NOP");
8
       }
9
    }
10
  }
11
}

Erstellt werden die Arrays in einer eigenen Funktion auf Anfrage und vor 
der Endlosschleife. Ich verwende einen ATMega8 mit externem Quarz, 
FuseBits sind gesetzt, Optimierung ist aktiviert, F_CPU ist angegeben.

Ich habe Zugang zu einem Digitalen Speicheroszi und ich habe 
festgestellt, dass ich um meine angestrebten Abstände zwischen den 
Portzuständen eine Varianz von bis zu 2 us habe, was bei teilweise 
angestrebten Pulsdistanzen runter bis auf 5 us ein inakzeptabler Wert 
ist.
Beim Gegenmessen eines komerziellen Impulsgebers stehen die 
Pulsdistanzen starr ohne Varianz auf dem eingestellten Wert.
Selbst, wenn ich den eingestellten Abstand aufgrund einer Taktzeit von 
62,5 ns bei 16MHz und internen Offsets durch die Programmabarbeitung 
zwischen den Zeitpunkten noch nicht 100% treffe, so sollte ich doch 
wenigstens stabil danebenliegen. Momentan ist es z.B. so, dass ich eine 
Pulsdistanz von 15 us anstrebe und effektiv einen Mittelwert von 16,x 
mit einer Standardabweichung von 1,9x us messe. Mit dem etwas 
danebenliegen komme ich zurecht. Das lässt sich bestimmt noch 
kompensieren, wenn ich alles Zeitkritische komplett in Assembler 
schreibe oder auch noch einen Quarztakt mit anderer Taktfrequenz 
verwende (gerader Teiler z.B. 10 MHz = 50ns), aber die Schwankungen 
betreffend ...? Den Temperaturdrift schließe ich aus, da die 
Schwankungen sehr schnell und statistisch verteilt sind und der 
Mittelwert sich nicht ändert.
Wie kann ich diese Schwankungen "abschalten"?

Danke und viele Grüße

von Karl H. (kbuchegg)


Lesenswert?

Sebastian S. schrieb:

>  mit externem Quarz,
> FuseBits sind gesetzt

Bist du da 100% sicher?

Gegentest gemacht: Quarz abziehen (wenn möglich) und der µC steht.


> 62,5 ns bei 16MHz und internen Offsets durch die Programmabarbeitung

klar. Die for-Schleife gibts nicht gratis. Aber das ist dir ja bewusst.

Zeig mal dein richtiges Programm (ven wegen Datentypen)

> betreffend ...? Den Temperaturdrift schließe ich aus, da die
> Schwankungen sehr schnell und statistisch verteilt sind und der
> Mittelwert sich nicht ändert.

Genau das lässt mich in die Richtung tendieren: interner RC-Oszi
der ist nicht sehr stabil und könnte die Schwankungen erklären

von Sebastian S. (rudimentor)


Lesenswert?

Danke ersteinmal für die Antwort.
Das  Prog hab ich leider gerade nicht zur Hand, aber die Datentypen sind 
alles uint8 oder uint16 je nach möglicher größe der Werte. 2x 1 Dim- und 
1x 2 Dim Array. Mein main ist bis auf den Funktionsaufruf und die 
Timerinitialisierung vor der while(1) Schleife identisch mit dem was 
schon gepostet ist.
Mit den Fuses muß ich mich noch mal auseinanderseten, um die Hand für 
meine Aussage ins Feuer zu legen, aber so weit mir bekannt, kann der 
Interne RC-Oszillator doch nur 1 MHz? Mein MueC ist aber def. mit 16 MHz 
Getaktet, da die vom CTC Counter eingestellte Grundfrequenz laut Oszi 
mit der überein stimmt, die ich auch haben wollte.

Oder sollte ich einen Quarz-Oszilator nehmen mit den schon verbauten 
Kapazitäten und die Fuses auf 0000 (laut Datenblatt) stellen? Mit was 
arbeitet den der normale Cryst.-Quarz im MueC zusammen? Können daher 
die Schwankungen kommen? Oder es ist vieleicht die falsche Auslegung der 
Lastkapazitäten...ich benutze mom das Pollin Board zur Evaluation.

von Karl H. (kbuchegg)


Lesenswert?

Sebastian S. schrieb:

> Timerinitialisierung vor der while(1) Schleife identisch mit dem was
> schon gepostet ist.

Das hoffe ich dann doch nicht :-)
Sonst hättest du hier

while(1){
  if (interrupt = 1){

einen Fehler :-)

> Interne RC-Oszillator doch nur 1 MHz? Mein MueC ist aber def. mit 16 MHz
> Getaktet, da die vom CTC Counter eingestellte Grundfrequenz laut Oszi
> mit der überein stimmt, die ich auch haben wollte.

Ist natürlich ein starkes Argument.

Deine Schwankungen sind mir aber ein wenig zu heftig für einen Quarz. 
Gibts sonst irgendwelche anderen Interrupts?

Probier doch mal folgendes:
Simpels Programm: Portpin auf 1, Portpin auf 0

und sieh dann mal nach, ob du dort dasselbe Phänomen hast.

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.