Looplicht 4

29 maart 2009

Looplicht 4 is een verbeterde variant van de voorgaande. Het dimmen van de leds is verwerkt in de hoofd PWM lus en verloopt nu veel vloeiender.

De code is wat ingewikkelder, voor het opschuiven van de leds wordt gebruik gemaakt van een computed-goto (berekende sprong) Dit maakt de code compact. Het dimmen is verstopt in een subroutine. Daar gebruik ik indirect adresseren om het dimmen van de leds in een lus te doen en het niet voor elke led te hoeven uitschrijven.

De hoofdlus bestaat uit twee geneste lussen. Een is de PWM lus. Binnen deze lus loopt een andere teller die af telt van 32. Als deze tellen 0 is worden de leds een stap gedimd. Het opschuiven gebeurt na dat de PWM lus 10 x 255 doorlopen is. Deze waarden zijn door te proberen bepaald. Zo vind ik het er het leukste uit zien.

Asmfile: looplicht4.asm
Hexfile: looplicht4.hex

; -----------------------------------------------------------------------
; Template source file generated by piklab
    #include <p16f628a.inc>

; -----------------------------------------------------------------------
; Configuration bits: adapt to your setup and needs
        __CONFIG _WDT_OFF & _PWRTE_OFF & _INTOSC_OSC_NOCLKOUT & _MCLRE_ON & _BOREN_ON & _LVP_OFF & _DATA_CP_OFF & _CP_OFF

; -----------------------------------------------------------------------
; Variables declaration
INT_VAR UDATA_SHR
w_saved      RES 1 ; variable used for context saving
status_saved RES 1 ; variable used for context saving
pclath_saved RES 1 ; variable used for context saving

VAR     UDATA
led1    RES 1
led2    RES 1
led3    RES 1
led4    RES 1
led5    RES 1
led6    RES 1
led7    RES 1
led8    RES 1
ledH    RES 1
dir     RES 1
counter1 RES 1
counter2 RES 1
counter3 RES 1
output  RES 1
tmp     RES 1


; -----------------------------------------------------------------------
; reset vector
STARTUP CODE 0x000
    nop                    ; needed for ICD2 debugging
    movlw   high start     ; load upper byte of 'start' label
    movwf   PCLATH         ; initialize PCLATH
    goto    start          ; go to start of main code

; interrupt vector
INT_VECTOR CODE 0x004
    goto    interrupt      ; go to start of interrupt code

; relocatable code
PROG CODE
interrupt
    movwf   w_saved        ; save context
    swapf   STATUS,w
    movwf   status_saved
    movf    PCLATH,w       ; only required if using more than first page
    movwf   pclath_saved
    clrf    PCLATH
    ; << insert interrupt code >>
    movf    pclath_saved,w ; restore context
    movwf   PCLATH
    swapf   status_saved,w
    movwf   STATUS
    swapf   w_saved,f
    swapf   w_saved,w
    retfie

start
    bsf     STATUS, RP0
    movlw   0
    movwf   TRISB
    bcf     STATUS, RP0
    
    movlw   0xff
    movwf   led1 
    clrf   led2
    clrf   led3
    clrf   led4
    clrf   led5
    clrf   led6
    clrf   led7
    clrf   led8
    clrf   ledH         ; Houdt bij welke led het felst brand.
    clrf   dir          ; Houdt de richting bij.
    movlw   1
    movwf   counter1
    movlw   0xa
    movwf   counter2
    movlw   0x20
    movwf   counter3
    
loop1
    movlw   0xff
    movwf   output
    movf    counter1, 0
    subwf   led1, 0
    btfss   STATUS, C    ;resultaat negatief -> counter > led1
    bcf     output, 0 
    movf    counter1, 0
    subwf   led2, 0
    btfss   STATUS, C
    bcf     output, 1
    movf    counter1, 0
    subwf   led3, 0
    btfss   STATUS, C
    bcf     output, 2
    movf    counter1, 0
    subwf   led4, 0
    btfss   STATUS, C
    bcf     output, 3
    movf    counter1, 0
    subwf   led5, 0
    btfss   STATUS, C
    bcf     output, 4
    movf    counter1, 0
    subwf   led6, 0
    btfss   STATUS, C
    bcf     output, 5
    movf    counter1, 0
    subwf   led7, 0
    btfss   STATUS, C
    bcf     output, 6
    movf    counter1, 0
    subwf   led8, 0
    btfss   STATUS, C
    bcf     output, 7
    movf    output, 0
    movwf   PORTB
    call    dim_leds
    incfsz  counter1
    goto    loop1
    incf    counter1            ; counter1 start bij 1
    decfsz  counter2
    goto    loop1
    movlw   0xa
    movwf   counter2
    movf    ledH, 0
    addwf   PCL, 1              ; computed goto, jump table
    goto    led1_high
    goto    led2_high
    goto    led3_high
    goto    led4_high
    goto    led5_high
    goto    led6_high
    goto    led7_high
    goto    led8_high
