山本ワールド
timer0 割り込みサンプル
概要
LCD液晶に約1秒おきに0から255までを10進数で表示する。
LCD液晶はSC1602を対象としているが、液晶モジュールの電源の接続をVDD,GNDを入れ替えればSC2004でも対応可能。ただし16文字*2行でしか表示されないので注意。
約1秒間隔は、timer0による割り込みにより設定する。timer0はアップカウント動作を開始し16bitカウンタがオーバーフローしたときに後に割り込みが発生する。timer0は初期値を自動プリセットできないので、割り込み処理ルーチンで再度、timer0を設定している。CPUクロックを分周しているまてクロック周波数に依存している。
クロックはUSB-IOで接続済みの12MHzのセラミック振動子を使用しPLLで4倍にしている。書込みはPICKit3を前提とする。
液晶表示例
HelloPIC18F14K50 123sec回路は次のとおりである。
回路図(PNG) 回路図(PDF) 回路図(DXF)
プログラムの説明
ソースファイル
以下のファイルで構成されているtimer0a.asm ・・・ メインプログラム lcd.asm ・・・ LCD表示用ライブラリ Version 1.00 lcd.inc ・・・ LCD表示用インクルードファイル Version 1.00 stdlib.asm ・・・ 8bit,16bit割り算、2進,10進,16進数値変換等のライブラリ Version 1.00 stdlib.inc ・・・ 8bit,16bit割り算、2進,10進,16進数値変換等のインクルートファイル Version 1.00
ソースファイルのダウンロード lcd1a.zip
lcd.asm
主にSC1602向けのLCD液晶表示用のライブラリである。
液晶モジュールと接続するポートはマクロで変更可能である。
busyフラグはチェックせずソフトウェアディレイで対応しているためクロック周波数が変更された場合はディレイの調整が必要
詳細は以下のリンクを参照されたい
lcd.asm
stdlib.asm
8bit,16bit割り算、2進,10進,16進数値変換等をサポートしたライブラリである
詳細は以下のリンクを参照されたいstdlib.asm
timer0a.asm
メインプログラムである。
IOポートの入出力の設定をし、LCDの初期化サブルーチンコール、timer0の設定をし待機する。約1秒後に割り込みが発生するので、再度timer0を設定し液晶表示後、復帰する。
; LCD液晶に約1秒おきに0から255までを10進数で表示する
;
; File: timer0a.asm
; Target: PIC18F14K50 48Mhz
; アセンブラ: Microchip MPASM(v5.51)
; 書き込み: PICKit 3
; リリース: 2013/10/01 21:00
;
; 液晶表示例
; 列 0123456789abcdef
; 1行目 HelloPIC18F14K50
; 2行目 000 sec
;
; タイマー0を使用して1秒置きに割り込みをかけてカウントする。
;
#INCLUDE <p18f14k50.inc>
; 水晶発振(12MHz) クロック分周無 PLL有効(*4)
; ウォッチドッグタイマ無効 低電圧プログラム書き込みモード無効
CONFIG FOSC = HS,CPUDIV = NOCLKDIV,PLLEN=ON,WDTEN=OFF,LVP=OFF,MCLRE=OFF
#INCLUDE "lcd.inc"
#INCLUDE "stdlib.inc"
; プログラムメモリadsのアドレスをTLPTRレジスタに上書きする
LDTBLPTR MACRO ads
movlw UPPER ads
movwf TBLPTRU
movlw HIGH ads
movwf TBLPTRH
movlw LOW ads
movwf TBLPTRL
ENDM
UDATA ; 変数の定義
Tcount1 RES 1 ; wait
Tcount2 RES 1 ; wait
Tcount3 RES 1 ; wait
LCD_WRITE RES 1 ; writeデータを指定
LCD_TEMP RES 1
LCD_BUF RES d'32' ; 16*2文字分のバッファ
Temp1 RES 1 ; サブルーチン用の変数
ARG1 RES 1 ; サブルーチン引数
BYTE2HEX_TEMP RES 1
COUNT RES 1
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
GLOBAL LCD_WRITE,LCD_TEMP,Temp1
GLOBAL Tcount1,Tcount2,Tcount3
GLOBAL DIV_A,DIV_MOD,DIV_B,DIV_MODL,DIV_MODH,DIV_AL,DIV_AH,ARGH,ARGL,ARG1
GLOBAL BYTE2HEX_TEMP
; Timer0 1秒設定値
TMR0L_1SEC EQU d'229'
TMR0H_1SEC EQU d'72' ; 65536-46875=72*256+229
LED_ADS EQU PORTC
LED0 EQU 0
CODE
ORG 0
goto start ; リセット時
org 08h
goto inth ; 割り込み
start
clrf ANSEL ; RC3-RC0,RA4をデジタル入力バッファに設定
clrf ANSELH ; RB5-RB4,RC7-RC6をデジタル入力バッファに設定
clrf SLRCON ; PORTA,PORTB,PORTCをスルーレートを標準に設定
clrf TRISA ; PORTAを全部出力に設定
movlw b'11110000'
movwf TRISB ; RB7-RB4を入力に設定
movlw b'00000010' ; RC1を予約
movwf TRISC ; PORTCの入出力を設定。
clrf PORTC ; PORTCをクリア
; Timer0設定
movlw b'10000111' ; 16bit FOSC/4/256=46875Hz
movwf T0CON
movlw TMR0H_1SEC
movwf TMR0H
movlw TMR0L_1SEC
movwf TMR0L
call lcd_init ; 液晶初期化
movlw d'32'
movwf Temp1
LDTBLPTR lcd_init_str
lfsr FSR0,LCD_BUF
lcd_init_str_set_loop
tblrd *+ ; プログラムメモリTBLPTRから読み出し後TBLPTRを+1する
movf TABLAT,W
movwf POSTINC0 ; 間接アドレッシング アドレスはアクセス後に+1される
decfsz Temp1 ; Temp1から1を引き結果が0になるまで繰り返す
bra lcd_init_str_set_loop
lfsr FSR1,LCD_BUF
call lcd_disp
clrf RCON
movlw b'00000100' ; timer0高位割り込み RBプルアップ
movwf INTCON2
movlw b'10100000' ; timer0オーバーフロー割り込み有効
movwf INTCON
bsf LED_ADS,LED0
clrf COUNT
goto $
inth ; 高位割り込み
bcf INTCON,TMR0IF ; 割り込みフラグクリア
movlw TMR0H_1SEC
movwf TMR0H
movlw TMR0L_1SEC
movwf TMR0L
btg LED_ADS,LED0
incf COUNT
movf COUNT,W
movwf ARG1
lfsr FSR1,LCD_BUF+d'16'
call byte2deg
lfsr FSR1,LCD_BUF
rcall lcd_disp
retfie FAST
lcd_init_str
; 0123456789abcdef
DB "HelloPIC18F14K50"
DB " sec "
END