3 Kanal 16 bit PWM mit Tiny2313 (Bascom)

OP #2237866
Lesenswert?

Liebes Forum,

ich versuche für die Ansteuerung von RGB-LEDs einen Tiny dazu zu 
bewegen, mir 3 16bit PWMs bereitzustellen. Mit den beiden PWMs vom 
Timer1 ist das kein Problem.

Den dritten wollte ich aus dem Timer0 basteln. Dazu wird der im 
Fast-PWM-Modus gestartet und ruft sich in einer Interrupt-Routine immer 
wieder selbst auf, bis der 16bit-Wert erreicht ist und schaltet sich 
dann ab, bis der Timer1 eine neue Runde einlaeutet.

Das funktioniert auch einigermaßen. Leider gibt es immer wieder 
"Ruckler" im Fading. Ich kann die Ursache nicht finden. Vielleicht hat 
ja jemand eine Idee dazu, oder sowas schon mal selbst gemacht....

lg,
arne

Hier der Code:
1
'3 Kanal 16bit PWM
2
'
3
'Laesst drei LEDs an OC0A, OC1A und OC1B mit 16 bit ein- und ausfaden
4
'Der dritte 16-bit Kanal wird durch mehrfaches Aneinanderhaengen
5
'von Timer0 (8bit) nachgebildet
6
'
7
'Arne Groh
8
'2011-06-20
9
'
10
'Fusebits
11
'1111 1111
12
'1111 1111
13
'1101 1111
14
'1110 0100
15

16
$regfile = "attiny2313.dat"
17
$crystal = 8e6
18

19

20
Dim I As Byte
21
Dim J As Integer
22
Dim Ocr_0a As Word
23
Dim Ocr0ah As Byte
24
Dim Ocr0al As Byte
25
Dim Ocr1a As Word
26
Dim Ocr1b As Word
27
Dim Flags As Byte
28
Lastrun Alias Flags.0
29

30

31
'------------ Timer konfigurieren --------
32
'-- Timer1 --
33
'Fast PWM-Mode 14 einstellen (TOP in ICR1)
34
Set Tccr1a.wgm11
35
Set Tccr1b.wgm12
36
Set Tccr1b.wgm13
37

38
'Ausgaenge bei Compare Match low schalten
39
Set Tccr1a.com1a1
40
Set Tccr1a.com1b1
41

42
'Overflow-Interrupt einschalten
43
Set Timsk.toie1
44

45
'niedrigste Frequenz einstellen (damit man das PWM voll ausreizen kann)
46
Icr1h = &HFF : Icr1l = &HFF
47

48
'-- Timer0 --
49
'Fast PWM-Mode 3 einstellen
50
Set Tccr0a.wgm00
51
Set Tccr0a.wgm01
52

53
'Ausgang bei Compare-Match low schalten
54
Set Tccr0a.com0a1
55

56
'Compare-Match-Interrupt einscalten
57
Set Timsk.ocie0a
58

59
'OC0A OC1A und OC1B als Output (PB2 PB3 PB4)
60
Set Ddrb.2
61
Set Ddrb.3
62
Set Ddrb.4
63

64
'Globale Interrupts einschalten
65
Set Sreg.7
66

67
'Timer1 einschalten (kein Prescale)
68
Set Tccr1b.cs10
69
'Timer0 einschalten (kein Prescale)
70
Set Tccr0b.cs00
71

72
'--------------------------------------
73

74
On Ovf1 T1ovf
75
On Oc0a T0cm
76

77

78
Do
79

80
'Einatmen
81
For I = 0 To 255 Step 1
82
J = I - 255
83
J = J * -1
84
Ocr1a = Lookup(j , Fade256)
85
Ocr1b = Lookup(i , Fade256)
86
Ocr_0a = Ocr1a
87
'Tastverhaeltniss einstellen
88
Ocr1ah = High(ocr1a) : Ocr1al = Ocr1a
89
Ocr1bh = High(ocr1b) : Ocr1bl = Ocr1b
90
Waitms 7
91
Next I
92

93
'Verharren
94
Waitms 150
95

96
'Ausatmen
97
For I = 255 To 0 Step -1
98
J = I - 255
99
J = J * -1
100
Ocr1a = Lookup(j , Fade256)
101
Ocr1b = Lookup(i , Fade256)
102
Ocr_0a = Ocr1a
103
'Tastverhaeltniss einstellen
104
Ocr1ah = High(ocr1a) : Ocr1al = Ocr1a
105
Ocr1bh = High(ocr1b) : Ocr1bl = Ocr1b
106
Waitms 14
107
Next I
108

109
'Verharren
110
Waitms 400
111

112
Loop
113

114

115
'--------------------PWM DATA----------------------------
116