led1_high
    movlw   0xff
    movwf   led2
    incf    ledH
    goto    loop1
led2_high
    movlw   0xff
    btfss   dir, 0
    goto    led2_up
    movwf   led1
    decf    ledH
    bcf     dir, 0
    goto    loop1
led2_up
    movwf   led3
    incf    ledH
    goto    loop1
led3_high
    movlw   0xff
    btfss   dir, 0
    goto    led3_up
    movwf   led2
    decf    ledH
    goto    loop1
led3_up
    movwf   led4
    incf    ledH
    goto    loop1
led4_high
    movlw   0xff
    btfss   dir, 0
    goto    led4_up
    movwf   led3
    decf    ledH
    goto    loop1
led4_up
    movwf   led5
    incf    ledH
    goto    loop1
led5_high
    movlw   0xff
    btfss   dir, 0
    goto    led5_up
    movwf   led4
    decf    ledH
    goto    loop1
led5_up
    movwf   led6
    incf    ledH
    goto    loop1
led6_high
    movlw   0xff
    btfss   dir, 0
    goto    led6_up
    movwf   led5
    decf    ledH
    goto    loop1
led6_up
    movwf   led7
    incf    ledH
    goto    loop1
led7_high
    movlw   0xff
    btfss   dir, 0
    goto    led7_up
    movwf   led6
    decf    ledH
    goto    loop1
led7_up
    movwf   led8
    incf    ledH
    goto    loop1
led8_high
    movlw   0xff
    movwf   led7
    decf    ledH
    bsf     dir, 0
    goto    loop1
    
dim_leds
    decfsz  counter3
    return
    movlw   0x20
    movwf   counter3
    clrf   tmp
loop2
    movf    ledH, 0         ; tmp == ledH ?
    subwf   tmp, 0
    btfss   STATUS, Z
    goto    low1            ; no
    incf    tmp             ; yes
    goto    next
low1
    movlw   led1 
    addwf   tmp, 0
    movwf   FSR
    movf    INDF, 1
    btfss   STATUS,Z
    decf    INDF, 1
    incf    tmp
next
    movlw   0x8
    subwf   tmp, 0
    btfss   STATUS, Z
    goto    loop2
    return
END
Advertenties

Looplicht 3

29 maart 2009

Deze versie heeft een naijlend effect. Dit wordt bewerkt door de leds aan te sturen met een pulse-width-modulation (PWM) lus. In pseudo code voor een led:


teller = 1
ledwaarde = PWM-waarde
lus:
tmp-led = aan
als teller>ledwaarde
dan tmp-led = uit
led = tmp-led
goto lus

Dit is in de code 8 keer uitgeschreven.

Een variabele houdt de richting van het lopen bij. Elke 0xd (=14) keer de hoofdlus, schuift de felst brandde led een op. Van de andere wordt de waarde gehalveerd. Dit heeft een schoksgewijs dimmen van de leds tot gevolg. Het dimmen en opschuiven is ook 8 keer uitgeschreven.

Asmfile: looplicht3.asm
Hexfile: looplicht3.hex

; -----------------------------------------------------------------------
; Template source file generated by piklab
    #include <p16f628a.inc>

; -----------------------------------------------------------------------
; Configuration bits: adapt to your setup and needs
        __CONFIG _WDT_OFF & _PWRTE_OFF & _INTOSC_OSC_NOCLKOUT & _MCLRE_ON & _BOREN_ON & _LVP_OFF & _DATA_CP_OFF & _CP_OFF

; -----------------------------------------------------------------------
; Variables declaration
INT_VAR UDATA_SHR
w_saved      RES 1 ; variable used for context saving
status_saved RES 1 ; variable used for context saving
pclath_saved RES 1 ; variable used for context saving

VAR     UDATA
led1    RES 1
led2    RES 1
led3    RES 1
led4    RES 1
led5    RES 1
led6    RES 1
led7    RES 1
led8    RES 1
dir     RES 1
counter1 RES 1
counter2 RES 1
output  RES 1



; -----------------------------------------------------------------------
; reset vector
STARTUP CODE 0x000
    nop                    ; needed for ICD2 debugging
    movlw   high start     ; load upper byte of 'start' label
    movwf   PCLATH         ; initialize PCLATH
    goto    start          ; go to start of main code

