mikrocontroller.net

Forum: Compiler & IDEs Timer auf Befehl starten


Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich bin relativ neu im Mikrokontroller Bereich und bräuchte euere Hilfe.

Es geht darum eine Bitsequenz einzulesen.
Dazu habe ich mir überlegt, dass ganze über einen externen Interrupt zu 
steuern. Sobald eine Flanke fällt, muss 250µs gewartet werden und dann 
das Bit ausgelesen werden. Fällt wieder eine Flanke, muss wiederum 250µs 
gewartet werden, und das Bit ausgelesen werden.
Mein Problem ist bisher nur, dass mir das GCC Tutorial nicht "verraten" 
konnte, wie ich erst nach dem Interrupt einen Timer starte, und nach den 
250µs wieder anhalte. Ich weiß bisher nur, wie ich einen Timer einfach 
konfigurieren kann und laufen lassen kann. Aber wie ich ihn erst bei 
einer fallenden Flanke starten kann, ist mir ein Rätzel. Ich hoffe 
jemand hat einen Tipp für mich.

Danke,

mfG
David

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sehe ich das richtig im Datenblatt, dass das nicht möglich ist?

ich hab mir gerade überlegt, dass ich ja den Timer auf 0 zurücksetzen 
kann, und dann abwarte bis etwas passiert. Aber Bits tatsächlich nur 
auslese wenn die flanke gefallen ist. Solange kann der Timer ja machen 
was er will, der beeinflusst ja eigentlich nichts. Sehe ich das richtig 
so?

Autor: Grrrr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
David schrieb:
> Sehe ich das richtig im Datenblatt, dass das nicht möglich ist?

Das könnten wir beantworten wenn wir wüssten in welches Datenblatt Du 
schaust.

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
im Flankeninterrupt Timer aktivieren, sprich den Prescaler der Clock in 
seinem TCCR ungleich 0 setzen, dann läuft der Timer.
Z.B. über einen Compare Match Interrupt kannste dann nach 250 us nen 
weiteren Interrupt generieren lassen. In diesem setzt du den 
Clockprescaler wieder auf 0 (Timer stopped). Wert im TCNT nicht 
vergessen zurückzusetzen, da das nicht automatisch passiert, außer du 
stellst CTC ein (geht nicht bei allen Timern).

So das war allgemein, für genauere Infos müssteste dann deine 
Schaltung/verwendeten Prozessor mitteilen ;-)

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
GENIAL! Auf die Idee bin ich nicht gekommen. Natürlich funktioniert das 
so.

Dankeschön :)

War übrigends ein Atmega 8535.

Danke

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetz wäre nur noch die Frage, wie ich genau 251,77µs bei 12Mhz 
hinbekomme.

Aber dazu muss ich CTC verwenden.
Mit Prescaler 64 und Vergleichswert 47 bekomme ich aber 250,666667µs 
hin, und das ist auserhalb von meinen 0,5% Toleranz die ich habe... :/

Zudem habe ich schon eine Lösung wie es auch ohne Starten und Stoppen 
des Timers geht.
Ich lasse einfach einen Wert hochzählen (da ich auch ab und ein 
vielfaches von 251,77µs brauche)


Danke

Autor: Grrrr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
David schrieb:
> das ist auserhalb von meinen 0,5% Toleranz

Ich rechne bei 250,666667µs eine Abweichung von 0.44% aus.

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh, du hast recht, ist schon spät... habs falsch gerechnet, aber danke 
:)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nur aus Neugier.

Was ist denn das für eine Anwendung, bei der man eine Leitung exakt 
251,77 µs nach einer Flanke abfragen muss? 1µs davor bzw. 1µs danach 
liefert ein falsches Ergebnis.


Das vom Auftreten der Flanke bis zum Abarbeiten der ISR bis dann in der 
ISR der Vorteiler für den Timer gesetzt wird auch Zeit vergeht hast du 
berücksichtigt?

Dass von der Endemeldung des Timers bis zum tatsächlichen Auslesen des 
Pins ebenfalls Zeit vergeht, hast du ebenfalls berücksichtigt?

Das sich dein ganzes Timing mit der nächsten Compilerversion (die ev. 
beim Eintritt in die ISR ein Register mehr/weniger pusht) minimal 
verschieben kann, hast du berücksichtigt?

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

es geht darum, eine Datenleitung für ein Display auszulesen.

Das Signal hat 32 Bit (also 32 verschiedene Leuchtelemente auf der 
Displaytafel)

Das Signal baut sich so auf.

Erst wird ca. 11ms eine Pause abgewartet (Signal High). Fällt die 
Flanke, kommt nach 241,77µs das erste bit. Dann muss man warten bis das 
Signal nach ein paar µs wieder auf High geht und erneut fällt. Dann 
wiederum muss 241,77µs auf das nächste Bit gewartet werden, etc.

Hab den Code soweit fertig, nur was ich nicht verstehe ist:
Wenn eine Fallende Flanke da ist, will ich den Timer zurücksetzen.
Ich habe angenommen das ich einfach OCR2 = 1 sagen kann, und er dann 
egal bei welchem Wert er gerade ist, ein Interrupt macht und im Zähler 
selbst setze ich ihn wieder auf 61. Das hat sich aber als völliger 
Blödsinn rausgestellt.
Ich möchte nur, das bei einer Flanke, der Timer wieder bei 0 zu zählen 
anfängt (also sich resettet).

Hier habe ich mal den Code soweit:
volatile uint8_t pause;
volatile uint8_t flanke;
volatile uint8_t read;
volatile uint8_t count;

///INT0 Interrupt
ISR(INT0_vect)
{
    flanke = 1;
    pause = 0;
    count = 0;
    ///Timer mit Flanke syncronisieren
    OCR2  = 1;
}


