;; CLOCK 10MHz
; PORTB 0:LED緑,1:LED赤
;
LIST P=PIC16F84A ; LIST宣言で使用するPICを16F84Aと定義する
INCLUDE P16F84A.INC ; 設定ファイルp16f84a.incを読み込む
__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
#define LCD_E PORTB,4
#define LCD_RS PORTB,5
#define LCD_RW PORTA,4 (今回は使っていない)
#define LED_G PORTA,0
#define LED_R PORTA,1
#define KEY_1 PORTA,2
#define KEY_2 PORTA,3
#define LCD_BUSY PORTB,3
CBLOCK 020h
reg20
reg21
lcddat
Xziku
Yziku
ENDC
Yloca0 macro
movlw 0
movwf Yziku
call zahyou
endm
Yloca1 macro
movlw 1
movwf Yziku
call zahyou
endm
Yloca2 macro
movlw 2
movwf Yziku
call zahyou
endm
Yloca3 macro
movlw 3
movwf Yziku
call zahyou
endm
ORG 0 ; リセットベクタ(0番地)を指定する
MAIN
BSF STATUS,RP0 ; ファイルレジスタSTATUSのRP0(ビット5)をセット(1)する → バンク1
movlw B'11111100' ;FC --->wレジスタへ
movwf TRISA ;w---> TRISAへ代入 RA0,1= 出力 1=入力
CLRF TRISB ;0= 全出力
BCF STATUS,RP0 ; STATUSのRP0をクリア(0) → バンク0
bsf PORTA,0
bsf PORTA,1
call t1s
bcf PORTA,0
bcf PORTA,1
call lcd_init
call t100ms
Yloca0
movlw 030h ;1表示
call cara_one
Yloca1
movlw 041h ;A表示
call cara_one
Yloca2
movlw 042h ;B表示
call cara_one
Yloca3
movlw 043h ;C表示
call cara_one
LOOP
bsf PORTA,1
call t500ms
bcf PORTA,1
call t500ms
btfss PORTA,2 ;1ならば JMP次行?
goto LOOP11
GOTO LOOP
LOOP11
bsf PORTA,0
call t500ms
call t500ms
bcf PORTA,0
call t500ms
btfss PORTA,3
goto LOOP
goto LOOP11
LCD_home
movlw 02h
call LCD_command
return
LCD_cls
movlw 01h
call LCD_command
return
LCD_off
movlw 08h
call LCD_command
return
LCD_on
movlw 0Ch
call LCD_command
return
LCD_2line
movlw 0C0h
call LCD_command
return
LCD_3line
movlw 094h
call LCD_command
return
LCD_4line
movlw 0D4h
call LCD_command
return
zahyou
btfsc Yziku,0 ;0bit=0 次命令スキップ
goto zahyou_1
;00 or 10 0or4
btfsc Yziku,1
goto zahyou_2
movlw 080h
goto zahyou_e
;01 or 11 1 or 3
zahyou_1
btfsc Yziku,1 ;1bit=0 skip
goto zahyou_3
movlw 0C0h
goto zahyou_e
zahyou_2
movlw 094h
goto zahyou_e
zahyou_3
movlw 0D4h
zahyou_e
;addwf Xziku
call LCD_command
return
;-------------------------------------------
;上位4ビットを下位にSWAPして転送
;次に下位4ビットを転送
;--------------------------
cara_one
movwf lcddat
bsf LCD_RS
movlw 0F0h
andwf PORTB,F
swapf lcddat,w
andlw 0Fh
iorwf PORTB,F
bsf LCD_E
nop
bcf LCD_E
movlw 0F0h
andwf PORTB,F
movf lcddat,w
andlw 0Fh
iorwf PORTB,F
bsf LCD_E
nop
bcf LCD_E
call t1ms
return
LCD_command
movwf lcddat
bcf LCD_RS ;0=制御
bcf LCD_RW
movlw 0F0h
andwf PORTB,F
swapf lcddat,w
andlw 0Fh
iorwf PORTB,F
bsf LCD_E
nop
bcf LCD_E
movlw 0F0h
andwf PORTB,F
movf lcddat,w
andlw 0Fh
iorwf PORTB,F
bsf LCD_E
nop
bcf LCD_E
call t1ms
return
; LCDのイニシャル------------------------
lcd_init
call t100ms
bcf LCD_RW
bcf LCD_RS ;0=制御モード 1=データモード
bcf LCD_E ;E=0-->1で書き込み
call t10ms
;1) 0011-0000
movlw 0F0h
andwf PORTB,w
iorlw 03h ;1
movwf PORTB ;w--->LCD_DATへ格納
bsf LCD_E
nop
bcf LCD_E
call t10ms
movlw 0F0h
andwf PORTB,w
iorlw 03h ;2
movwf PORTB ;w--->LCD_DATへ格納
bsf LCD_E
nop
bcf LCD_E
call t10ms
movlw 0F0h
andwf PORTB,w
iorlw 03h ;3
movwf PORTB ;w--->LCD_DATへ格納
bsf LCD_E
nop
bcf LCD_E
call t10ms
movlw 0F0h
andwf PORTB,w
iorlw 02h
movwf PORTB ;w--->LCD_DATへ格納
bsf LCD_E
nop
bcf LCD_E
call t1ms
movlw 028h
call LCD_command
call LCD_off
call LCD_cls
movlw 06h
call LCD_command
call LCD_on
bsf LCD_RS ;1=データモード
return
;----------タイマー 10MHZの時---25サイクル(10us)-------------------
t10us:
goto $+1 ;2サイクル
goto $+1
goto $+1
goto $+1
goto $+1
goto $+1 ;2サイクル
goto $+1
goto $+1
goto $+1
goto $+1
nop
return
t500us:
movlw D'50' ;w <---89
movwf reg20 ;レジスタを使用する
t500us_1:
call t10us
decfsz reg20,f ;0でなければ次の行、違えば 次は飛ばす
goto t500us_1
nop
return
t1ms:
movlw D'89' ;w <---89
movwf reg20 ;レジスタを使用する
t1ms_1:
call t10us
decfsz reg20,f ;0でなければ次の行、違えば 次は飛ばす
goto t1ms_1
nop
goto $+1
return
;-------- 25000サイクル--------------
t10ms:
movlw D'10'
movwf reg21
t10ms_1:
call t1ms
decfsz reg21,f
goto t10ms_1
nop
return
;-------- 250000サイクル--------------
t100ms:
movlw D'10'
movwf reg21
t100ms_1:
call t1ms
call t1ms
decfsz reg21,f
goto t100ms_1
nop
return
;-------- 1250000サイクル--------------
t500ms:
movlw D'250'
movwf reg21
t500ms_1:
call t1ms
call t1ms
decfsz reg21,f
goto t500ms_1
nop
return
;----------------------
t1s:
movlw D'250'
movwf reg21
t1s_1:
call t1ms
call t1ms
call t1ms
call t1ms
decfsz reg21,f
goto t1s_1
nop
return
END ; プログラムの終了をアセンブラに指示する
どうしてもAVRと比較してしまう。後発メーカーのAVRは使いやすい
AVRは個人的にはZ80系のアセンブラでわかりやすい。
PICの命令は 8080系のながれなのか、バンク切り替えなどがわかりにくい
例えば、PORTA を入力にする出力にするか を設定する場合、いちいち、バンク1に切り替えて設定して またバンク0にもどし、PORTAをコントロールする。(16F84の場合、、、)
C言語の場合には、あまり気にしなくてもよいので、AVRとの差は無いと考えてよいだろう。
ただし、PICはアセンブラ開発が主流だったためか、メモリは1K程度しかない
でも、アセンブラで1Kを書くのは結構大変なので十分だろう。だ
C言語が主流になってきた今は、PIC1684は古い、AVRのようにメモリが大きくないと困る。
例えば、下記はアセンブラのPORTAの設定であるが、
MAIN
BSF STATUS,RP0 ; ファイルレジスタSTATUSのRP0(ビット5)をセット(1)する
→ バンク1
movlw B'11111100'
movwf TRISA ;RA0,1= 出力 1=入力
CLRF TRISB ;0= 全出力
BCF STATUS,RP0 ; STATUSのRP0をクリア(0) → バンク0にもどす
18F14K50になると
バンク切り替えは無くなって、簡単になってきている
PIC16F84AでLEDをアセンブラで点滅させる
|
MPLAB X IDEやXC8をパソコンにインストールしておく |
インストール方法、や使い方は、資料が沢山でているのでPICは楽である
テスト基板は簡単なもので、LED2個、キースイッチ 2個 LCD 2004 4行×20文字
電源 5v をプラボードに取り付けた。
書き換えしながら、ソフトを覚えるので、PICKIT3の接続を回路に組み込んでいる
ICソケットだけの基板は 後日実験する18F14K50用である
工事中ーー