; interrupt vector
INT_VECTOR CODE 0x004
    goto    interrupt      ; go to start of interrupt code

; relocatable code
PROG CODE
interrupt
    movwf   w_saved        ; save context
    swapf   STATUS,w
    movwf   status_saved
    movf    PCLATH,w       ; only required if using more than first page
    movwf   pclath_saved
    clrf    PCLATH
    ; << insert interrupt code >>
    movf    pclath_saved,w ; restore context
    movwf   PCLATH
    swapf   status_saved,w
    movwf   STATUS
    swapf   w_saved,f
    swapf   w_saved,w
    retfie

start
    bsf     STATUS, RP0
    movlw   0
    movwf   TRISB
    bcf     STATUS, RP0
    
    movlw   0xff
    movwf   led1
    clrf   led2
    clrf   led3
    clrf   led4
    clrf   led5
    clrf   led6
    clrf   led7
    clrf   led8
    clrf   dir
    movlw   1
    movwf   counter1        ; Counter start bij 1, 0 als ledwaarde is dan echt uit.
    movlw   0xd
    movwf   counter2
    
loop1
    movlw   0xff            ; PWM lus. Start met alle leds aan.
    movwf   output
    movf    counter1, 0
    subwf   led1, 0
    btfss   STATUS, C    ;resultaat negatief -> counter > led1
    bcf     output, 0       ; Dan led1 (=bit0) uit
    movf    counter1, 0
    subwf   led2, 0         ; Zelfde voor led2 en verder...
    btfss   STATUS, C
    bcf     output, 1
    movf    counter1, 0
    subwf   led3, 0
    btfss   STATUS, C
    bcf     output, 2
    movf    counter1, 0
    subwf   led4, 0
    btfss   STATUS, C
    bcf     output, 3
    movf    counter1, 0
    subwf   led5, 0
    btfss   STATUS, C
    bcf     output, 4
    movf    counter1, 0
    subwf   led6, 0
    btfss   STATUS, C
    bcf     output, 5
    movf    counter1, 0
    subwf   led7, 0
    btfss   STATUS, C
    bcf     output, 6
    movf    counter1, 0
    subwf   led8, 0
    btfss   STATUS, C
    bcf     output, 7
    movf    output, 0       ; output naar W register
    movwf   PORTB           ; W naar PORTB
    incfsz  counter1
    goto    loop1
    incf    counter1
    decfsz  counter2
    goto    loop1
    movlw   0xd
    movwf   counter2
    btfss   dir, 0              ; Richting omhoog of omlaag
    goto up
    goto down
up                              ; Uit geschreven elke ledbrandtijd is helft van vorige waarde.
    movf    led7, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led7_0xff        ; Led7 is vol aan
    goto    up_led7_div
up_led7_0xff                    ; Dan nu led8 vol aan
    movlw   0xff
    movwf   led8
    bsf     dir, 0
    goto up_next1
up_led7_div                     ; anders led8 halveren
    addlw   0                   ; Voor de zekerheid Carry = 0
    rrf     led8, 1
up_next1
    movf    led6, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led6_0xff
    goto    up_led6_div
up_led6_0xff
    movlw   0xff
    movwf   led7
    goto up_next2
up_led6_div
    addlw   0
    rrf     led7, 1
up_next2
    movf    led5, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led5_0xff
    goto    up_led5_div
up_led5_0xff
    movlw   0xff
    movwf   led6
    goto up_next3
up_led5_div
    addlw   0
    rrf     led6, 1
up_next3
    movf    led4, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led4_0xff
    goto    up_led4_div
up_led4_0xff
    movlw   0xff
    movwf   led5
    goto up_next4
up_led4_div
    addlw   0
    rrf     led5, 1
up_next4
    movf    led3, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led3_0xff
    goto    up_led3_div
up_led3_0xff
    movlw   0xff
    movwf   led4
    goto up_next5
up_led3_div
    addlw   0
    rrf     led4, 1
up_next5
    movf    led2, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led2_0xff
    goto    up_led2_div
up_led2_0xff
    movlw   0xff
    movwf   led3
    goto up_next6
up_led2_div
    addlw   0
    rrf     led3, 1
up_next6
    movf    led1, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    up_led1_0xff
    goto    up_led1_div
up_led1_0xff
    movlw   0xff
    movwf   led2
    addlw   0
    rrf     led1, 1
    goto up_next7
up_led1_div
    addlw   0
    rrf     led2, 1
    addlw   0
    rrf     led1, 1
up_next7
    goto loop1
