• 検索結果がありません。

レッスン 2: LED 点滅

ドキュメント内 PICkit 3 Starter Kit User’s Guide (ページ 47-51)

Chapter 3. レッスン

3.3 レッスン 2: LED 点滅

PICkit™ 3 スタータキット ユーザガイド

DS41628B_JP - p.48  2015 Microchip Technology Inc.

アセンブリでは非常によく使う命令です。通常、データをWREGに代入した後、演 算を実行するか別のレジスタへ代入します。

3.3.5.1.2 movwf

movlwに似た命令で、WREGのデータを別のレジスタへ代入します。

3-7:

3.3.5.1.3 decfsz

レジスタの値を1 つデクリメントします。デクリメント後のレジスタの値が「0」の 場合、次の命令をスキップします。これは遅延ループの作成に使います。

3.3.5.1.4 bra/goto

これら 2 つの命令は、コードの別のセクションへのジャンプに使います。BRA は現 在のプログラム カウンタの位置からの相対分岐です。エンハンスト ミッドレンジ コ アの場合、カウンタはプログラムメモリの-256≤n≤255のアドレスレンジにアクセス できます。PIC18のBRAは、プログラムメモリの-1024≤n≤1023のアドレスレンジ にアクセスできます。値と符号に注意が必要です。エンハンスト ミッドレンジ コア では、相対分岐を使うとページ境界を越えてジャンプできるため便利です。

gotoは無条件ジャンプで、エンハンスト ミッドレンジの場合は現在のページ内の任 意のアドレスにアクセスできます。PIC18では、goto命令で全てのプログラムメモ リにアクセスできます。ただしプログラムメモリを2ワード必要とする事に注意が必

要です。つまりPIC18では1つのgoto命令がBRA命令の2倍の空間を必要とします。

PIC18では、分岐先アドレスが現在のアドレスから±1024以内であればGOTOではな

く相対分岐を推奨します。エンハンスト ミッドレンジでは、ページ境界を越えたジャ ンプを繰り返す場合のみ相対分岐に利点があります。

3.3.5.2 PIC18

3.3.5.2.1 btg

指定したレジスタのビット値を反転します。

3.3.6 アセンブリ

3.3.6.1 エンハンストミッドレンジ

3-8:

3-6: 新しく学ぶPIC18の命令

命令 英語名 目的

btg Bit Toggle f LEDを点滅する

movwf OPTION_REG 命令実行前:

OPTION_REG = 0xFF W = 0x4F

命令実行後:

OPTION_REG = 0x4F W = 0x4F

movlw b'00111000' ;set cpu clock speed movwf OSCCON

ここではPIC MCUの動作周波数を500 kHzに設定しています。ワーキング レジスタ

(WREG) を使ってレジスタにバイト値を代入します。このレジスタへの書き込みを

省略した場合も、PIC16F1829は既定値の500 kHzで動作します。しかし既定値は デバイスによって異なるため、コードの冒頭で必ずこのレジスタへの書き込みが必 要です。これで、PIC MCUは1命令を8 µsで実行するようになります(式3-1参照)。

3-1: 実行時間

LEDを点滅させるには、まずLEDを点灯した後に一定時間待ってから同じ時間だけ LEDを消灯するようにプログラムを記述する必要があります。これには内蔵RAMを 使います。

3-9:

CBLOCKはユーザメモリを割り当てます。CBLOCKの後の数値は、どのアドレスからメ モリを割り当てるかを指定します。0x70は、エンハンスト ミッドレンジ コアでは全 てのバンクで共有する共通RAM のアドレスです。ここに格納できるのは16 バイト のみです。これらの変数を使う場合、プログラムでバンクを切り換える必要はありま せん。ここから先のレッスンでは、エンハンスト ミッドレンジではこの共通RAMに、

PIC18ではアクセスRAMに変数を格納します。ここに、以下の遅延ループを作成す

るための2つの変数を格納します。

3-10:

