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

レッスン 5: 可変速ローテート

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

Chapter 3. レッスン

3.6 レッスン 5: 可変速ローテート

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

DS41628B_JP - p.60  2015 Microchip Technology Inc.

call命令はスタックを1段使います。前述の通りPIC18のスタックサイズは31段で、

エンハンスト ミッドレンジ コアは16段です。call命令を実行するたびにリターン アドレスがスタックにプッシュされ、プログラム カウンタはlabelのプログラムメ モリ アドレスへ移動します。

スタックの深さを超えないように注意する必要があります。例えば、PIC16F1829で 一度もリターンアドレスに戻らずcall命令を17回実行すると、スタック オーバーフ ローが発生します。

PIC18のcall命令はプログラム空間を2ワード占有しますが、プログラム空間の任

意のアドレスに移動できます。エンハンスト ミッドレンジでは、callのジャンプ先 が現在選択中のページ以外にある場合、まずページ選択ビットを設定してから call を実行する必要があります。

3.6.5.1.2 RETURN

return命令を実行すると、スタックに最後に保存したアドレスがプログラム カウン タに戻り、スタックポインタはプログラム カウンタの直前のcallに移動します。こ れで、プログラム カウンタはcall命令の直後の命令を指し示します。call命令を 実行せずにreturn文を実行すると、スタック アンダーフローが発生します。

STVRENコンフィグレーション ビットを使うと、スタック アンダーフロー/オーバー

フロー時にリセットを発生させる事ができます。call命令とreturn命令はどちら も2サイクル必要です。

3.6.5.1.3 XORWF

このレッスンでは、XORWFを使ってA/D変換結果が0かどうかを調べます。以下に XORの真理値表を示します。

3-24:

これは、Delay2レジスタと「0」をXOR演算してDelay2の値が「0」かどうかを調 べています。Delay2の値が「0」であればXOR演算結果が「0」となるため、STATUS レジスタのZビットがセットされます。

3.6.5.2 PIC18

3.6.5.2.1 TSTFSZ

レジスタが「0」かどうかをこの命令で簡単に調べる事ができます。PIC18では、PIC16の

3-25: XORの真理値表

入力

A B 出力

0 0 0

0 1 1

1 0 1

1 1 0

movlw d'0' ;load wreg with '0'

xorwf Delay2, w ;XOR wreg with the ADC result and save in wreg

btfss STATUS, Z ;if the ADC result is NOT '0', then simply return to MainLoop

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

命令 英語名 目的

tstfsz Test f, skip if 0 簡単なゼロチェック(IF文)

rcall Relative Call コードのモジュール化

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

DS41628B_JP - p.62  2015 Microchip Technology Inc.

3-25:

Delay2が「0」の場合、return命令はスキップされるため実行されません。

3.6.5.2.2 rcall

ジャンプ先アドレスが現在のプログラム カウンタのアドレスから1Kのレンジ内にあ る場合はrcallを使います。これは、通常のcall命令がプログラム空間を2ワー ドを占有するのに対し、rcall命令は1ワードしか占有しないためです。

3.6.6 アセンブリ

3.6.6.1 両デバイス共通 例3-26:

call を使う事で、これまでのレッスンに比べ、メインループの可読性が向上しています。

その他、ADC、遅延ループ、ローテートのモジュール(関数)があります。callの 後はgotoではなくreturnで戻るように注意します。

CheckIfZeroは、遅延ループが0から255へロールオーバーしないようにするために 必要です。このcall命令を省略すると、A/D変換結果が「0」の場合にLEDのロー テート速度が非常に遅くなります。

3.6.7 C言語

こちらのコード実装の方がはるかに理解が容易です。

3-27:

このルーチンは、A/D変換結果が「0」の場合に少なくとも50 msの遅延を挿入し ます。A/D変換結果の値が1つ大きくなるたびに、このループで2 msの遅延を挿入 します。

このレッスンでは、新たに関数呼び出しも使っています。

これは、アセンブリでcallを実装するのと同じです。プログラムカウンタはプログ ラム空間内でこの ADC関数が存在するアドレスへ移動し、コードを実行します。そ して1つの値を返し、これをdelayに代入します。

なお、関数の実体をmain関数の後で定義する場合、最初にプロトタイプを宣言して おく必要がある点に注意します。

tstfsz Delay2 ;if the ADC result is NOT '0', then simply return to MainLoop return ;return to MainLoop

MainLoop:

call A2d ;get the ADC result

;top 8 MSbs are now in the working register (Wreg) movwf Delay2 ;move ADC result into the outer delay loop

call CheckIfZero ;if ADC result is zero, load in a value of '1' or else the delay loop will decrement starting at 255

call DelayLoop ;delay the next LED from turning ON call Rotate ;rotate the LEDs

bra MainLoop ;do this forever

__delay_ms(50); //delay for AT LEAST 50ms

while (delay-- != 0) __delay_ms(2); //decrement the 8 MSbs of the ADC and delay 2ms for each

delay = adc(); //grab the top 8 MSbs

unsigned char adc(void); //prototype

3.7 レッスン 6: デバウンス

3.7.1 レッスンの紹介

機械式スイッチはコンピュータ、マイクロプロセッサ、マイクロコントローラを使っ たほとんど全てのアプリケーションで幅広く使われ、重要な役割を果たしています。

機械式スイッチは低コストで信頼性に優れています。しかし機械式スイッチにはノイ ズの問題があります。ノイズの主な要因はスイッチの瞬間的な開閉にあり、電気的な 状態がきれいに(なめらかに)遷移する事はほとんどありません。最終的にスイッチ の状態が安定するまでに何回も接点の開閉が繰り返され、場合によっては数百回にも 及ぶ事があります。

この問題はスイッチのバウンス (チャタリング)と呼ばれます。このように開閉が繰り 返される原因の 1 つに、スイッチ接点同士が実際に衝突している事が挙げられます。

例えば2つのビリヤードの球を衝突させた場合を考えてください。硬質な非弾性素材 は、動きの運動エネルギを吸収しません。ビリヤードの球を衝突させるとそれに反発 する動作が発生し、時間の経過と摩擦に伴いエネルギが放散します。硬質金属のス イッチ接点も同じような反応を示します。また、スイッチ接点は完全な平滑ではあり ません。接点同士が接触する際、接点表面の凹凸や不純物によって電気接続が途切れ る現象が起こります。この結果、スイッチのバウンスが生じます。

スイッチのバウンスを補正しないで生じる結果は、ごく軽微なものから深刻なものま で様々です。例えばテレビのチャンネルを変える時に、次のチャンネルに進むつもり が2つ、3つ先のチャンネルまで進んでしまう事も考えられます。このような状況が 起こらないよう対策をとる必要があります。

スイッチのバウンス問題は最初期のコンピュータ以前から存在していました。古典的 な対処法にはRC回路を使う、テーブルシフトレジスタをリセットする等のフィル タ処理があります。これらの方法は今でも効果的ですが材料、取り付け、基板面積等 の点でコストがかさみます。

3-5: スイッチのデバウンス

スイッチのデバウンスとして最も簡単なのは、信号が安定するまでスイッチをサンプ リングするか、バウンスが検出されなくなるまで信号のサンプリングを継続する方法 です。サンプリングをどれだけ継続すれば良いかは、詳細な検討が必要です。通常は 5 msもあれば十分で、ユーザが気付く事はありません。

PICkit少ピン開発ボードのスイッチはそれほど大きなバウンスはありませんが、シス

テムで使う全スイッチについてデバウンス処理を実行すべきです。

3.7.2 ハードウェアの動作

スイッチを押すとDS1が点灯します。スイッチを離すと消灯します。

+V

R1

R2

Filtered Switch Output SW

C1

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

DS41628B_JP - p.64  2015 Microchip Technology Inc.

3.7.3 概要

このレッスンでは、簡単な遅延ルーチンを使ってスイッチピン操作時に表れるノイズ を除去しています。このコードで生成する遅延はわずか5 msですが、ほとんどのノ イズを除去できます。必要な遅延量は使用するスイッチによって異なります。スイッ チによっては、より長い遅延が必要です。

このレッスンでは、Cとアセンブリの両方でプリプロセッサ シンボルの#defineに ついても学びます。ピン位置をコード内に直接記述するのは良いコーディング手法と は言えません。将来変わる可能性のある値はプリプロセッサ シンボルで定義するよう にします。別のPIC MCUを使ってこのレッスンを実行する場合、全てのピンが変わっ てしまう事もあります。ピン位置をコードに直接記述している場合、その部分を全て 調べて変更しなくてはいけません。

3-28:

こうしておけば、この1行を変更するだけで全体に反映されます。

プリプロセッサは、「LED」という識別子を検出すると全て「LATC, 0」に置き換えます。

これはコードのアセンブル/コンパイル処理(プロセス)の前に実行されるため、プ リプロセッサと呼ばれます。

3.7.4 新しく学ぶレジスタ

なし

3.7.5 新しく学ぶ命令

なし

3.7.6 アセンブリ

3.7.6.1 エンハンスト ミッドレンジ 例3-29:

これまでのレッスンとの大きな違いは1つだけです。それは、プログラムでスイッチ の状態をチェックする際、ラッチではなくポートを読み出しているという点です。

PORTAでなく LATAとするとスイッチの状態を検出できません。前述の通り、読み

出しは必ずポートから、書き込みは必ずラッチへ実行します。LATA レジスタに対し

てRead-Modify-Write を実行すると、PORTA のラッチ出力値を読み出して書き戻し

ます。

3.7.7 PIC18 なし

3.7.8 C言語

新しく学ぶ内容はありません。

#define SWITCH PORTA, 2 ;pin where SW1 is connected..NOTE: always READ from the PORT and WRITE to the LATCH

#define LED LATC, 0 ;DS1

bsf LATC, 0 ;turn on the LED

bsf LED ;turn on the LED

MainLoop:

banksel PORTA ;get into Bank0

btfsc SWITCH ;defined above....notice how the PORT is being read and not the LATCH bra LedOff ;switch is not pressed - turn OFF the LED

bra Debounce ;switch is held down, pin needs to be debounced

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