down
    movf    led2, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led2_0xff
    goto    down_led2_div
down_led2_0xff
    movlw   0xff
    movwf   led1
    bcf     dir, 0
    goto down_next1
down_led2_div
    addlw   0
    rrf     led1, 1
down_next1
    movf    led3, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led3_0xff
    goto    down_led3_div
down_led3_0xff
    movlw   0xff
    movwf   led2
    goto down_next2
down_led3_div
    addlw   0
    rrf     led2, 1
down_next2
    movf    led4, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led4_0xff
    goto    down_led4_div
down_led4_0xff
    movlw   0xff
    movwf   led3
    goto down_next3
down_led4_div
    addlw   0
    rrf     led3, 1
down_next3
    movf    led5, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led5_0xff
    goto    down_led5_div
down_led5_0xff
    movlw   0xff
    movwf   led4
    goto down_next4
down_led5_div
    addlw   0
    rrf     led4, 1
down_next4
    movf    led6, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led6_0xff
    goto    down_led6_div
down_led6_0xff
    movlw   0xff
    movwf   led5
    goto down_next5
down_led6_div
    addlw   0
    rrf     led5, 1
down_next5
    movf    led7, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led7_0xff
    goto    down_led7_div
down_led7_0xff
    movlw   0xff
    movwf   led6
    goto down_next6
down_led7_div
    addlw   0
    rrf     led6, 1
down_next6
    movf    led8, 0
    sublw   0xff
    btfsc   STATUS, Z
    goto    down_led8_0xff
    goto    down_led8_div
down_led8_0xff
    movlw   0xff
    movwf   led7
    addlw   0
    rrf     led8, 1
    goto down_next7
down_led8_div
    addlw   0
    rrf     led7, 1
    addlw   0
    rrf     led8, 1
down_next7
    goto loop1
END

Looplicht 2

28 maart 2009

Dit tweede looplicht lijkt op de eerste. Het verschil is dat deze nu in beide richtingen loopt. Binnen de hoofdlus zijn er nu twee lussen, een voor omhoog en een voor omlaag.

Asmfile: looplicht2.asm
Hexfile: looplicht2.hex

; -----------------------------------------------------------------------
; Template source file generated by piklab
    #include <p16f628a.inc>

; -----------------------------------------------------------------------
; Configuration bits: adapt to your setup and needs
        __CONFIG _WDT_OFF & _PWRTE_OFF & _INTOSC_OSC_NOCLKOUT & _MCLRE_ON & _BOREN_ON & _LVP_OFF & _DATA_CP_OFF & _CP_OFF

; -----------------------------------------------------------------------
; Variables declaration
INT_VAR UDATA_SHR
w_saved      RES 1 ; variable used for context saving
status_saved RES 1 ; variable used for context saving
pclath_saved RES 1 ; variable used for context saving

CBLOCK 0x20
		cntr1
		cntr2
		cntr3
ENDC

; -----------------------------------------------------------------------
; reset vector
STARTUP CODE 0x000
    nop                    ; needed for ICD2 debugging
    movlw   high start     ; load upper byte of 'start' label
    movwf   PCLATH         ; initialize PCLATH
    goto    start          ; go to start of main code

; interrupt vector
INT_VECTOR CODE 0x004
    goto    interrupt      ; go to start of interrupt code

; relocatable code
PROG CODE
interrupt
    movwf   w_saved        ; save context
    swapf   STATUS,w
    movwf   status_saved
    movf    PCLATH,w       ; only required if using more than first page
    movwf   pclath_saved
    clrf    PCLATH
    ; << insert interrupt code >>
    movf    pclath_saved,w ; restore context
    movwf   PCLATH
    swapf   status_saved,w
    movwf   STATUS
    swapf   w_saved,f
    swapf   w_saved,w
    retfie

start
    bsf     STATUS, RP0
    movlw   0
    movwf   TRISB
    bcf     STATUS, RP0
    movlw   b'00000001'
loop1
    movwf   PORTB
    call    delay
    rlf     PORTB, 0        ; Schuif links 
    btfss   STATUS, C       ; Carry == 1 ?
    goto    loop1           ; Nee, hoogste was nog niet gezet volgende
    addlw   0x40            ; Ja, zet op een na hoogste en wis carry
loop2
    movwf   PORTB
    call    delay
    rrf     PORTB, 0        ; Schuif rechts
    btfss   STATUS, C       ; Carry == 1 ?
    goto    loop2           ; Nee, laagste was nog niet gezet, volgende
    addlw   2               ; Ja, zet op een na laagste en wis carry
    goto    loop1
    
