PIC18F46K22でSPIで7セグLEDを4桁ドライブする(アセンブラ)(timer0使用)

icon 項目のみ表示/展開表示の切り替え

概要

PIC18F46K22 のSPIに74HC595経由で7セグメントLED4桁をドライブする。
回路はSPIで7セグLEDを4桁ドライブする回路のとおりである。
本プログラムはダイナミック点灯のタイミングはtimer0を使用する。
1ms置きに割り込みを掛け桁を切り替えて表示する。
表示内容はメインルーチンで約0.16秒置きにseg7dispサブルーチンを呼び出して設定します。
0~9999まで1ずつカウントしてゼロパディングで表示します。

プログラムの説明

seg7dispサブルーチン

引数ARGH:ARGLを4桁LEDに10進数として表示するデータを作成しdisp7segdataに保存します。

word2deg

2byte整数ARGH:ARGLをBCD4桁に変換しアドレスFSR1に保存します。

div16_8

16bit/8bitを計算します。

spi2rw

WREGの値をSPIへ出力します。

inth

Timer0の割り込みにより起動します。
桁データをLEDに転送します。

ソースファイル

以下のファイルで構成されている
7seg4a1.asm ・・・ メインプログラムとLED制御プログラム

ソースファイルのダウンロード 7seg4a1.zip


; 7SEG LED4桁 ハードウェアSPIダイナミックスキャンサンプル(timer0使用) Version 1.00  2014/02/23
; 慈渓博瑞テクノロジー株式会社 PIC18F46K22 マイコンキット Ver2013.12.08用
;   http://akizukidenshi.com/catalog/g/gK-07231/
;   水晶は16MHzに交換してPICを64MHzで駆動
; MPLAB X IDE v1.85 Microchip MPASM(v5.51)
; PicKit 3

        #INCLUDE <p18f46k22.inc>
        ; 水晶発振(16MHz) クロック分周無 PLL有効(*4) プライマリクロック有効  ウォッチドッグタイマ無効 低電圧プログラム書き込みモード無効
        CONFIG FOSC = HSHP,PLLCFG=ON,PRICLKEN=ON,WDTEN=OFF,LVP=OFF

TMR0SET EQU     d'131'  ; 1/(64MHz/4)*128*(256-131)=0.001m秒

bank0       UDATA     ; 変数の定義 バンク0
disp7segdata  RES   4 ; 表示データ4桁分
disp7segcount RES   1 ; 表示桁位置

Tcount1     RES     1
Tcount2     RES     1
Count16     RES     2 ; LEDに表示する値

ARGL        RES     1
ARGH        RES     1
DIV_A       RES     1 ; 除算の被除数を指定 サブルーチンコール後答えが返る
DIV_MOD     RES     1 ; サブルーチンコール後余りが返る
DIV_B       RES     1 ; 除算の除数を指定
DIV_AL      RES     1
DIV_AH      RES     1
DIV_MODL    RES     1
DIV_MODH    RES     1
DIV_COUNT   RES     1
temp1       RES     1

        CODE
        ORG 0
        goto   start    ;   リセット時
        org 08h
        goto   inth     ;   割り込み

start
        movlb   d'15'
        movlw   b'11100110'     ;   SCK2 SS2 SDO2をデジタル入出力に設定
        movf    ANSELD,BANKED
        andwf   PORTD
        andwf   TRISD
;   i2c2モジュール設定
        movlw   b'00110001'     ;   FOSC/16
        movwf   SSP2CON1
        movlw   b'11000000'     ;   SCKの立下りでデーター更新
        movwf   SSP2STAT

;   LEDの表示桁カウンタを初期化する
        clrf    disp7segcount
;   LEDの表示を初期化する
        setf    WREG
        call    spi2rw
;   Timer0を設定する
        movlw   b'11000110'     ;   8bit FOSC/4 1:128
        movwf   T0CON
        movlw   TMR0SET
        movwf   TMR0L
;   Timer0割り込み許可
        bsf     INTCON,TMR0IE
        bsf     INTCON,GIE
