山本ワールド
PIC18F46K22でSPIで7セグLEDを4桁ドライブする(アセンブラ)(timer0使用)
概要
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
Copyright (C) 2012 山本ワールド All Rights Reserved.