delay	
    movlw	D'1'
    movwf	cntr3
delay1
    movlw	0x82
    movwf	cntr2
delay2
    movlw	0xff
    movwf	cntr1
delay3
    decfsz	cntr1, f 
    goto	delay3
    decfsz	cntr2, f
    goto	delay2
    decfsz	cntr3, f
    goto	delay1
    return
END

Looplicht 1

19 maart 2009

Dit is een simpel looplicht, die de ledjes aangesloten aan PortB in volgorde laat oplichten. Van bit 0 tot bit 7 en dan weer van voor af aan. Hij lijkt wat op het looplicht van Oefening 4 van de in de vorige post genoemde tutorial (Link) Echter in plaats van de bitpatronen hard te coderen maak ik gebruik van de instructie rlf. Ook loopt mijn eerste variant maar een richting op.

De rlf instructie roteert het register rechtsom via de carry en plaatst het resultaat in register W. (Door directieveld in de instructie.) Na bit 7 zijn alle bits 0 en is de carry 1. De instructie adwl 1 telt 1 bij W op (en zet dus weer bit 0), maar belangrijker is dat deze ook de carry wist.

De template waarin dit programma geschreven is komt van het programma Piklab. Deze bevat een lege interrupt routine. Deze heb ik laten staan al worden er geen interrupts gebruikt.

Voor het mooie zou het roteren van de bits niet direct op PortB moeten gebeuren. Nu leest de instructie de input latch van PortB. Dat kan rare patronen opleveren als PortB hoog of laag gedwongen wordt door aangesloten componenten.

Asmfile: looplicht.asm
Hexfile: looplicht.hex

; -----------------------------------------------------------------------
; Looplicht.asm 
; Simpel looplicht van portb0 naar portb7
    #include <p16f628a.inc>

; -----------------------------------------------------------------------
; Configuration bits: adapt to your setup and needs
        __CONFIG _WDT_OFF & _PWRTE_OFF & _INTOSC_OSC_NOCLKOUT & _MCLRE_ON & _BOREN_ON & _LVP_OFF & _DATA_CP_OFF & _CP_OFF

; -----------------------------------------------------------------------
; Variables declaration
INT_VAR UDATA_SHR
w_saved      RES 1 ; variable used for context saving
status_saved RES 1 ; variable used for context saving
pclath_saved RES 1 ; variable used for context saving

CBLOCK 0x20
		cntr1
		cntr2
		cntr3
ENDC

; -----------------------------------------------------------------------
; reset vector
STARTUP CODE 0x000
    nop                    ; needed for ICD2 debugging
    movlw   high start     ; load upper byte of 'start' label
    movwf   PCLATH         ; initialize PCLATH
    goto    start          ; go to start of main code

; interrupt vector
INT_VECTOR CODE 0x004
    goto    interrupt      ; go to start of interrupt code

; relocatable code
PROG CODE
interrupt
    movwf   w_saved        ; save context
    swapf   STATUS,w
    movwf   status_saved
    movf    PCLATH,w       ; only required if using more than first page
    movwf   pclath_saved
    clrf    PCLATH
    ; << insert interrupt code >>
    movf    pclath_saved,w ; restore context
    movwf   PCLATH
    swapf   status_saved,w
    movwf   STATUS
    swapf   w_saved,f
    swapf   w_saved,w
    retfie

start
    bsf     STATUS, RP0
    clrf    TRISB               ; Port B allemaal outputs
    bcf     STATUS, RP0
    movlw   b'00000001'
    movwf   PORTB
loop
    call    delay
    rlf     PORTB, 0
    btfsc   STATUS, C          ; carry == 1, bit7 was 1
    addlw   1                  ; start start opnieuw met bit0, wist carry
    movwf   PORTB
    goto    loop              ; oneindige lus

delay	
    movlw	D'1'          ; delay van ongeveer 100ms
    movwf	cntr3
delay1
    movlw	0x82
    movwf	cntr2
delay2
    movlw	0xff
    movwf	cntr1
delay3
    decfsz	cntr1, f
    goto	delay3
    decfsz	cntr2, f
    goto	delay2
    decfsz	cntr3, f
    goto	delay1
    return

END

Schema looplicht tests PIC 16f628a

18 maart 2009

Ik ben begonnen met het programmeren van PIC microcontrollers met een 16f628a. De eerste probeersels zijn gebaseerd op een tutorial. Link

Mijn schema is een wat beperktere versie van het in de tutorial getoonde schema.

PIC test schema

PIC test schema

Volgende posts beschrijven een aantal looplicht varianten, de gebruikte programmer en tools.