; 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にもどす
#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用である