Forum: Mikrocontroller und Digitale Elektronik Problem mit RGB-LED-Fader Atmega8


von Michael M. (eos400dman)


Lesenswert?

Hallo,

ich habe erste vor ein paar Woche mit Assembler und AVRs angefangen.
Gerade versuche ich mit PWM einen RGB-Fader zu programmieren, geht auch 
schon recht gut.
Allerdings springt er nicht erst aus den Routinen wenn ocr_X = 00 ist 
sonder schon bei recht zufälligen Werten bei rot zbsp: schon bei 242.
Wahrscheinlich habe ich einen ganz einfachen Denkfehler aber ich hoffe 
ihr könnt mir trotzdem helfen.
1
.include "m8def.inc"
2
 
3
.def temp  = r16
4
.def PWMCount = r17
5
.def ocr_1 = r18                      ; Helligkeitswert Led1: 0 .. 127
6
.def ocr_2 = r19                      ; Helligkeitswert Led2: 0 .. 127
7
.def ocr_3 = r20                      ; Helligkeitswert Led3: 0 .. 127
8
.def counter = r23
9
10
.org 0x0000
11
        rjmp    main                    ; Reset Handler
12
.org OVF0addr
13
        rjmp    timer0_overflow         ; Timer Overflow Handler
14
     
15
main:
16
        ldi   counter, $01
17
        ldi     temp, LOW(RAMEND)       ; Stackpointer initialisieren
18
        out     SPL, temp
19
        ldi     temp, HIGH(RAMEND)
20
        out     SPH, temp
21
  
22
        ldi     temp, 0xFF              ; Port C auf Ausgang
23
        out     DDRC, temp
24
 
25
        ldi     ocr_1, $ff          ; Blau  
26
        ldi     ocr_2, $ff        ; Grün
27
        ldi     ocr_3, $ff        ; Rot
28
 
29
        ldi     temp, 1<<CS00           ; CS00 setzen: Teiler 1
30
        out     TCCR0, temp
31
 
32
        ldi     temp, 1<<TOIE0          ; TOIE0: Interrupt bei Timer Overflow
33
        out     TIMSK, temp
34
 
35
        sei
36
37
loop:  
38
    rol counter
39
40
    sbrs counter, 0
41
    rcall rot_an
42
    sbrs counter, 1
43
    rcall gruen_an
44
    sbrs counter, 2
45
    rcall blau_an
46
47
    sbrs counter, 3
48
    rcall rot_aus
49
    sbrs counter, 4
50
    rcall gruen_aus
51
    sbrs counter, 5
52
    rcall blau_aus
53
54
    rjmp loop
55
 
56
;*****************
57
blau_an:   
58
    cpi ocr_1, $00
59
    breq loop
60
    dec ocr_1
61
    rcall pause
62
    cpi ocr_1, $00
63
    brne blau_an
64
    ret
65
66
;****************
67
blau_aus:  
68
    cpi ocr_1, $fe
69
    breq loop
70
    cpi ocr_2, $00
71
    breq blau_aus_2
72
    cpi ocr_3, $00
73
    breq blau_aus_2
74
    rjmp loop
75
76
blau_aus_2:
77
    inc ocr_1
78
    rcall pause
79
    cpi ocr_1, $fe
80
    brne blau_aus_2
81
    ldi counter, $01
82
    ret
83
84
;******************
85
Gruen_an:   
86
    cpi ocr_2, $00
87
    breq loop
88
    dec ocr_2
89
    rcall pause
90
    cpi ocr_2, $00
91
    brne Gruen_an
92
    ret
93
;***************
94
gruen_aus:  
95
    cpi ocr_2, $fe
96
    breq loop
97
    cpi ocr_1, $00
98
    breq gruen_aus_2
99
    cpi ocr_3, $00
100
    breq gruen_aus_2
101
    rjmp loop
102
103
Gruen_aus_2:
104
    inc ocr_2
