; 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 LED_G  PORTA,0
#define LED_R  PORTA,1


reg20 equ 0x20    ;; 汎用レジスタ 0C ? 4F 68個 (16F84A)
reg21 equ 0x21    

ORG 0    ; リセットベクタ(0番地)を指定する

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戻す


LOOP
   ;MOVLW B'00000001'
   ;MOVWF PORTA   ; PORTAのRA0をオンにする(LED点灯)
   bsf PORTA,1     ;表記方法を変えた
   call t1s

   bcf PORTA,1
   ;MOVLW B'00000000' ;;PORTAのRA0をオフにする
   ;MOVWF PORTA
   call t1s

   btfss PORTA,2     ;PORTAのRA2が0ならば LOOP11へ
   goto LOOP11
   GOTO LOOP

LOOP11
   ;MOVLW B'00000010'
   ;MOVWF PORTA ; PORTAのRA1をオンにする(LED点灯)
   bsf PORTA,0
   call t500ms
   movlw B'00000000'  ;PORTAのRA1をオフする
   MOVWF PORTA
   ;call t500ms

   ;btfss PORTA,3   ; PORTAのRA3がOならば JMPする
   goto LOOP
   ;goto LOOP11




;----------タイマー 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

t1ms:
   movlw D'89' ;w <---89
   movwf reg20 ;レジスタを使用する
   t1ms_1:
   call t10us
   decfsz reg20,f ;0でなければ次の行、違えば 次は飛ばす
   goto t1ms_1
   nop
   goto $+1 ;89*28+ 2+2+5-1 =2500サイクル
return

;-------- 25000サイクル--------------
t10ms:
   movlw D'10'
   movwf reg21
   t10ms_1:
   call t1ms
   decfsz reg21,f
   goto t10ms_1
return

;-------- 250000サイクル--------------
t100ms:
   movlw D'50'
   movwf reg21
   t100ms_1:
   call t1ms
   call t1ms
   decfsz reg21,f
   goto t100ms_1
return

;-------- 1250000サイクル--------------
t500ms:
   movlw D'250'
   movwf reg21
   t500ms_1:
   call t1ms
   call t1ms
   decfsz reg21,f
   goto t500ms_1
return
;----------------------
t1s:
   movlw D'250'
   movwf reg21
   t1s_1:
   call t1ms
   call t1ms
   call t1ms
   call t1ms
   decfsz reg21,f
   goto t1s_1
return



END ; プログラムの終了をアセンブラに指示する

AVRマイコンならC言語下記のようになる

int main () {

//初期化 出力=1 入力=0

PORTA.DIR = 0x00; // 0b0000-0000 全IN
PORTB.DIR = 0x03; // 0b0000-0011

ーーーーーーーーーーーーーーーーーーーーーーーーー
AVRマイコンのアセンブラは 下記のように簡単である

start:
    ldi  w,0  
   out  DDRA,w ;    PORTA入力方向設定
   out  DDRB,w ;     PORTB入力

out命令で 設定する

C言語ならば

main(void)
{
     TRISA = 0b11111100 ; // 1で入力 0で出力 RA2-RA3入力(RA5は入力専用)
     TRISB = 0b00000000 ; // RB3のみ入力、残り全て出力
     PORTA = 0b00000000;

while(1) {

例えば下記はアセンブラの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にもどす

PIC 初歩から始める

#include <pic.h>
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>

#define _XTAL_FREQ 10000000 //PICの外付けクロック 10Mセラロック

__CONFIG(FOSC_HS & DEBUGDIS & LVPDIS & UNPROTECT & MCLRDIS & BOREN & PWRTEN & WDTDIS & INTIO) ;

#pragma config FOSC = HS //セラロック 4M以上
#pragma config WDTE = OFF //ウォッチドッグ
#pragma config PWRTE = ON //電源ON後64ms後にプログラム開始
#pragma config CP = OFF

int main(void)
{
  TRISA = 0b11111100 ; // 1で入力 0で出力 RA2-RA3入力(RA5は入力専用)
  TRISB = 0b00000000 ; // RB3のみ入力、残り全て出力

  PORTA = 0x00;
  __delay_ms(500);
  RA1 =1 ;
  __delay_ms(500);
  RA1 = 0;
  __delay_ms(500);
  RA1 = 1;
  __delay_ms(500);
  RA1 = 0;
  while(1) {
       RA0 =1;
       __delay_ms(500);
       RA0 =0;
       __delay_ms(500);
        if (RA2 == 0 ) { RA1 = 0 ;} // 1番ピンにHIGHを出力する(LED 点灯)
        if(RA3 == 0){RA1 = 1 ;}
       }
  return 0;
}

AVRと比較して使いづらい点は バンクとページの概念だろう。
例えば、PORTA を入力にする出力にするか を設定する場合、いちいち、バンク1に切り替えて設定して またバンク0にもどし、PORTAをコントロールする。

C言語の場合には、あまり気にしなくてもよいので、AVRとの差は無いと考えてよいだろう。

アセンブラ表記ではーーーー
HSや WDT(ウオッチドッグ)は CONFIGに記載することで設定している
HS_OSC,      HS発振モードにする
WDT_OFF     ウオッチドッグOFF設定
CP_OFF      プロテクトしない
PWRTE_ON    電源ON 時 立ち上がりを遅くする

LED1を1秒間隔で点滅しているとき、SW1を押すと LED2が500ms間隔で点滅する。
SW2を押すと もとに戻って LED1が1秒間隔で点滅する。

C言語で下記のプログラムを組んでみた
LED-0 は500msで点滅していて、SWを押すと LED-1が点灯、SW2を押すと LED-1が消灯する
動作OKである。
ーーーーーーーーー
1)最初はコンパイル成功しているのに、LEDが点灯しなかった。 
  原因は
    #pragma config FOSC = HS
  HSは外部クロックでセラロック10M付けていた(16F84Aは内部クロックがない)
  この1行を入れていなかったため、
   
2)LED−1がSWを押さないのに勝手に点滅する
  原因は
   CPUリセットがかかっていた、ウォッチドッグタイマーが働いて、org 0に戻っていた
     #pragma config WDTE = OFF //ウォッチドッグ
  この1行加えることで完了

3)PORTAbits.RA0 =1と RA0=1の違い 
   同じなので 全部 RA0=1 表記にした

工事中ーー

PIC16G48AでLEDを点滅させる事からはじめよう

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

インストール方法、や使い方は、資料が沢山でているのでPICは楽である
ただ、PICはアセンブラは混乱しやすい、後発のAVRの方がわかりやすいと思う、

バンクーーーー
 制御レジスタ 汎用レジスタを区分したもの、7F程度の領域を切り替えてつかう

ページーーーー
 、プログラムを書き込むメモリをブロックごとに区切ったもの
  ちなみに PIC16F84はページは無い

*昔インテル80系は 8ビットで制御するため、アドレスが7Fまで、、だから切り替えて使う必要があった名残であろう。
32ビット、64ビットで多量メモリを使えるようになると面倒な概念だろう
Z80系、AVRは進化して、その概念がなくなっていると考えればよいだろう、

 

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