braでループ先頭に戻り、処理を繰り返します。このループの実行には3命令サイク ル (デクリメントに1命令サイクル、braに2命令サイクル)かかります。そしてカ ウンタの動作によってこのループを 256 回実行するため、実行には合計768命令サ イクルがかかります。それでも、人間の目にはほとんど認識できないほどの速さです。

そこで、このループの外側にもう 1 つのループを追加してさらに速度を落とします。

内周ループの実行時間が768サイクルで、外周ループの3 サイクルを足したもの を256回繰り返します。すなわち、実行時間は(768+3) * 256 = 197376命令/125K命 令/s = 1.579 sです。

Instruction time 1 FOSC

---4 --- 1

500kHz ---4 --- 8 µS

= = =

cblock 0x70 ;shared memory location that is accessible from all banks Delay1 ; Define two file registers for the delay loop in shared memory Delay2

endc

bsf LATC, 0 ; turn LED on OndelayLoop:

decfsz Delay1,f ; Waste time.

bra OndelayLoop ; The Inner loop takes 3 instructions per loop * 256 loops = 768 instructions

decfsz Delay2,f ; The outer loop takes an additional 3 instructions per lap * 256 loops bra OndelayLoop ; (768+3) * 256 = 197376 instructions / 125K instructions per second = 1.579 ;sec.

bcf PORTC,0 ; Turn off LED C0 - NOTE: do not need to switch banks with 'banksel' since ;bank0 is still selected

OffDelayLoop:

decfsz Delay1,f ; same delay as above bra OffDelayLoop

decfsz Delay2,f bra OffDelayLoop

bra MainLoop ; Do it again...

PICkit™ 3 スタータキット ユーザガイド

DS41628B_JP - p.50  2015 Microchip Technology Inc.

goto命令とbra命令が2命令サイクルを必要とするのは、このプロセッサがパイプラ イン構造をしているためです。プロセッサは現在の命令を実行中に次の命令をフェッチ します。プログラムが発生すると、gotoまたはbraの後のフェッチ済み命令は実行 されません。その代わりにNOPが実行され、その間に分岐先の命令をフェッチします。

変数Delay1とDelay2は0から255へロールオーバします。このため、デクリメ ントする前に変数Delay1とDelay2に値を代入しておく必要はありません。

3.3.6.2 PIC18

エンハンスト ミッドレンジ コアには全バンクで共有できる汎用RAM (共通RAM)が 16バイトありますが、PIC18にはこれに相当する領域として0x00->0x5Fがあります。

この96バイトはバンク指定なしでアクセスできます。

3-11:

3.3.7 C言語

3.3.7.1 両デバイス共通

変数カウンタを使ったCによる遅延ループでは、実際の遅延時間は予測できません。

C コードの場合、PIC MCU に書き込む前にコンパイラがユーザコードをアセンブリ に変換するステップが入ります。ループの実行時間は、コンパイラの効率およびプロ グラムの記述方法によって異なります。従って、遅延ループ用のライブラリ関数を使 う事を推奨します。

このレッスンでは両方の方法を紹介します。このレッスンのコードの最後でコメント アウトしたセクションは、XC8コンパイラ内蔵の高精度な遅延関数を使っています。

これ以降のレッスンでは、この内蔵遅延マクロを使います。

3-12:

この高精度なルーチンを使うには、PIC MCU のプロセッサ速度を定義しておく必要 があります。

3-13:

変数delayを作成し、デクリメントしてからLEDをトグルしています。^はピンの 値と「1」をXOR演算しており、これによってピンの値をトグルしています。コンパ イラの最適化レベルを変えると生成されるコードが変化し、遅延時間が増減します。

cblock 0x00 ; Access RAM

Delay1 ; Define two file registers for the delay loop in shared memory Delay2

endc

#define _XTAL_FREQ 500000 //Used by the HI-TECH delay_ms(x) macro

delay = 7500;

while (1) {

while(delay-- != 0)continue; //each instruction is 8us (1/(500KHz/4)) LATCbits.LATC0 ^= 1; //toggle the LED

delay = 7500; //assign a value since it is at 0 from the delay loop

ドキュメント内 PICkit 3 Starter Kit User’s Guide (ページ 47-51)