loop2
;   LED表示値を初期化
        clrf    Count16
        clrf    Count16+1
loop1
        movff   Count16,ARGL
        movff   Count16+1,ARGH
;   Count16をLED表示用データーに変換
        call    seg7disp
;   0.16秒wait
        movlw   d'10' ;   64MHz*0.16秒/1024/1024=10
        call    delay1024kc
;   Count16をインクリメント
        incf    Count16
        clrf    WREG
        addwfc  Count16+1
;   Count16==10000の時loop2へジャンプ、10000以外の時はloop1へジャンプ
        movlw   LOW d'10000'
        subwf   Count16,w
        bnz     loop1
        movlw   HIGH d'10000'
        subwfb  Count16+1,w
        bnz     loop1
        bra     loop2


;   引数Wを10進数とみなして7SEG表示データを設定

seg7disp
        lfsr    1,disp7segdata ; BCDデータ格納場所
;   BCDデーターに変換
        call    word2deg
;   桁データ追加
        movlw   b'11100000'
        addwf   disp7segdata
        movlw   b'11010000'
        addwf   disp7segdata+1
        movlw   b'10110000'
        addwf   disp7segdata+2
        movlw   b'01110000'
        addwf   disp7segdata+3
        return

;   WREG*1024*1024クロックwait

delay1024kc
        movwf   Tcount2
delay1024kL1   ;   16*256*256=1024*1024
        clrf    Tcount1
delay4kL22
        clrf    WREG
delay4kL11
        nop
        nop
        decfsz  WREG
        goto    delay4kL11   ;   16*256=4096
        decfsz  Tcount1
        goto    delay4kL22
        decfsz  Tcount2
        goto    delay1024kL1
        return

;   SPI2入出力

spi2rw
        bcf     PORTD,SS2
        movwf   SSP2BUF
        btfss   SSP2STAT,BF
        goto    $-2
        movf    SSP2BUF,w
        bsf     PORTD,SS2
        return

inth    ;   高位割り込み
        bcf     INTCON,TMR0IF ;   割り込みフラグクリア

        lfsr    0,disp7segdata
        movf    disp7segcount,w
        movf    PLUSW0,w ; fsr0+wreg -> w
        call    spi2rw  ;   74HC595へデータを転送

        incf    disp7segcount,w
        andlw   b'00000011'
        movwf   disp7segcount

        movlw   TMR0SET
        movwf   TMR0L
        retfie  FAST

word2deg    ;   2byteの整数を4桁BCDに変換する 引数ARGH:ARGL FSR1:BCD保存先
        movf    ARGL,W
        movwf   DIV_AL
        movf    ARGH,W
        movwf   DIV_AH
        movlw   d'10'
        movwf   DIV_B

        rcall   div16_8
        movf    DIV_MODL,W
        movwf   POSTINC1

        rcall   div16_8
        movf    DIV_MODL,W
        movwf   POSTINC1

        rcall   div16_8
        movf    DIV_MODL,W
        movwf   POSTINC1

        rcall   div16_8
        movf    DIV_MODL,W
        movwf   POSTINC1
        movf    DIV_AL,W
        return


;       除算    DIV_AH:DIV_AL / DIV_B  商はDIV_AH:DIV_AL   余りはDIV_MODL:DIV_MODLに返される
div16_8      ;   16bit/8bit=16bit
        clrf    DIV_MODL
        clrf    DIV_MODH
        movlw   d'16'
        movwf   temp1
div16_8_loop
        bcf     STATUS,C
        rlcf    DIV_AL
        rlcf    DIV_AH
        rlcf    DIV_MODL
        rlcf    DIV_MODH

        movf    DIV_B,W
        subwf   DIV_MODL
        movlw   0
        subwfb  DIV_MODH
        bnc     div16_8_non_sub
        bsf     DIV_AL,0
        bra     div16_8_shift
div16_8_non_sub
        movf    DIV_B,W
        addwf   DIV_MODL
        movlw   0
        addwfc  DIV_MODH
div16_8_shift
        decfsz  temp1
        bra     div16_8_loop
        return

        END