下記はLCDに表示させるプログラムである
LCDのR/W端子のコントロールはやめている、そのため、命令を送る場合には時間を取っている





;; 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になると
    バンク切り替えは無くなって、簡単になってきている


PIC 初歩から始める

PIC16F84AでLEDをアセンブラで点滅させる

MPLAB X IDEやXC8をパソコンにインストールしておく

インストール方法、や使い方は、資料が沢山でているのでPICは楽である

テスト基板は簡単なもので、LED2個、キースイッチ 2個 LCD 2004 4行×20文字
電源 5v をプラボードに取り付けた。
書き換えしながら、ソフトを覚えるので、PICKIT3の接続を回路に組み込んでいる
ICソケットだけの基板は 後日実験する18F14K50用である

工事中ーー