tab が変だけど…
;
; X68000のキーボードからキーコードを読み取り
; LCDに表示してみる
;
; 2001/11/16 作成
; 2001/11/21 更新
;
; 秋月アセンブラ用
; ----__----
; RA2 1-|* |-18 RA1
; RA3 2-| |-17 RA0
; RA4 TOCKI 3-| |-16 OSC1 CLKIN
; /MCLR 4-| |-15 OSC2 CLKOUT
; Vss 5-| PIC16C84 |-14 Vdd
; RB0 INT 6-| |-13 RB7
; RB1 7-| |-12 RB6
; RB2 8-| |-11 RB5
; RB3 9-| |-10 RB4
; ----------
; I/Oポートの割り当て
; PORT A
LCD_E equ 0 ; RA0 - LCD E
LCD_RS equ 1 ; RA1 - LCD RS
X68_READY equ 2 ; RA2 - X68 KY READY
; RA3 - 未使用 (入力に設定し、GNDへ接続)
; RA4 - 未使用 (入力に設定し、GNDへ接続)
; PORT B
PC_DATA equ 0 ; RB0 - PS/2 DATA (外部にプルアップ抵抗をつける 2kくらい?)
PC_CLK equ 1 ; RB1 - PS/2 CLK (外部にプルアップ抵抗をつける 2kくらい?)
X68_RxD equ 2 ; RB2 - X68 KY RxD
X68_TxD equ 3 ; RB3 - X68 KY TxD
LCD_DB4 equ 4 ; RB4 - LCD DB4
LCD_DB5 equ 5 ; RB5 - LCD DB5
LCD_DB6 equ 6 ; RB6 - LCD DB6
LCD_DB7 equ 7 ; RB7 - LCD DB7
; LCDの余ったピンの処理
; LCD DB0 - GND
; LCD DB1 - GND
; LCD DB2 - GND
; LCD DB3 - GND
; LCD R/~W - GND 常時ライト
.16c84 ; デバイスの設定(省略できません)
.osc HS ; 発振タイプの設定
; LP ローパワー発振子(〜約200kHz)
; HS 高速クリスタル(約4MHz〜20MHz)
; RC RC発振
; XT クリスタル・セラロック(〜約4MHz)
.wdt off ; ウォッチドックタイマの有効・無効の設定
; 省略時は“on”
.pwrt on ; パワーアップタイマの有効・無効の設定
.protect off ; プロテクトの設定
; “on”にすると、その IC からプログラムを読み出す事が
; 出来なくなる
; 省略時は“off”
; eedata {value[,value..]} ; データ EEPROM の初期値をセットする
; この命令を使用することで、プログラムの
; 書き込みと同時にデータ EEPROM の内容を
; 書き込む事が出来る
; (PIC16x84 のみ有効)
; eeorg {value} ; データ EEPROMのアセンブラ内部アドレスをセットする
; (eedata 命令で書き込むアドレスをセットする)
; (PIC16x84 のみ有効)
; -----------------------------------------------------------------------------
; システムレジスタにラベル付け
TMR0 equ 01h ; タイマ(BANK0)
PCL equ 02h ; プログラムカウンタの下位8ビット(BANK0)
STATUS equ 03h ; ステータスレジスタ(BANK0)
C equ 0 ; STATUS,C キャリーフラグ
DC equ 1 ; STATUS,DC DCフラグ
Z equ 2 ; STATUS,Z ゼロフラグ
PD equ 3 ; STATUS,PD パワーダウンフラグ
TO equ 4 ; STATUS,TO タイムアウトフラグ
RP0 equ 5 ; STATUS,RP0 RAMのバンク切り替え
PORTA equ 05h ; I/OポートA(BANK0)
PORTB equ 06h ; I/OポートB(BANK0)
INTCON equ 0bh ; 割り込み制御レジスタ(BANK0)
RBIF equ 0 ; RB<4:7>ポートチェンジ割り込みフラグ
INTF equ 1 ; INT(RA4)割り込みフラグ
T0IF equ 2 ; TMR0オーバーフロー割り込みフラグ
RBIE equ 3 ; RBIF割り込み許可
INTE equ 4 ; INTF割り込み許可
T0IE equ 5 ; TMR0割り込み許可
EEIE equ 6 ; データEEPROM書き込み終了割り込み許可
GIE equ 7 ; 全体割り込み許可
OPTION equ 01h ; オプションレジスタ(BANK1)
RBPU equ 7 ; OPTION,RBPU ポートBのプルアップ 0:行う 1:行わない
TRISA equ 05h ; ポートA出力/入力設定 0:出力 1:入力(BANK1)
TRISB equ 06h ; ポートB出力/入力設定 0:出力 1:入力(BANK1)
; 定数のセット
; PICの動作クロックに応じて書き換えてください
CONST_WAIT_MS equ 250 ; ms 単位のウェイト用定数
; CONST_WAIT_MS = (動作クロック[MHz]/4)*100
; 10MHz 時 250
; 8MHz 時 222
; 6MHz 時 150
CONST_COMSPEED equ 130 ; シリアル通信用割り込み間隔
; CONST_COMSPEED = 255 - (osc[Hz] / bps / 32)+5?
; 例1
; 255 - (10000000{Hz] / 2400[bps] / 32) = 125
; -----------------------------------------------------------------------------
; 変数を宣言
org 0ch
temp1 ds 1 ; 0ch から 1 バイト分のメモリを確保し、
; ラベル“temp1”を付ける(変数temp1)汎用一時変数
temp2 ds 1 ; 汎用一時変数
temp3 ds 1 ; 汎用一時変数
temp4 ds 1 ; 汎用一時変数
temp5 ds 1 ; 汎用一時変数
lcd_temp1 ds 1 ; LCD表示で使う変数
lcd_temp2 ds 1 ; LCD表示で使う変数
lcd_temp3 ds 1 ; LCD表示で使う変数
lcd_temp4 ds 1 ; LCD表示で使う変数
wait_count1 ds 1 ; ウェイトルーチンで使うカウンタ
wait_count2 ds 1 ; ウェイトルーチンで使うカウンタ
int_w ds 1 ; 割り込み処理でのレジスタ退避用
int_status ds 1 ; 割り込み処理でのレジスタ退避用
x68txd ds 1 ; 送信バッファ
x68rxd ds 1 ; 受信バッファ
int_x68rmode ds 1 ; 受信処理内部状態
int_x68rcount ds 1 ; 受信割り込みカウンタ
int_x68tmode ds 1 ; 送信処理内部状態
int_x68tcount ds 1 ; 送信割り込みカウンタ
com_status ds 1 ; 通信ステータスフラグ
x68receiving equ 0 ; com_status,x68receiving 受信中
x68transmitrq equ 1 ; com_status,x68transmitrq 送信要求
x68rxdvalid equ 2 ; com_status,x68rxdvalid 受信データ有効
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; リセット処理
org 000h
goto start
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; 割り込み処理
org 004h
interrupt
movwf int_w ; wレジスタを退避
movf STATUS,0
movwf int_status ; ステータスレジスタを退避
movlw CONST_COMSPEED
movwf TMR0 ; TMR0プリセット
; -----------------------------------------------------------------------------
; x68キーボードとの通信処理
; 2400bps,8ビット,ストップビット1,パリティなし
; 受信すると x68rxd にデータが入り
; キーレディ信号 PORTA,X68_READY を 0
; データ有効フラグ com_status,x68rxdvalid を 1 にセットする
; 受信処理中は 受信処理中フラグ com_status,x68receiving が 1 になる
; プログラムで受信データを引き受けたら、
; キーレディ信号 PORTA,X68_READY を 1
; にすることで、次のデータの受信を行う
; (PORTA,X68_READY を 1 にしなければ、キーボードが次のデータを送信してこない)
; 受信処理
movf int_x68rmode,0 ; 内部状態に応じて分岐
addwf PCL,1 ; PCL=PCL+int_x68rmode
goto int_x68rmode0 ; スタートビット検出処理
goto int_x68rmode1 ; 本当にスタートビット?
goto int_x68rmode2_9 ; データの受信1
goto int_x68rmode2_9 ; データの受信2
goto int_x68rmode2_9 ; データの受信3
goto int_x68rmode2_9 ; データの受信4
goto int_x68rmode2_9 ; データの受信5
goto int_x68rmode2_9 ; データの受信6
goto int_x68rmode2_9 ; データの受信7
goto int_x68rmode2_9 ; データの受信8
goto int_x68rmode10 ; 受信処理終わり
int_x68rmode0
btfsc PORTB,X68_RxD
goto int_x68rbreak ; スタートビットを確認せず 中断
; X68_RxDが0 スタートビットがきた
bsf com_status,x68receiving ; 受信中フラグセット
movlw 2
movwf int_x68rcount ; int_x68rcount=2
incf int_x68rmode,1 ; int_x68rmode=int_x68rmode+1=1
goto int_x68rend
int_x68rmode1
btfsc PORTB,X68_RxD
goto int_x68rbreak ; スタートビットを確認せず 中断
; スタートビットを確認した
decf int_x68rcount,1 ; int_x68rcount=int_x68rcount-1
btfss STATUS,Z
goto int_x68rend ; int_x68rcountがゼロでなければ終了
; 3回続けてスタートビットを確認したので受信処理に入る
movlw 4
movwf int_x68rcount ; int_x68rcount=4
incf int_x68rmode,1 ; int_x68rmode=int_x68rmode+1=2
bcf com_status,x68rxdvalid ; 受信データ有効フラグクリア
clrf x68rxd ; 受信バッファクリア
goto int_x68rend
int_x68rmode2_9
decf int_x68rcount,1 ; int_x68rcount=int_x68rcount-1
btfss STATUS,Z
goto int_x68rend ; int_x68rcountがゼロでなければ終了
; 実際の受信 (割り込みが4回発生するごとに1回実行される)
rrf x68rxd,1 ; 受信バッファを右シフト
btfsc PORTB,X68_RxD
bsf x68rxd,7 ; RxDが1なら受信バッファのbit7をセット
movlw 4
movwf int_x68rcount ; int_x68rcount=4
incf int_x68rmode,1 ; int_x68rmode=int_x68rmode+1
goto int_x68rend
int_x68rmode10
decf int_x68rcount,1 ; int_x68rcount=int_x68rcount-1
btfss STATUS,Z
goto int_x68rend ; int_x68rcountがゼロでなければ終了
btfss PORTB,X68_RxD
goto int_x68rbreak ; ストップビットを確認せず 中断
; 受信正常終了
bcf PORTA,X68_READY ;
bsf com_status,x68rxdvalid ; 受信データ有効フラグセット
; 受信異常終了
int_x68rbreak
bcf com_status,x68receiving ; 受信中処理フラグクリア
clrf int_x68rmode
clrf int_x68rcount
int_x68rend
; -----------------------------------------------------------------------------
; 送信処理
; x68txd にデータをセットして
; 送信要求フラグ com_status,x68transmitrq を 1 にすると
; 送信が開始される
; 送信が終了すると com_status,x68transmitrq が 0 になる
; 送信を開始する前に com_status,x68transmitrq が 0 であることを確認する必要あり
movf int_x68tmode,0 ; 内部状態に応じて分岐
addwf PCL,1 ; PCL=PCL+int_x68tmode
goto int_x68tmode0 ; スタートビットを送信
goto int_x68tmode1_8 ; 1ビット目を送信
goto int_x68tmode1_8 ; 2ビット目を送信
goto int_x68tmode1_8 ; 3ビット目を送信
goto int_x68tmode1_8 ; 4ビット目を送信
goto int_x68tmode1_8 ; 5ビット目を送信
goto int_x68tmode1_8 ; 6ビット目を送信
goto int_x68tmode1_8 ; 7ビット目を送信
goto int_x68tmode1_8 ; 8ビット目を送信
goto int_x68tmode9 ; ストップビットを送信
goto int_x68tmode10 ; 送信おわり
int_x68tmode0
btfss com_status,x68transmitrq
goto int_x68tend ; 送信要求フラグが0なら終了
movlw 4
movwf int_x68tcount ; int_x68tcount=4
incf int_x68tmode,1 ; int_x68tmode=int_x68tmode+1=1
bcf PORTB,X68_TxD ; スタートビット(0)を送信
goto int_x68tend
int_x68tmode1_8
decf int_x68tcount,1 ; int_x68tcount=int_x68tcount-1
btfss STATUS,Z
goto int_x68tend ; int_x68rcountがゼロでなければ終了
; 受信バッファの下位ビットから順に送信する
btfsc x68txd,0
goto intx68tmode1_8_1
intx68tmode1_8_0
bcf PORTB,X68_TxD ;送信バッファのbit0が0なら0を送信
goto intx68tmode1_8end
intx68tmode1_8_1
bsf PORTB,X68_TxD ;送信バッファのbit0が1なら1を送信
intx68tmode1_8end
rrf x68txd,1 ;送信バッファを右シフト
movlw 4
movwf int_x68tcount ; int_x68tcount=4
incf int_x68tmode,1 ; int_x68tmode=int_x68tmode+1
goto int_x68tend
int_x68tmode9
decf int_x68tcount,1 ; int_x68tcount=int_x68tcount-1
btfss STATUS,Z
goto int_x68tend ; int_x68rcountがゼロでなければ終了
bsf PORTB,X68_TxD ; ストップビット(1)を送信
movlw 4
movwf int_x68tcount ; int_x68tcount=4
incf int_x68tmode,1 ; int_x68tmode=int_x68tmode+1
goto int_x68tend
int_x68tmode10
decf int_x68tcount,1 ; int_x68tcount=int_x68tcount-1
btfss STATUS,Z
goto int_x68tend ; int_x68rcountがゼロでなければ終了
clrf int_x68tcount
clrf int_x68tmode
bcf com_status,x68transmitrq ; 送信が終わりましたの印
int_x68tend
;*****************************************************************************
btfsc temp1,0 ; 割り込み動作のテスト
goto int_portclr ; 割り込みが入るたびにポートBを反転する
goto int_portset
int_portclr
clrf temp1 ;
bcf PORTB,0 ;
goto int_return
int_portset
decf temp1,1
bsf PORTB,0 ;
;*****************************************************************************
; -----------------------------------------------------------------------------
; 割り込み処理の終了
int_return
bcf INTCON,T0IF ; TMR0オーバーフロー割り込みフラグをクリア
movf int_status,0
movwf STATUS ; ステータスレジスタを元に戻す
movf int_w,0 ; wレジスタを元に戻す
; goto interrupt
retfie ; 割り込みを許可してリターン
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; 初期設定いろいろ
start
bsf STATUS,RP0 ; bank1
movlw 11000000b ; プリスケーラを使用、分周比1:2
; |||||||+----- PS0 -+
; ||||||+------ PS1 +- プリスケーラ分周比
; |||||+------- PS2 -+
; ||||+-------- PSA プリスケーラ設定 0:TMR0 1:WDT
; |||+--------- RTE TMR0信号のエッジ 0:↑ 1:↓
; ||+---------- RTS TMR0信号のソース 0:内部 1:外部
; |+----------- INTEDG INT 割り込みのエッジ 0:↓ 1:↑
; +------------ /RBPU ポートBのプルアップ 0:行う 1:行わない
movwf OPTION
; I/Oポートの設定
; ポートA
movlw 11111000b ; w=11111000b
; ||||+----- LCD_E out
; |||+------ LCD_RS out
; ||+------- X68_READY out
; |+-------- RA3 - 未使用 in
; +--------- RA4 - 未使用 in
movwf TRISA ; 設定レジスタに書き込み
; ポートB
movlw 00000100b ;
; |||||||+----- PC_DATA out
; ||||||+------ PC_CLK out
; |||||+------- X68_RxD in
; ||||+-------- X68_TxD out
; |||+--------- LCD_DB4 out
; ||+---------- LCD_DB5 out
; |+----------- LCD_DB6 out
; +------------ LCD_DB7 out
movwf TRISB ; 設定レジスタに書き込み
bcf STATUS,RP0 ; bank0
; X68キーボードデータ送出禁止
bcf PORTA,X68_READY
; X68キーボードへの送信ポートを1にしておく
bsf PORTB,X68_TxD
; 変数の初期化
clrf int_x68rmode
clrf int_x68rcount
clrf int_x68tcount
clrf int_x68tmode
clrf com_status
; goto interrupt
; LCDの初期化
movlw 15
call wait ; 15ms 待つ
bcf PORTA,LCD_RS ; RS DB7 DB6 DB5 DB4
movlw 00110000b ; 0 0 0 1 1
call lcd_write4
movlw 5
call wait ; 5ms 待つ
movlw 00110000b
call lcd_write4
movlw 1
call wait ; 1ms 待つ
movlw 00110000b
call lcd_write4
movlw 00100000b ; DB7 DB6 DB5 DB4
call lcd_write4 ; 0 0 1 0
; 4ビットモードに設定
movlw 00101000b ; 4bit, 1/16duty, 5x7
call lcd_write
movlw 00000001b ; 表示クリア
call lcd_write
movlw 2 ; クリアには少し時間がかかるので
call wait ; 2ms 待つ
movlw 00000110b ; エントリーモードセット
call lcd_write ; (カーソルの進み方の設定)
movlw 00001110b ; 表示オン/オフコントロール
call lcd_write ; 表示オン, カーソル表示あり, ブリンクなし
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; 割り込み許可
movlw 10100000b
movwf INTCON ; TMR0割り込み許可
; X68キーボードデータ送出許可
bsf PORTA,X68_READY
; -----------------------------------------------------------------------------
; movlw 0ah ; w=0ah
; call disp_h
;dadada
; goto dadada
; x68txd にデータをセットして
; 送信要求フラグ com_status,x68transmitrq を 1 にすると
; 送信が開始される
; 送信が終了すると com_status,x68transmitrq が 0 になる
; 送信を開始する前に com_status,x68transmitrq が 0 であることを確認する必要あり
movlw 255
call wait
dadada
btfsc com_status,x68transmitrq
goto dadada
movlw 10000000b ; LED全部点灯
movwf x68txd
bsf com_status,x68transmitrq
loop
btfsc PORTA,X68_READY
goto loop ; データを受信するまで何もしない
; bcf PORTA,LCD_RS ; カーソルを1文字目に
; movlw 10000000b
; call lcd_write
; movlw 2
; call wait
movf x68rxd,0 ; 何か受信したら
call disp_h ; キーコード表示
bsf PORTA,X68_READY ; X68キーボードデータ送出許可
goto loop
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; wレジスタの内容を16進表記で表示する
; 例
; 1: movlw 0ah ; w=0ah
; 2: call disp_h
; と実行するとLCDに
; +----------------+
; |0A_ |
; | |
; +----------------+ と表示する
disp_h
clrf lcd_temp4 ; lcd_temp5=0
movwf lcd_temp3 ; lcd_temp3=w
bsf PORTA,LCD_RS ; RS を 1
disp_h_loop
swapf lcd_temp3,0
andlw 00001111b
movwf lcd_temp1 ; lcd_temp1=w
addlw 6 ; w=w+6
btfsc STATUS,DC ; 0fhを超えた(w=9以下)
goto disp_h_1
; 0〜9の時
movlw 030h ; w=030h
addwf lcd_temp1,0 ; w=w+lcd_temp1
call lcd_write
goto disp_h_2
; a〜hの時
disp_h_1
movlw 037h ; w=037h
addwf lcd_temp1,0 ; w=w+lcd_temp1
call lcd_write
disp_h_2
btfsc lcd_temp4,0 ; lcd_temp4のbit0が 0以外ならreturn
return ;
decf lcd_temp4,1 ; lcd_temp4=lcd_temp4-1 (0-1=0ffh)
swapf lcd_temp3,1
goto disp_h_loop
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; LCDへの書き込み
; wレジスタの内容をLCDに書き込む
lcd_write
movwf lcd_temp1 ; lcd_temp1=w
call lcd_write4 ; 上位4ビットの書き込み
swapf lcd_temp1,0 ; lcd_temp1 の上位4ビットと下位4ビットを入れ替えて
; wレジスタに代入
call lcd_write4 ; 下位4ビットの書き込み
return
;
; 書き込みサブルーチンのサブルーチン
; wレジスタの上位4ビットだけを書き込む
; ポートBの下位4ビットは変化しない
lcd_write4
andlw 11110000b ; w=w&11110000b
movwf lcd_temp2 ; 書き込むデータの上位4ビットのみを退避
movf PORTB,0 ; w=PORTB
andlw 00001111b ; w=w&00001111b
; ポートBの下位4ビットのみを取り出し
iorwf lcd_temp2,0 ; w=w|lcd_temp2
movwf PORTB ; ボートBの下位4ビットとデータの上位4ビットを
; 合成してポートBに出力
bsf PORTA,LCD_E ; 書き込み
nop
bcf PORTA,LCD_E
movlw 1
call wait ; 少し待つ
return
; -----------------------------------------------------------------------------
; -----------------------------------------------------------------------------
; wレジスタの値に応じて ms 単位のウェイトを入れる
; 使用変数
; wait_count1,wait_count2
; 例、約2ms待つ
; 1: movlw 2
; 2: call wait
; メモ
; 使用クロックに応じて、定数 CONST_WAIT_MS を定義してください
; CONST_WAIT_MS = (動作クロック[MHz]/4)*100
; 例、8Mhz時
; CONST_WAIT_MS equ 200
wait
movwf wait_count1 ; wait_count1=w
wait_loop1
movlw CONST_WAIT_MS
movwf wait_count2 ; wait_count2=CONST_WAIT_MS
wait_loop2
nop
nop
nop
nop
nop
nop
nop
decfsz wait_count2,1 ; wait_count2=wait_count2-1
goto wait_loop2 ; if wait_count2!=0 goto wait_loop2
decfsz wait_count1,1 ; wait_count1=wait_count1-1
goto wait_loop1 ; if wait_count1!=0 goto wait_loop1
return ; else return
('A`)