105
    rcall pause
106
    cpi ocr_2, $ff
107
    brne Gruen_aus_2
108
    ret
109
;*************
110
Rot_an:   
111
    cpi ocr_3, $00
112
    breq loop
113
    dec ocr_3
114
    rcall pause
115
    cpi ocr_3, $00   <--Hier springt er schon bei 242 nicht mehr zu rot_an 
116
    brne Rot_an
117
    ret
118
;**********
119
rot_aus:  
120
    cpi ocr_3, $fe
121
    breq loop
122
    cpi ocr_1, $00
123
    breq rot_aus_2
124
    cpi ocr_2, $00
125
    breq rot_aus_2
126
    rjmp loop
127
128
Rot_aus_2:
129
    inc ocr_3
130
    rcall pause
131
    cpi ocr_3, $fe
132
    brne Rot_aus_2
133
    ret
134
135
timer0_overflow:                      ; Timer 0 Overflow Handler
136
        inc     PWMCount              ; den PWM Zähler von 0 bis
137
        cpi     PWMCount, 127        ; 127 zählen lassen
138
        brne    WorkPWM
139
        clr     PWMCount
140
 
141
WorkPWM:
142
        ldi     temp, 0b11000000      ; 0 .. Led an, 1 .. Led aus
143
 
144
        cp      PWMCount, ocr_1       ; Ist der Grenzwert für Led 1 erreicht
145
        brlo    OneOn
146
        ori     temp, $01
147
 
148
OneOn:  cp      PWMCount, ocr_2       ; Ist der Grenzwert für Led 2 erreicht
149
        brlo    TwoOn
150
        ori     temp, $02
151
 
152
TwoOn:  cp      PWMCount, ocr_3       ; Ist der Grenzwert für Led 3 erreicht
153
    brlo    ThreeOn
154
        ori     temp, $04
155
156
ThreeOn:      
157
        ori     temp, $08
158
 
159
SetBits:                              ; Die neue Bitbelegung am Port ausgeben
160
    andi temp, 0b00000111
161
        out     PORTC, temp
162
 
163
        reti
164
165
pause:
166
; ============================= 
167
;   Warteschleifen-Generator 
168
;     20000 Zyklen:
169
; ----------------------------- 
170
; warte 19998 Zyklen:
171
          ldi  R21, $21
172
WGLOOP0:  ldi  R22, $C9
173
WGLOOP1:  dec  R22
174
          ;brne WGLOOP1
175
          dec  R21
176
          ;brne WGLOOP0
177
; ----------------------------- 
178
; warte 2 Zyklen:
179
          nop
180
          nop
181
; ============================= 
182
ret

von Thomas P. (topla)


Lesenswert?

Du solltest in der Interruptroutine timer0_overflow unbedingt das sreg 
sichern.

Thomas

von Michael M. (eos400dman)


Lesenswert?

Danke!
Jetzt läuft es.

Gruß Michael

von Vivil (Gast)


Lesenswert?

Ich würde mal diese Zeilen bedenken. Ansonsten hast du einen Zeitbombe.
1
blau_an:   
2
    cpi ocr_1, $00
3
    breq loop
4
5
6
blau_aus:  
7
    cpi ocr_1, $fe
8
    breq loop
9
10
11
Gruen_an:   
12
    cpi ocr_2, $00
13
    breq loop
14
15
16
gruen_aus:  
17
    cpi ocr_2, $fe
18
    breq loop
19
20
Rot_an:   
21
    cpi ocr_3, $00
22
    breq loop
23
24
25
rot_aus:  
26
    cpi ocr_3, $fe
27
    breq loop

von Michael M. (eos400dman)


Lesenswert?

Ich habe es mittlerweile von fe auf ff geändert, kann dir aber nicht 
ganz folgen. Kannst du mir etwas genauer erklären, was du mit Zeitbombe 
meinst?

Gruß Michael

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.