MSP430 Lauflicht mit Schieberegistern (2x MOS4094 + 16 LEDs)

In diesem Beispiel-Programm wird ein Lauflicht mit zwei Schieberegistern (MOS4094, kaskadiert) programmiert. Die 16 LEDs sind in einem Rechteck/Quadrat/Kreis angeordnet. Die Schieberegister bekommen ihre Daten seriell, somit werden nur 3-4 Ports am MSP430 benötigt um 16 LEDs anzusteuern. Das Programm soll erstmal nur ein kleiner Test für ein größeres Projekt sein.

Schaltplan

16_lauf

In dem Schaltplan fehlen die Stützkondensatoren (100nF), nicht vergessen! Für einen kleinen Testaufbau nicht so tragisch, kann aber trotzdem böse enden.

Bild & Video

16_aufbau

ASM-Programm

FILE: main.asm

;***********************************************
;     ___       _             _     
;    |   |_ _ _| |___ ___   _| |___
;    | | |_'_| . | -_|  _|_| . | -_|
;    |___|_,_|___|___|___|_|___|___|
;
; FILE:     main.asm
; Author:   declis (xdec.de)
;***********************************************

    .cdecls "msp430g2231.h"
    .cdecls "defs.h"
    .ref clock_gen,init_regs,init_TimerA,ISR_TimerA
    .global main
    .text

main:
    mov.w #0x280,SP                    ;initialize stack pointer
    mov.w #WDTPW+WDTHOLD,&WDTCTL       ;stop watchdog timer

    bis.b #data+clock+strobe,&P1DIR    ;P1.0,P1.1,P1.2 -> output
    bic.b #data+clock+strobe,&P1OUT    ;clear data,clock,strobe

    mov.w #0,R15                       ;global flag for TimerA interrupt
                                        ;if R15=1, TimerA interrupt triggered

    bis.b #strobe,&P1OUT               ;storage registers high
    call #init_regs                    ;initialize shift registers (all LEDs off)
    call #init_TimerA                  ;initialize TimerA
    EINT                               ;interrupt enable

loop_start:
    bis.b #data,&P1OUT                 ;data port high
    call #clock_gen                    ;shift one bit into shift-register
                                        ;(one LED on)
    bic.b #data,&P1OUT                 ;data port low
    mov.w #led_number,R4               ;counter for LED position

loop_main:
    cmp.w #1,R15                       ;if TimerA interrupt triggered
    jz loop_shift
    jmp loop_main

loop_shift:
    call #clock_gen                    ;shift to next stage
    mov.w #0,R15                       ;reset ISR flag
    dec.w R4                           ;counter-1
    cmp.w #0,R4                        ;if LED-Position 0 (15th LED on), start again
    jz loop_start
    jmp loop_main

    .sect TIMERA0_VECTOR               ;0xFFF2 Timer A CC0 (".int09")
    .word ISR_TimerA                   ;interrupt service routine for TimerA
    .end

FILE: lib_func.asm

;***********************************************
;     ___       _             _     
;    |   |_ _ _| |___ ___   _| |___
;    | | |_'_| . | -_|  _|_| . | -_|
;    |___|_,_|___|___|___|_|___|___|
;
; FILE:     lib_func.asm
; Author:   declis (xdec.de)
;***********************************************

    .cdecls "msp430g2231.h"
    .cdecls "defs.h"
    .def clock_gen,init_regs,init_TimerA,ISR_TimerA
    .text

;------------------------------------------
; Name:         clock_gen
; Description:  generates a rising edge
;               _||_ (0-1-0)
; Input:        nothing
; Returns:      nothing
; Destroys:     nothing
;------------------------------------------
clock_gen:
    bic.b #clock,&P1OUT
    bis.b #clock,&P1OUT
    bic.b #clock,&P1OUT
    ret

;------------------------------------------
; Name:         init_regs
; Description:  initialize shift registers
;               (all outputs low)
; Input:        nothing
; Returns:      nothing
; Destroys:     nothing
;------------------------------------------
init_regs:
    push.w SR
    push.w R5

    bic.b #data,&P1OUT         ;data port low
    mov.w #led_number,R5       ;counter (16 LEDs)
    cmp.w #0,R5
loop:
    jz alloff                  ;shift-registers filled up with 0's
    call #clock_gen            ;shift 0 into shift-registers
    dec.w R5                   ;counter-1
    jmp loop

alloff:
    pop.w R5
    pop.w SR
    ret

;------------------------------------------
; Name:         init_TimerA
; Description:  initialize Timer A
;               cycles=(seconds*10^6Hz)/8
;               seconds=(8*cycles)/10^6Hz
;               62500 cycles = 500ms
;               SMCLK=~1MHz
; Input:        nothing
; Returns:      nothing
; Destroys:     nothing
;------------------------------------------
init_TimerA:
    bis.w #TASSEL_2+ID_3,&TACTL        ;SMCLK, 8x divider
    mov.w #cycles,&TACCR0
    bis.w #CCIE,&TACCTL0               ;enable TimerA interrupt
    bis.w #MC_1,&TACTL                 ;start timer in up-mode
    ret

;------------------------------------------
; Name:         ISR_TimerA
; Description:  Interrupt Service Routine TA
; Input:        nothing
; Returns:      nothing
; Destroys:     R15
;------------------------------------------
ISR_TimerA:
    mov.w #1,R15                       ;set interrupt flag
    ;everything else will be calculated in main
    reti

    .end

Das Unterprogramm “init_regs” kann man sich theoretisch sparen.

FILE: defs.asm

;***********************************************
;     ___       _             _     
;    |   |_ _ _| |___ ___   _| |___
;    | | |_'_| . | -_|  _|_| . | -_|
;    |___|_,_|___|___|___|_|___|___|
;
; FILE:     defs.h
; Author:   declis (xdec.de)
;***********************************************

#ifndef DEFS_H_
#define DEFS_H_

#define cycles 6250                 /* 50ms delay between shift process */
#define data 0x01                   /* DATA (serial input) on P1.0 */
#define clock 0x02                  /* CLOCK on P1.1 */
#define strobe 0x04                 /* STROBE (storage register) on P1.2 */
#define led_number 16               /* number of LEDs */

#endif /*DEFS_H_*/

Leave a Reply

Your email address will not be published.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

This site uses Akismet to reduce spam. Learn how your comment data is processed.