Das vollständige ASM-File zum Download gibts auf Anfrage.
Das Programm verwendet eine Reihe von Techniken, welche auch in anderen Projekten benötigt werden, z.B.
Lesen und Schreiben des EEPROMs
Timer-Interrupt
Software-Counter
Auslesen des AD-Wandlers
Ein Moving Average Digitalfilter
Beschaltung des Controllers:
Schliessen Sie eine RGB-Led bzw. drei einzelne LED's an die Pins PB0 bis PB2 an (mit entsprechenden Vorwiderständen natürlich)
Ein Taster wird an PB3 angeschlossen, das Analogsignal wird an PB4 angelegt. Das Analogsignal sollte über einen RC-Tiefpass mit 100k/100nF zugeführt werden.
In der Hauptroutine des Programms wird das PWM Signal für die 3 Kanäle erzeugt. Über den Timer Interrupt wird der AD-Wandler ausgelesen, und über eine Nachschlagetabelle ein weitgehend lineares Anzeigeverhalten implementiert. Ein Moving Average Digitalfilter stellt dabei eine sehr ruhige und gleichmässige Anzeigecharakteristik sicher.
Dabei sind folgende Funktionen impementiert:
Durch Drücken des Tasters kann die Reihenfolge umgeschaltet werden, in welcher die LED's zu leuchten beginnen. Dabei gibt es 6 Möglichkeiten
ROT-GRÜN-BLAU
ROT-BLAU-GRÜN
BLAU-ROT-GRÜN
BLAU-GRÜN-ROT
GRÜN-ROT-BLAU
GRÜN-BLAU-ROT
Wenn der Taster länger als ca 3 Sekunden gedrückt bleibt, wird diese Einstellung dauerhaft abgespeichert.
Wenn der Taster während dem Anlegen der Betriebsspannung gedrückt ist, wird die Polarität des Ausgangssignales umgeschaltet. Dadurch können Treiberstufen leichter angeschaltet werden, bzw. LED's sowohl mit gemeinsamer Anode als auch mit gemeinsamer Kathode benutzt werden.
Das Programm wurde mit AVR Studio 4.10 erstellt.
Beim Programmieren bitte den OSCCAL-Wert in die EEPROM-Zelle $3f speichern!
Den vollständigen Quellcode gibt es auf Anfrage
;Voltage Control RGB
;(C) 2004 Markus Vohburger
;Gewerbliche Nutzung untersagt
;Definitionen für Tiny15
.include "tn15def.inc"
;Programmvariablen
.def pwmcount = r01
.def pwmvalue_1 = r02
.def pwmvalue_2 = r03
.def pwmvalue_3 = r04
.def mode_1=r05
.def mode_2=r06
.def mode_3=r07
.def omod=r08
.def sbuffer=r09
.def temp1 = r16
.def temp2 = r17
.def output = r18
.def swcount=r19
.def mode=r20
;movin' average filter
.def adcold1 = r23
.def adcold2 = r24
.def adcold3 = r25
.equ EE_MODE = $00
.equ EE_OMOD = $01
.equ EE_OSCCAL = $3f
.equ timer_value = $80
;reset handler
.org $0000
rjmp main
;timer overflow interrut handler
.org T0OVAddr
rjmp T0OVHandler
.org $0010
main:
;read osccal byte
ldi temp1,EE_OSCCAL
rcall readeeprom
out osccal,temp1
ldi temp1,$07
out ddrb,temp1
;port b output LED's Off,, pullup on pb3
ldi temp1,$0f
out portb,temp1
ldi temp1,EE_MODE
rcall readeeprom
cpi temp1,$06
brlo mode_ok
ldi temp1,$00
mode_ok:
mov mode,temp1
rcall readsettings
ldi temp1,EE_OMOD
rcall readeeprom
cpi temp1,$00
breq omod_ok
cpi temp1,$07
breq omod_ok
ldi temp1,$00
omod_ok:
mov omod,temp1
;Taster an PB3 überprüfen
sbic pinb,pb3
rjmp no_omod_change
ldi temp1,$07
eor omod,temp1
;Mode umschalten
ldi temp1,EE_OMOD
mov temp2,omod
rcall writeeeprom
;port setup
;port pb0,1,2 outputs
no_omod_change:
notoggle:
;Timer zurücksetzen
ldi temp1,timer_value
out tcnt0,temp1
;Timer interrupts an
ldi temp1,(1<<toie0)
out timsk,temp1
;Timer starten
ldi temp1,0b00000100
out tccr0,temp1
rcall init_adc
clr swcount
sei
;Hauptschleife für PWM
loop:
;leds aus
ldi output,$0f
cp pwmvalue_1,pwmcount
brsh check_green
;leds an
and output,mode_1
check_green:
cp pwmvalue_2,pwmcount
brsh check_blue
;leds an
and output,mode_2
check_blue:
cp pwmvalue_3,pwmcount
brsh writeoutput
;leds an
and output,mode_3
writeoutput:
eor output,omod
out portb,output
inc pwmcount
brne loop
inc pwmcount
rjmp loop
;Timer Interrupt
T0OVHandler:
;Status sichern
in sbuffer,sreg
;AD-Wandler lesen
in temp1,adch
;dividieren
lsr temp1
lsr temp1
lsr temp1
;Moving Average Filter
mov temp2,temp1
add temp1,adcold1
adc temp1,adcold2
adc temp1,adcold3
mov adcold3,adcold2
mov adcold2,adcold1
mov adcold1,temp2
lsr temp1
lsr temp1
;pwm-Wert aus Tabelle lesen
clr r0
ldi zl,low(table_pwm_1<<1)
ldi zh,high(table_pwm_1<<1)
add zl,temp1
adc zh,r0
lpm
com r0
mov pwmvalue_1,r0
clr r0
ldi zl,low(table_pwm_2<<1)
ldi zh,high(table_pwm_2<<1)
add zl,temp1
adc zh,r0
lpm
com r0
mov pwmvalue_2,r0
clr r0
ldi zl,low(table_pwm_3<<1)
ldi zh,high(table_pwm_3<<1)
add zl,temp1
adc zh,r0
lpm
com r0
mov pwmvalue_3,r0
;Taster abfragen
sbic pinb,pb3
rjmp releasehandler
cpi swcount,$20
brsh exit_ovf0Handler
inc swcount
exit_ovf0Handler:
out sreg,sbuffer
reti
;wenn längere Zeit gedrückt, dann modus speichern
releasehandler:
cpi swcount,$20
breq writemode
;kurze Impulse ignorieren
cpi swcount,$02
brsh key_valid
clr swcount
rjmp exit_ovf0handler
Tabellen Initialisierungsroutinen etc...
Den vollständigen Quellcode gibts hier zum Download. |