-
        

Ergebnis 1 bis 5 von 5

Thema: 8 Bit stand alone PWM auf 16 Bit aufgebohrt

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    12.06.2006
    Beiträge
    473

    8 Bit stand alone PWM auf 16 Bit aufgebohrt

    Anzeige

    Hallo zusammen,

    ich hab gestern mal ein bisschen expeimentiert. Und zwar hatte ich das allgemein bekannte Problem, dass man für RGB drei PWM Kanäle braucht, aber z.B. der Mega8 nur zwei 16 Bit hat. (ich brauch zwingend drei).
    Zwei laufen einfach auf dem Compare Units des Timer 1.

    Als Eingabe habe ich zwei Spannungsteiler. Der eine Wert wandert direkt in das OCR2 Register. Der andere ist im Prinzip ein Dimmwert.

    Hab jetzt aus dem 8 Bit des Timer 2 einen 16 er gemacht. Der Timer 2 ist so aufgesetzt, dass er im fast PWM läuft und bei comparematch den OC2 Pin Low schaltet. Trotzdem lasse ich den zugehörigen Interrupt ausführen.
    In der ISR wir eine Variable einfach nur hochgezählt, die naturgemäß bei 255 überläuft. Diese Variable wird mit dem Dimmwert verglichen. Ist sie gleich oder größer, wird das Datenrichtungsbit vom OC2 Pin auf Input gesetzt. Ist sie kleiner, auf Ausgang.

    Außerdem habe ich eingaut, das im Prinzip "vorrausschauend" gearbeitet wird. Das Kommentiere ich im Code.

    Im Ergebnis ist das natürlich kein echtes 16 Bit PWM, weil die einzelnen 8 Bit PWM´s hintereinander ablaufen. Aber für LED Anwendungen ist das gehupft wie gesprungen.

    mfg,
    The Man

    Code:
    .include"m8def.inc"
    
    .org 0x0000
    	rjmp reset
    .org OC2addr	; OCR2 Interrupt Vector Address
        rjmp hitvalue
    reset:
    ldi r16,HIGH(RAMEND)
    	out SPH,r16
    	ldi r16,LOW(RAMEND)
    	out SPL,r16
    	ldi r16,0b00000000
    	out DDRB,r16
    	out PORTB,r16
    ldi r16,0b10000000
    out TIMSK,r16
    ldi r16,0b01101001
    out TCCR2, r16;       fast PWM,
    ldi r16,255
    out ICR1H,r16
    out ICR1L,r16
    ldi r16,255
    out OCR1AL,r16
    ldi r16,0b10100010
    out TCCR1A,r16; clear on match, compare output, fast PWM => ICR1A = Top
    ldi r16,0b00011001
    out TCCR1B,r16; fast PWM => ICR1A = Top, prescaler = 1
    sei
    
    main:
    ;**********************
    ;Erfassung Dimmwert
    ;
    ldi r16,0b00100000
    out ADMUX,r16
    ldi r16,0b11010101
    out ADCSRA,r16
    warten0:
    in r16,ADCSRA
    sbrs r16,4
    rjmp warten0
    in r18,ADCH ;DIMMER
    ori r18,1
    ;**********************
    
    ldi r16,0b00100011
    out ADMUX,r16
    ldi r16,0b11010101
    out ADCSRA,r16
    warten3:
    in r16,ADCSRA
    sbrs r16,4
    rjmp warten3
    in r21,ADCH
    out OCR2,r21
    
    ;*********************************
    ;die gehen an die Comapre Units des Timer 1
    ;
    ldi r16,0b00100001
    out ADMUX,r16
    ldi r16,0b11010101
    out ADCSRA,r16
    warten1:
    in r16,ADCSRA
    sbrs r16,4
    rjmp warten1
    in r19,ADCH
    
    mul r18,r19
    out OCR1AH,r1
    out OCR1AL,r0
    
    ldi r16,0b00100010
    out ADMUX,r16
    ldi r16,0b11010101
    out ADCSRA,r16
    warten2:
    in r16,ADCSRA
    sbrs r16,4
    rjmp warten2
    in r20,ADCH
    
    mul r20,r18
    out OCR1BH,r1
    out OCR1BL,r0
    ;*********************************
    rjmp main
    
    hitvalue:
    
    out DDRB,r27
    inc r25;        
    ;***************************
    ;hier wird die Bitkodierung des DDRB für den nächsten Durchgang
    ; vorrausberechnet
    mov r26,r25;
    inc r26;<<<<=== VORALLEM HIER!!!
    cp r26,r18;
    brlo ok;
    ldi r27,0b00000110;
    rjmp nicht_ok;
    ok:;
    ldi r27,0b00001110;
    nicht_ok:;
    ;***************************
    reti
    Chuck Norris kann Windows Vista auf einem Atmel in Assembler implementieren!
    Chuck Norris coded mit 3 Tasten:"1","0" und "compile"

  2. #2
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Die Lösung ist schon gar nicht schlecht, und unterscheidet sich eigentlich nicht von echtem 16 Bit PWM. Alternativ könnte man auch als 8 Bit PWM
    zwischen den High Byte und dem Highbyte+1 umschalten. Das gibt dann kein normales PWM aber im Mittel das gleiche.

    Bei der Umsetzung ist allerdings noch ein Fehler drin: die Interruptsroutine sichert nicht den Prozessor status. Dadurch kann es im Hauptprogramm zu ziehmlich seltsamen Effekten kommen. Eventuell sollte man auch die anderen benutzten Register auf den Stack retten. Das ist aber in ASM optional, denn man kann auch einfach ein paar Register für die Interrupts reservieren.

    Bei einigen Werten könnte es immer noch zu kleinen Fehlern kommen ( <255). Auch ist man darauf angewiesen das der 8 Bit PWM den OCR-wert Puffert. Soweit ich weiss wird das nicht bei allen Chips/Timern gemacht.

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    12.06.2006
    Beiträge
    473
    Hi,

    was meinst du mit Fehlern <255 ? Wenn der ADC < 255 ? Ich mache ohnehin nur eine 8 Bit Wandlung.

    Meinst du, ich schreibe abwechselnd das High und Lowbyte der Multiplikation in das OCR2?

    Greez

  4. #4
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Bei kleinen Werten klapt es tatsächlich. Da sollte es keine Probleme geben. Das Problem mit den Statusregister sollte man aber schon ernst nehmen. Bei dem Kurzen Hauptprogramm hier geht es wohl noch gut weil man da ohne SREG auskommt. Das ist aber eher die Ausnahmen.

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    30.07.2005
    Beiträge
    569
    Eine Anmerkung:

    Bit Monster ala 0b00110010 lassen sich ohne Datenblatt nur schwer nachvollziehen. Besser wäre es die zu ladenden Bits direkt zu benennen.

    Grüße,
    Hanni
    Grundregeln des Forenpostings:
    1. Nutze niemals die Suchfunktion!
    2. Überprüfe niemals die Topics nach Ähnlichkeiten!
    3. Schreibe alles in hellgelb!

Berechtigungen

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