117
Fade256:
118
Data 0% , 1% , 1% , 1% , 1% , 1% , 1% , 1% , 1% , 1% , 2% , 2% , 2% , 2% , 2% , 2%
119
Data 2% , 2% , 2% , 2% , 2% , 2% , 3% , 3% , 3% , 3% , 3% , 3% , 3% , 4% , 4% , 4%
120
Data 4% , 4% , 4% , 5% , 5% , 5% , 5% , 5% , 6% , 6% , 6% , 6% , 7% , 7% , 7% , 8%
121
Data 8% , 8% , 9% , 9% , 10% , 10% , 10% , 11% , 11% , 12% , 12% , 13% , 14% , 14% , 15% , 15%
122
Data 16% , 17% , 18% , 18% , 19% , 20% , 21% , 22% , 23% , 24% , 25% , 26% , 27% , 28% , 30% , 31%
123
Data 32% , 34% , 35% , 37% , 39% , 40% , 42% , 44% , 46% , 48% , 50% , 52% , 55% , 57% , 60% , 62%
124
Data 65% , 68% , 71% , 74% , 77% , 81% , 84% , 88% , 92% , 96% , 100% , 105% , 110% , 115% , 120% , 125%
125
Data 130% , 136% , 142% , 149% , 155% , 162% , 169% , 177% , 185% , 193% , 202% , 210% , 220% , 230% , 240% , 250%
126
Data 262% , 273% , 285% , 298% , 311% , 325% , 340% , 355% , 371% , 387% , 404% , 422% , 441% , 461% , 481% , 502%
127
Data 525% , 548% , 572% , 598% , 624% , 652% , 681% , 711% , 743% , 776% , 811% , 847% , 884% , 924% , 965% , 1007%
128
Data 1052% , 1099% , 1148% , 1199% , 1252% , 1308% , 1366% , 1427% , 1490% , 1556% , 1625% , 1698% , 1773% , 1852% , 1934% , 2020%
129
Data 2110% , 2204% , 2302% , 2404% , 2511% , 2623% , 2739% , 2861% , 2988% , 3121% , 3260% , 3405% , 3556% , 3714% , 3879% , 4052%
130
Data 4232% , 4420% , 4616% , 4822% , 5036% , 5260% , 5494% , 5738% , 5993% , 6259% , 6537% , 6828% , 7132% , 7449% , 7780% , 8125%
131
Data 8487% , 8864% , 9258% , 9669% , 10099% , 10548% , 11017% , 11507% , 12018% , 12552% , 13110% , 13693% , 14302% , 14938% , 15602% , 16295%
132
Data 17020% , 17776% , 18566% , 19392% , 20253% , 21154% , 22094% , 23076% , 24102% , 25173% , 26292% , 27461% , 28682% , 29957% , 31288% , 32679%
133
Data 34132% , 35649% , 37234% , 38889% , 40617% , 42423% , 44308% , 46278% , 48335% , 50484% , 52728% , 55072% , 57520% , 60076% , 62747% , 65535%
134

135

136
'------------ Interrupt-Routinen -----------------------
137

138
T1ovf:
139
Reset Lastrun
140
Ocr0ah = High(ocr_0a) : Ocr0al = Ocr_0a
141
Set Tccr0a.wgm01
142
Set Ddrb.2
143

144
Return
145

146
T0cm:
147
Ocr0a = 0
148
'wenn die letzte Runde gelaufen ist, Timer0 aus, bis Timer1 neu startet
149
If Lastrun = 1 Then
150
Reset Tccr0a.wgm01
151
Goto Raus
152
End If
153

154
'solange Timer0 auf High, bis Highbytes alle sind
155
If Ocr0ah > 0 Then
156
Ocr0a = &HFF
157
Decr Ocr0ah
158

159
'dann noch den Lowbyte-Rest High und danach Low durch Abschalten
160
Else
161
Ocr0a = Ocr0al
162
Set Lastrun
163
End If
164

165
Raus:
166
Return
Angehängte Dateien:
OP #2256182
Lesenswert?

Ich habe nochmal die Interrupt-Routinen geändert:

jetzt wird der Low-Anteil als erstes verarbeitet. Danach dann der Timer 
für High-Anteil Male wiederholt.

Das Ergebniss ist jetzt deutlich "weicher". Allerdings gibt es beim 
Übergang von High 1 auf 0 immer noch Sprünge. Ausserdem scheint der 
TCNT0 ab und an irgendwie überzulaufen. Jedenfalls gibt es beim 
runterzählen Werte, an der die LED wieder heller zu werden scheint.

Hat noch jemand eine Idee dazu?
1
T1ovf:
2
Ocr0count = 0
3
'Beim Neustart des Timer1 zunaechst den Low-Teil des 16bit Wertes durch Timer0 ausgeben
4
Ocr0a = Ocr0al
5
'Datenrichtungsbit vom OC0A auf Output schalten
6
Set Ddrb.2
7
'Timer0 zurueck an den Start
8
Set Tifr.tov0
9

10
Return
11

12

13
T0cm:
14
'Incr Ocr0count
15
'Wenn Anzahl der Durchlaeufe erreicht, dann Datenrichtungsbit aendern (Pin auf Input)
16
'Bleibt bis zum naechsten Start von Timer1 auf Input
17
If Ocr0ah > Ocr0count Then
18
Incr Ocr0count
19
Ocr0a = 255
20
Goto Raus
21
End If
22
Reset Ddrb.2
23
Raus:
24
Return
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren