vklaffehn
16.12.2007, 20:46
Moin!
Beim letzten Einkauf habe ich 'aus versehen' ein paar Tiny12 mitbestellt und habe entsetzt feststellen müssen, daß ich die gar nicht in C programmieren kann mangels RAM. Naja, da habe ich die Gelegenheit ergriffen und mich in die Tiefen des Assemblers gestürzt (sowas hab ich zuletzt vor Jahrzehnten mit dem C64 gemacht...). Als Projekt bot sich eine sogenannte 'Stimmungslampe' an, da sich mein Kollege so eine bei Aldi gekauft hatte, und ich angeberisch hab verlauten lassen : Das kann ich auch !! \:D/ Also kurz einen Prototypen gebaut bestehend aus einem Tiny12, einem Taster, 4 Transistoren BC547B mit 750Ohm Basiswiderstand sowie 4 LED's (Gelb, Grün, Rot, Weiß) mit jeweils einfach 160 Ohm davor, was anderes hatte ich leider grad nicht. Und weil ich grad gut drauf war, habe ich gleich auch noch zum ersten mal in meinem Leben den Timer benutzt und eine Interruproutine geschrieben.... Das Grundkonzept ist eigentlich ganz einfach, es läuft eine Endlosschleife, die quasi mittels Software-PWM die 4 LED's dimmt, und in dem Timer IRQ wird einfach der Vergleichswert für das SW-PWM erhöht. Das funktioniert auch eigentlich ganz gut, allerdings steh ich jetzt grad auf dem Schlauch, da ich die LED's im Moment nur in eine Richtung dimme, also immer von An nach Aus, danach macht's 'plopp' und die LED ist wieder an. Also muß ich mir ja irgendwie merken, ob ich die aktuelle LED gerade dunkler oder heller machen muß, ich hab aber grad keine Idee, wie ich das sinnvoll machen kann. Vielleicht hat ja jemand einen kleinen Tipp für mich,hier ist erstmal mein 1. Assemblerprogramm für den AVR überhaupt!!!
.NOLIST
.INCLUDE <tn12def.inc>
.LIST
.CSEG
.def tmp = r16 ;arbeitsregister
.def cnt1 = r17 ;Helligkeit LED1
.def cnt2 = r18 ;Helligkeit LED2
.def cnt3 = r19 ;Helligkeit LED3
.def cnt4 = r20 ;Helligkeit LED4
.equ led1 = 1 ;Bit an PortB
.equ led2 = 2 ;Bit an PortB
.equ led3 = 3 ;Bit an PortB
.equ led4 = 4 ;Bit an PortB
.equ waittime = 200 ;Timer preload, Geschwindigkeit
.def dir = r21 ;Flag für Auf/Abblenden
;------------------------------------------------------
; Start Adresse 0000
;------------------------------------------------------
.org 0000
RESET:
rjmp INIT
;------------------------------------------------------
; ISR VECTORS
;------------------------------------------------------
.org OVF0addr
rjmp Timer
.ORG INT_VECTORS_SIZE
INIT:
;PortB konfigurieren
ldi tmp,(1<<1)| (1<<2)| (1<<3)| (1<<4) ;binär 00011110, Leds auf Ausgang, Taster als Eingang
out DDRB,tmp ;DDRB setzen
sbi PORTB,0 ;Pullup für PB0, Taster schaltet gegen GND
;Timer konfigurieren
ldi tmp,(1<<CS00) | (1<<CS02) ; prescaler 1024
out TCCR0,tmp
ldi tmp,(1<<TOIE0) ; IRQ anschalten
out TIMSK,tmp
ldi tmp,waittime
out tcnt0,tmp
ldi cnt1,127 ;starthelligkeit für LED1
ldi cnt2,127 ;starthelligkeit für LED2
ldi cnt3,127 ;starthelligkeit für LED3
ldi cnt4,127 ;starthelligkeit für LED4
ldi dir,0 ;
sei
MAIN:
ldi tmp,255 ;zähler für Soft-PWM auf Maximum
loop1:
cp tmp,cnt1 ;Zähler mit Helligkeit vergleichen
brlo led1_off ;wenn kleiner, dann led ausschalten
sbi portb,led1 ;ansonsten LED einschalten
rjmp skip1 ;und weiter mit Soft-PWM
led1_off:
cbi portb,led1 ;Led ausschalten, nur tmp < cnt1
skip1:
dec tmp ;tmp - 1
brne loop1 ;solange, bis tmp = 0
ldi tmp,255
loop2:
cp tmp,cnt2
brlo led2_off
sbi portb,led2
rjmp skip2
led2_off:
cbi portb,led2
skip2:
dec tmp
brne loop2
ldi tmp,255
loop3:
cp tmp,cnt3
brlo led3_off
sbi portb,led3
rjmp skip3
led3_off:
cbi portb,led3
skip3:
dec tmp
brne loop3
ldi tmp,255
loop4:
cp tmp,cnt4
brlo led4_off
sbi portb,led4
rjmp skip4
led4_off:
cbi portb,led4
skip4:
dec tmp
brne loop4
rjmp main
Timer:
inc cnt1
inc cnt2
inc cnt3
inc cnt4
ldi tmp,waittime
out tcnt0,tmp
reti
Hier ist ein kleines Video der ganzen Konstruktion in Aktion, was auch ein wenig seltsam ist, ist der starke Helligkeitssprung, nachdem die LED wieder an ist, liegt das an meinem Programm oder ist das ein Effekt der PWM? (Dieses Pulsieren der LED's sieht man nicht, das kommt von der Belichtungszeit meiner Kamera....) http://fokker.no-ip.com/moodlight.avi
Beim letzten Einkauf habe ich 'aus versehen' ein paar Tiny12 mitbestellt und habe entsetzt feststellen müssen, daß ich die gar nicht in C programmieren kann mangels RAM. Naja, da habe ich die Gelegenheit ergriffen und mich in die Tiefen des Assemblers gestürzt (sowas hab ich zuletzt vor Jahrzehnten mit dem C64 gemacht...). Als Projekt bot sich eine sogenannte 'Stimmungslampe' an, da sich mein Kollege so eine bei Aldi gekauft hatte, und ich angeberisch hab verlauten lassen : Das kann ich auch !! \:D/ Also kurz einen Prototypen gebaut bestehend aus einem Tiny12, einem Taster, 4 Transistoren BC547B mit 750Ohm Basiswiderstand sowie 4 LED's (Gelb, Grün, Rot, Weiß) mit jeweils einfach 160 Ohm davor, was anderes hatte ich leider grad nicht. Und weil ich grad gut drauf war, habe ich gleich auch noch zum ersten mal in meinem Leben den Timer benutzt und eine Interruproutine geschrieben.... Das Grundkonzept ist eigentlich ganz einfach, es läuft eine Endlosschleife, die quasi mittels Software-PWM die 4 LED's dimmt, und in dem Timer IRQ wird einfach der Vergleichswert für das SW-PWM erhöht. Das funktioniert auch eigentlich ganz gut, allerdings steh ich jetzt grad auf dem Schlauch, da ich die LED's im Moment nur in eine Richtung dimme, also immer von An nach Aus, danach macht's 'plopp' und die LED ist wieder an. Also muß ich mir ja irgendwie merken, ob ich die aktuelle LED gerade dunkler oder heller machen muß, ich hab aber grad keine Idee, wie ich das sinnvoll machen kann. Vielleicht hat ja jemand einen kleinen Tipp für mich,hier ist erstmal mein 1. Assemblerprogramm für den AVR überhaupt!!!
.NOLIST
.INCLUDE <tn12def.inc>
.LIST
.CSEG
.def tmp = r16 ;arbeitsregister
.def cnt1 = r17 ;Helligkeit LED1
.def cnt2 = r18 ;Helligkeit LED2
.def cnt3 = r19 ;Helligkeit LED3
.def cnt4 = r20 ;Helligkeit LED4
.equ led1 = 1 ;Bit an PortB
.equ led2 = 2 ;Bit an PortB
.equ led3 = 3 ;Bit an PortB
.equ led4 = 4 ;Bit an PortB
.equ waittime = 200 ;Timer preload, Geschwindigkeit
.def dir = r21 ;Flag für Auf/Abblenden
;------------------------------------------------------
; Start Adresse 0000
;------------------------------------------------------
.org 0000
RESET:
rjmp INIT
;------------------------------------------------------
; ISR VECTORS
;------------------------------------------------------
.org OVF0addr
rjmp Timer
.ORG INT_VECTORS_SIZE
INIT:
;PortB konfigurieren
ldi tmp,(1<<1)| (1<<2)| (1<<3)| (1<<4) ;binär 00011110, Leds auf Ausgang, Taster als Eingang
out DDRB,tmp ;DDRB setzen
sbi PORTB,0 ;Pullup für PB0, Taster schaltet gegen GND
;Timer konfigurieren
ldi tmp,(1<<CS00) | (1<<CS02) ; prescaler 1024
out TCCR0,tmp
ldi tmp,(1<<TOIE0) ; IRQ anschalten
out TIMSK,tmp
ldi tmp,waittime
out tcnt0,tmp
ldi cnt1,127 ;starthelligkeit für LED1
ldi cnt2,127 ;starthelligkeit für LED2
ldi cnt3,127 ;starthelligkeit für LED3
ldi cnt4,127 ;starthelligkeit für LED4
ldi dir,0 ;
sei
MAIN:
ldi tmp,255 ;zähler für Soft-PWM auf Maximum
loop1:
cp tmp,cnt1 ;Zähler mit Helligkeit vergleichen
brlo led1_off ;wenn kleiner, dann led ausschalten
sbi portb,led1 ;ansonsten LED einschalten
rjmp skip1 ;und weiter mit Soft-PWM
led1_off:
cbi portb,led1 ;Led ausschalten, nur tmp < cnt1
skip1:
dec tmp ;tmp - 1
brne loop1 ;solange, bis tmp = 0
ldi tmp,255
loop2:
cp tmp,cnt2
brlo led2_off
sbi portb,led2
rjmp skip2
led2_off:
cbi portb,led2
skip2:
dec tmp
brne loop2
ldi tmp,255
loop3:
cp tmp,cnt3
brlo led3_off
sbi portb,led3
rjmp skip3
led3_off:
cbi portb,led3
skip3:
dec tmp
brne loop3
ldi tmp,255
loop4:
cp tmp,cnt4
brlo led4_off
sbi portb,led4
rjmp skip4
led4_off:
cbi portb,led4
skip4:
dec tmp
brne loop4
rjmp main
Timer:
inc cnt1
inc cnt2
inc cnt3
inc cnt4
ldi tmp,waittime
out tcnt0,tmp
reti
Hier ist ein kleines Video der ganzen Konstruktion in Aktion, was auch ein wenig seltsam ist, ist der starke Helligkeitssprung, nachdem die LED wieder an ist, liegt das an meinem Programm oder ist das ein Effekt der PWM? (Dieses Pulsieren der LED's sieht man nicht, das kommt von der Belichtungszeit meiner Kamera....) http://fokker.no-ip.com/moodlight.avi