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. Required fields are marked *

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.