-         

Ergebnis 1 bis 3 von 3

Thema: CTC Modus

  1. #1
    Neuer Benutzer
    Registriert seit
    17.12.2009
    Ort
    Lorsch
    Alter
    26
    Beiträge
    2

    CTC Modus

    Anzeige

    Hallo zusammen,

    ich habe eine Funktion erstellt welche ein PPM Signal für den Trainerport meiner Futaba Funke erzeugt. Das Startsignal ist ein 0,4ms LOW gefolgt von dem ersten HIGH Signal für Kanal 1 (0,7ms - 1,54ms). Das ganze Wiederholt sich bis wir an Kanal 8 angekommen sind. Nach Kanal 8 kommt nochmal ein 0,4ms LOW Signal welches in einem 11ms langen HIGH Signal endet. Das ganze fängt dann wieder von vorne an.

    Es wird also mit sehr kurzen Timings gearbeitet. Sodass der Interrupt nur 210x im Bereich von 0,7ms bis 1,54ms getriggt wird. Ich benutze Timer0 im CTC Modus, ohne Prescale. Den gewünschten Endwert von 64 habe ich das Register OCR0 geladen. Soweit funktioniert auch alles. Wenn ich nun eine 32 als gewünschten Endwert wähle sollte der Interrupt ja nun 2x 210x also 410x durchlaufen werden. Irgendwie funktioniert das Programm dann aber nicht mehr.

    Ich benutze einen ATmega32 mit 16MHz Quarz. Fuses sind gesetzt. Das Signal prüfe ich mit einem Logic Analysator. Der Code schaut folgendermaßen aus:

    Code:
    #define F_CPU 16000000L
    
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    
    void g_ppm(int Kanal[]);
    void init();
    
    
    int Werte[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
    volatile int counter = 0;
    
    
    int main(void)
    {    
        init();
        
        while(1)
        {
            g_ppm(Werte);
        }
    }
    
    
    void init(void)
    {
        DDRD = 0xFF;
        PORTD = (1<<PD0);
        sei();
        
        TCCR0 = (1<<WGM01);        // CTC Modus
        TCCR0 |= (1<<CS00);        // Kein Prescale - CPU Takt
        OCR0 = 64;                // Endwert
        TIMSK |= (1<<OCIE0);    // Compare Interrupt erlauben
    }
    
    
    void g_ppm(int Kanal[])
    {    
        counter = 0;
        
        do // Startsignal
        {    
            PORTD = (0<<PD0);
        } while (counter != 100); // 100 = 0,4ms
        
        for (int i = 0; i <= 7; i++)
        {
            counter = 0;
            
            do // Signal
            {
                PORTD = (1<<PD0);
            } while (counter != Kanal[i]+175 );
            
            counter = 0;
            
            do // Pause
            {
                PORTD = (0<<PD0);
            } while (counter != 100); // 100 = 0,4ms
            
        }
        
        do // Endsignal
        {    
            PORTD = (1<<PD0);
        } while (counter != 2800); // 2750 = 11ms
    
    
    }
    
    
    ISR (TIMER0_COMP_vect)
    {
        counter++;
    }
    Meine Frage lautet nun:

    Wieso funktioniert das Programm nicht, wenn ich den Endwert auf 32 neheme?

    Liebe Grüße
    volpi
    ______________________________________________

    Träume nicht dein Leben,
    sondern lebe deine Traum.

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    1.892
    Überleg mal, was Du da tust.
    Der Controller hat gerade mal 32 Taktzyklen, bevor wieder eine neuer Interrupt ausgelöst wird.
    Das reicht noch nicht mal zum sichern aller Register!
    Ich würd die Telegrammaufbereitung anders machen.
    Nimm den Timer 1 mit einem Prescaler von 8.
    Somit ist ein Takt 0,5µs lang.
    Dann trägst Du in das OCR Register die gewünschte Puls bzw. Pausenlänge + den aktuellen OCR Register Inhalt ein.
    Dann musst Du nur noch ein Flag setzen, ob ein Impuls oder ne Pause dran ist und den entsprechenden Port Ein- bzw. Ausschalten.
    Dadurch ist ein Impulsauflösung von 0,5µs gegeben, das entspricht etwa 2000 sinnvollen Werten für 1ms, das schafft so gut wie keine Anlage.

    Auch für einen kurzen Impuls von 1ms hat dein Controller 2000*8 also 16000 Taktzyklen Zeit, bevor er wieder einen Interrupt abarbeiten muss.

    Solche Fehler wie Deinen kann man wunderbar mit dem Simulator vom AVR Studio 4.xx nachvollziehen.
    Dann wirst Du merken, das der Controller ständig nur den Interrupt ausführt und auch welche verpasst ( Der Comparematch Interrupt hat nur ein Flag ).

  3. #3
    Neuer Benutzer
    Registriert seit
    17.12.2009
    Ort
    Lorsch
    Alter
    26
    Beiträge
    2
    Vielen Dank für diese Antwort.

    Da ich noch blutiger Anfänger im Bereich Mikrocontroller und C Programmierung bin, hab ich mich schon sehr über meine "funktionierende" Lösung gefreut. Nach deinem Beitrag und sehr elegantem Lösungsvorschlag muss ich wohl nochmal neu ran und die Anwendungsbereiche für Interrups nochmal neu überdenken.
    ______________________________________________

    Träume nicht dein Leben,
    sondern lebe deine Traum.

Ähnliche Themen

  1. CTC Modus - irgendwo muss doch ein Fehler sein
    Von wisda.noobie im Forum Arduino -Plattform
    Antworten: 7
    Letzter Beitrag: 23.06.2013, 20:03
  2. [ERLEDIGT] Hilfe bei Atmega8 Timer/Counter1 für CTC Modus
    Von robotka im Forum C - Programmierung (GCC u.a.)
    Antworten: 3
    Letzter Beitrag: 22.03.2013, 19:51
  3. Problem mit Timer1 als Counter im CTC Modus und Interupt
    Von Anam52 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 7
    Letzter Beitrag: 26.02.2013, 16:34
  4. CTC Mode
    Von Thorsten im Forum C - Programmierung (GCC u.a.)
    Antworten: 6
    Letzter Beitrag: 22.09.2006, 12:55
  5. CTC
    Von surfer im Forum C - Programmierung (GCC u.a.)
    Antworten: 3
    Letzter Beitrag: 24.07.2005, 10:26

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •