-         

Ergebnis 1 bis 5 von 5

Thema: 16bit PFM mit Timer1

  1. #1

    16bit PFM mit Timer1

    Anzeige

    Guten Tag,

    dieses Forum hat mir als Neuling schon viele Fragen beantwortet, doch zu
    meiner jetzigen Frage habe ich keine passende Antwort gefunden.

    Allgemein möchte ich mit einem Atmega8 eine PFM (Pulsfrequenzmodulation)
    umsetzen.

    Um dies zu realisieren würde ich Timer1 im 16bit Fast PWM Mode
    verwenden.
    Dieser soll von 0 bis zu einem variabel einstellbaren Wert hochzählen.
    Von 0 bis zu einem fest eingestellten Wert soll der Ausgang OCR1A high
    sein und dann bis zu meinem TOP Wert low sein. Somit kann ich die
    Periodendauer ändern und die high Zeit bleibt konstant. Im Datenblatt
    findet man ein Beispiel auf Seite 88, Fig. 38 bei Period 5 und 6.

    Laut Datenblatt (Tab. 39) kann man die PWM mit WGM13:0 = 15 einstellen.
    Nun kann ich mit dem OCR1A Register den TOP Wert einstellen. Der Timer
    zählt auch brav von 0 bis zu diesem Wert und springt wieder auf 0.

    Aber wo kann ich meinen Compare Wert einstellen, bei dem das OCnX Signal
    von 1 auf 0 springt? Oder hat jemand eine komplett andere Idee für eine
    "hardware" PFM?

    Hier mal mein erster Testcode. In diesem fehlt noch eine Zeile, in der
    ich den Compare Wert an ein Register übergebe.

    $regfile = "m8def.dat"
    $crystal = 3686400
    $baud = 9600

    Ddrb.1 = 1

    Tccr1a = &B10000011
    Tccr1b = &B00011101


    Do
    If Ucsra.rxc = 1 Then
    Ocr1ah = UDR
    Ocr1al = &B11111111
    End If
    Loop

    Vielen Dank für eure Hilfe!!

    Gruss Lars

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    09.05.2007
    Beiträge
    99
    Hallo,

    ich sehe da auch ein Problem. Es wird nichts anderes übrig bleiben als
    OCR1A für die Periodendauer (TOP) zu nehmen
    OCR1B als Compare Register zu nehmen und dann
    OC1B als Output Pin (nicht OC1A) zu nehmen.

    Oder Du nimmst bzw. wagst(!) WGM13:0 = 14 und stellst TOP mittels ICR1 ein. Ist ein Wagnis da ICRn kein double buffering hat.
    Ich habe es da mit meiner PWM einfacher weil ich ICR1 nur einmal auf die von mir gewünschte Periodendauer einstellen muss. Und dann für die Pulsweiten mit OCR1A und OCR1B arbeiten kann:
    Code:
    const unsigned long fosc=F_CPU/8; // Arduino 16 MHz -> 8-Prescaler -> 2 MHz damit ~32.7ms Periodendauer bei 65535
    const unsigned int UpperLimit=	(unsigned int) (fosc*0.0025);
    const unsigned int LowerLimit=	(unsigned int) (fosc*0.0005);
    const unsigned int Middle=		(unsigned int) (fosc*0.0015);
    const unsigned int Period=		(unsigned int) (fosc*0.020);
    
    void initServos(void) {
    	cli();
    	DDRB = (1<<DDB1)|(1<<DDB2);
    
    	// Init Timer1 for ICP and FastPWM Mode 14
    	ICR1=Period;
    
    	// fast PWM mode 14
    	TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11) | (0<<WGM10);  // non-inverting OC-Mode
    	TCCR1B = (1<<CS11)  | (1<<WGM13) | (1<<WGM12);  // 8-Prescaler
    
    	OCR1A = Middle;
    	OCR1B = Middle;
    
    	sei();
    }

  3. #3
    Hallo,

    vielen Dank für die schnelle, helfende Antwort.
    Habe das mal ausprobiert und nach etwas hin und her auch hinbekommen. Viel leichter als gedacht.

    Habe dazu noch eine kleine Frage.

    Wie wird festgelegt, welches der beiden OC1x Register für TOP bzw. Compare verwendet wird? Habe es bis jetzt nicht im Datenblatt gefunden....

    Timer1=0 OC1B = 1
    Timer1 =OCR1B OC1B =0 (Timer läuft weiter)
    Timer1=OCR1A OC1B=1
    usw...

    Hier mal mein "Beispiel" Code dazu:


    Code:
    $regfile = "m8def.dat"
    $crystal = 3686400
    $baud = 9600
    
    Dim Pwm As Word At &H60
    Dim Pwm_lo As Byte At &H60 Overlay
    Dim Pwm_hi As Byte At &H61 Overlay
                             
    Ddrb.2 = 1
    
    Tccr1a = &B10100011
    Tccr1b = &B00011001
    
    Ocr1bh = &B00000000
    Ocr1bl = &B11111111
    
    Ocr1ah = &B11111111
    Ocr1al = &B11111111
    
    Main:
             'pwm Wert  z.B. über RS232
              Ocr1ah = Pwm_hi
              Ocr1al = Pwm_lo
    
    Goto Main
    Vielen Dank für die Hilfe

    Gruß Lars

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    09.05.2007
    Beiträge
    99
    Ich denke mal, dass wird nicht festgelegt sondern ist verdrahtet.
    D.h.
    OCR1A ist immer das compare register für OC1A und
    OCR1B ist immer das compare register für OC1B.

    Zusätzlich darf man OCR1A als TOP für OC1A und OC1B festlegen. Wie das in Deinem Fall auf OC1B wirkt ist jetzt klar. Wie das auf OC1A wirkt muss man gesondert nachlesen. (Ich glaube OC1A toggelt dann einfach zwischen 0 und 1 bei erreichen von TOP=OCR1A.)

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    12.07.2008
    Ort
    Villingen-Schwenningen
    Beiträge
    143
    Hallo,

    das geht, ich habs selbst mal ausprobiert.
    Schau mal im Datenblatt unter Timer 1 / Modes of Operations.
    Dirt steht, welche registerbits gesetzt werden müssen, um ICR1 als Top-Wert zu konfigurieren um OCR1A und OCR1B als PWM-Register zu verwenden.
    In deinem Fall must du Mode 8, 10 oder 14 verwenden.

Berechtigungen

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