///252µs Timer
ISR(TIMER2_COMP_vect)
{
    ///Timer ca 252µs laufen lassen +1 vom INT0 Interrupt
    OCR2  = 61;
    count++;
    if (count > 10)
    {
        count = 9;
    }

}


///Pause Timer
ISR (TIMER1_COMPA_vect)
{
    pause++;
    if (pause > 250){pause = 249;}

}

uint32_t lesen(void){

    uint8_t i;
    uint32_t daten = 0x00;


    for (i=1;i<33;i++)
    {
        ///Solange keine Flanke, warten
        while (flanke != 1);
        ///Wenn Flanke erkannt, auf 0 zurücksetzen
        if (flanke == 1)
        {
            flanke = 0;
        }
        ///Warten bis Timer 252µs gezählt hat
        while (count != 1);
        ///wenn 252µs erreicht
        if (count == 1)
        {
            ///Pin auf High, Bit setzen, sonst auf 0 lassen.
            if ( PIND & ( 1 << 1 ) )
            {
                daten |= (1<<i);

            }
        }

    }
    ///Daten zurückgeben
    return daten;

}

int main(void)
{
    uint32_t display;
    char buffer[31];
    pause = 0;
    flanke = 0;
    read = 0;

    TCCR1B = (1<<CS11) | (1<<WGM12);///Prescaler auf 1024 und CTC
    OCR1A  = 124;                   ///Comparematch 86 -> 125 µs, also 88 mal für pause


    TCCR2 = (1<<CS20) | (1<<CS21) | (1<<WGM21);  ///Prescaler 32 Takt 8Mhz und CTC
    OCR2  = 62;                              ///Comparematch 62 -> 252 µs
    TIMSK |= (1<<OCIE2) | (1<<OCIE1A);        /// Interrupts aktivieren, Timerstart
    sei();


    ///Externer Interrupt aktivieren
    ///***
    GICR  |= (1<<INT0);///INT0 eingang
    MCUCR |= (1<<ISC11);///Fallende Flanke erzeugt den Interrupt
    ///***

    lcd_init(LCD_DISP_ON);
    lcd_clrscr();
    lcd_command(_BV(LCD_CGRAM));

    while(1){
        ///Wenn 11ms vorbei (88 x 125µs)
        if (pause > 87)
        {
            ///Bereit zum lesen machen
            read = 1;
            ///Pausendetektor auf 0 setzen
            pause = 0;
        }
        ///Wenn Bereit zu lesen Read zurücksetzen und lesen() aufrufen
        if (read == 1)
        {
            read = 0;
            display = lesen();
            itoa (display, buffer, 10);
            lcd_clrscr();
            lcd_puts(buffer);
        }


    }///While

}


Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TCCR1B = (1<<CS11) | (1<<WGM12);///Prescaler auf 1024 und CTC

das soll natürlich nicht 1024 sondern 8 sein, da hab ich vergessen die 
Kommentierung umzuschreiben

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
David schrieb:

> Das Signal hat 32 Bit (also 32 verschiedene Leuchtelemente auf der
> Displaytafel)
>
> Das Signal baut sich so auf.
>
> Erst wird ca. 11ms eine Pause abgewartet (Signal High). Fällt die
> Flanke, kommt nach 241,77µs das erste bit. Dann muss man warten bis das
> Signal nach ein paar µs wieder auf High geht und erneut fällt. Dann
> wiederum muss 241,77µs auf das nächste Bit gewartet werden, etc.

Sei mir nicht böse und wahrscheinlich kannst du nichts dafür.
Aber wer denkt sich denn so einen Schwachsinn aus?

In diesem Protokoll wird haufenwweise gewartet. Zuerst 11ms, dann 241µs. 
Nur in der 'heißen' Phase, wenn es darum geht den Zustand zu samplen, 
muss alles plötzlich auf 1µs genau sein?

Demjenigen der sich das ausgedacht hat (wenn du die 
Protokollbeschreibung richtig hast), sollte man mit einem nassen Fetzen 
erschlagen. Der ist nicht zufällig BWL-er?

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was heißt den da haufenweiße warten????
Das ist ein ganz normales Protokoll???

Da is ne Pause, und danach kommen die Daten. Und damit man weiß welches 
Bit kommt, wartet man eine Flanke ab, und dann nach den paar µs kommt 
dann das Bit?
Das is doch absolut simpel.

und ob es auf eine 1µs wirklich ankommt weiß ich nicht. Da steht ne 
Tabelle, bei welcher Zeit welches Bit kommt, und obendrüber +- 0.5 %
Und daran will ich mich nur halten.

Gruß

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat den keiner n kleinen Tipp wie ich den Timer auf 0 zurücksetze, damit 
er wieder neu zum zählen anfängt?

Danke

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TCNT2 = 0 sollte wohl gehen:P Man bin ich blind, das Stand sogar oben...

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zusätzlich habe ich nen Fehler gefunden, und zwar wird der 
Interrupthandeler vom INT0 solange aufgerufen, solang nach der 
gefallenen Flanke, das Signal auf low bleibt. Konnte ich aber auch nur 
mim Logicanalyzer feststellen...

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Zusätzlich habe ich nen Fehler gefunden, und zwar wird der
>Interrupthandeler vom INT0 solange aufgerufen, solang nach der
>gefallenen Flanke, das Signal auf low bleibt. Konnte ich aber auch nur
>mim Logicanalyzer feststellen...

Manche Interrupt-Flags muss man von Hand zurücksetzen...

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey,

Also es funktionier alles, ich hab einfach jedesmal die Timer usw. 
gestoppt, so dass sie sich nicht gegenseitig beeinflussen.
Jetz läuft alles 1 a!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.