ich habe mal eine kleine Demo gemacht, wie man die Hardware-PWM-Funktionen der drei Timer/Counter eines ATMEGA168/88/48 (hier ist ein 168 verwendet worden, der Code geht aber auch mit einem 88 oder 48 ). Diese drei Microcontroller haben alle drei Timer/Counter, welche je zwei unabhängige PWM-Kanäle steuern können, d.h. bis zu sechs PWM-Kanäle pro Microcontroller.
Der Chip läuft bei mir auf internen 8MHz und die PWM-Frequenz beträgt je Kanal ca. 245Hz, wobei jeweils immer zwei Kanäle auf der gleichen PWM-Frequenz laufen müssen, da sie sich einen Timer/Counter teilen, das Tastverhältnis ist aber unabhängig.
Für diese Demo habe ich eine Superflux-RGB-LED direkt an den Chip angeschlossen, d.h. jede Farbkathode über einen entsprechenden Widerstand direkt an den entsprechenden (von mir so gewählten) Output Compare Register (OCR) Pin des Microcontrollers, die gemeinsame Anode der LED direkt an +5V.
Ich habe hier einen spezielle Farbkodierung (Hue; Position im Farbkreis) für das Durchlaufen der Farben gewählt, da ich damit die Regenbogen-Farbinformation in nur einem Byte speichern kann (benötige ich für ein spezielles, späteres Projekt), aber man könnte natürlich auch direkt mit den RGB-Werten spielen (der Hue wird bei mir sowieso in RGB umgewandelt, bevor er in die Compare Register geschrieben wird).
Ein Video vom Ferbverlauf befindet sich hier, live sieht's aber viel besser aus, ad der Helligkeitsabgleich meines Handys stört. Man sieht jedoch auch so, dass der Verlauf recht sanft vonstatten geht (dank Hardware-PWM), obwohl nur 42 diskrete Werte pro Farbkanal enthalten sind (Hue/Farbkreis aufgeteilt in 252 Werte).
Der Code der ganzen Spielerei in BASCOM-AVR Basic:
Code: Alles auswählen
' pwm_led_cc1.bas by Neni
' Shows usage of Hardware-PWM for LED Color Change Applications
' Works on ATMEGA168, ATMEGA88, ATMEGA48
' Frequency: 8MHz internal RC (remember to disable CKDIV8 fuse bit)
' OCR PWM Generation is set to the Inverted Mode because the LED Cathodes
' are directly connected to the OCR Pins
' Copyright: Neni (neni@synvox.ch)
$regfile = "m168def.dat"
$crystal = 8000000
$hwstack = 64
$swstack = 64
$framesize = 64
Red_pwm1 Alias Ocr0a
Red_pwm2 Alias Ocr0b
Green_pwm1 Alias Ocr1al
Green_pwm2 Alias Ocr1bl
Blue_pwm1 Alias Ocr2a
Blue_pwm2 Alias Ocr2b
Dim I As Byte
Declare Sub Color_set1(byval Hue As Byte)
' Input/Output Ports initialization
' Port B initialization
' Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=In
' State7=P State6=P State5=P State4=P State3=1 State2=1 State1=1 State0=P
Portb = &HFF
Ddrb = &H0E
' Port C initialization
' Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
' State6=P State5=P State4=P State3=P State2=P State1=P State0=P
Portc = &HFF
Ddrc = &H00
' Port D initialization
' Func7=In Func6=Out Func5=Out Func4=In Func3=Out Func2=In Func1=In Func0=In
' State7=P State6=1 State5=1 State4=P State3=1 State2=P State1=P State0=P
Portd = &HFF
Ddrd = &H68
' Timer/Counter 0 initialization
' Clock source: System Clock
' Clock value: 125.000 kHz -> PWM-Freq ca. 245Hz
' Mode: Phase correct PWM top=FFh
' OC0A output: Inverted PWM
' OC0B output: Inverted PWM
Tccr0a = &HF1
Tccr0b = &H03
Tcnt0 = &H00
Ocr0a = &H00
Ocr0b = &H00
' Timer/Counter 1 initialization
' Clock source: System Clock
' Clock value: 125.000 kHz -> PWM-Freq ca. 245Hz
' Mode: Ph. correct PWM top=00FFh
' OC1A output: Inverted
' OC1B output: Inverted
' Noise Canceler: Off
' Input Capture on Falling Edge
' Timer 1 Overflow Interrupt: Off
' Input Capture Interrupt: Off
' Compare A Match Interrupt: Off
' Compare B Match Interrupt: Off
Tccr1a = &HF1
Tccr1b = &H03
Tcnt1h = &H00
Tcnt1l = &H00
Icr1h = &H00
Icr1l = &H00
Ocr1ah = &H00
Ocr1al = &H00
Ocr1bh = &H00
Ocr1bl = &H00
' Timer/Counter 2 initialization
' Clock source: System Clock
' Clock value: 125.000 kHz -> PWM-Freq ca. 245Hz
' Mode: Phase correct PWM top=FFh
' OC2A output: Inverted PWM
' OC2B output: Inverted PWM
Assr = &H00
Tccr2a = &HF1
Tccr2b = &H04
Tcnt2 = &H00
Ocr2a = &H00
Ocr2b = &H00
Do
For I = 0 To 251
Call Color_set1(i)
Waitms 100
Next I
Loop
Sub Color_set1(byval Hue As Byte)
If Hue < 42 Then
Red_pwm1 = 251
Green_pwm1 = Hue * 6
Blue_pwm1 = 0
Elseif Hue < 84 Then
Hue = 84 - Hue
Red_pwm1 = Hue * 6
Green_pwm1 = 251
Blue_pwm1 = 0
Elseif Hue < 126 Then
Hue = Hue - 84
Red_pwm1 = 0
Green_pwm1 = 251
Blue_pwm1 = Hue * 6
Elseif Hue < 168 Then
Hue = 168 - Hue
Red_pwm1 = 0
Green_pwm1 = Hue * 6
Blue_pwm1 = 251
Elseif Hue < 210 Then
Hue = Hue - 168
Red_pwm1 = Hue * 6
Green_pwm1 = 0
Blue_pwm1 = 251
Else
Hue = 252 - Hue
Red_pwm1 = 251
Green_pwm1 = 0
Blue_pwm1 = Hue * 6
End If
End SubGrüsse aus der Schweiz
Neni




