PIC ことはじめ ~ 簡単な I/O

Posted by
ぴろり
Posted at
2011/10/27 21:50
Trackbacks
関連記事 (0)
Post Comment
コメントできます
Category
電子工作 カテゴリ

 以前に購入したまま、ずーっと放置していた PIC を触り始めました。ネット上で見つかる PIC の解説ページでは、プログラムにアセンブラを用いたものが多いのですが、アセンブラも電子回路もどちらも素人なので、経験のある C 言語を用いてプログラミングすることにします。どちらも慣れない間は、バグってしまった時に、その原因がプログラムなのか、電子回路なのか判らないですからね... C 言語によるプログラミングでは、生成されるバイナリやメモリの利用効率はアセンブラに多少劣りますが、そのあたりを気にするのは、まぁ、もうちょっと慣れてからでもいいかなと。実際のところ手をつけてみると、プログラム作成はすんなりいったものの、電子回路の実装でハマってしまいましたし orz

このエントリーをはてなブックマークに追加  

概要

  • PIC12F675 を用いた簡単な I/O を実装する。
  • PIC の入力(GP2, GP3)に接続された 2 つのスイッチのオンオフに応じて、PIC の出力(GP0, GP1, GP4, GP5)に接続された 4 つの LED の点灯消灯を制御する。

ソースコード

#include <htc.h>

__CONFIG (FOSC_INTRCIO 	// 内蔵オシレータを使用
		& WDTE_OFF 		// WDT 無効
		& PWRTE_OFF 	// PWRT 無効
		& MCLRE_OFF		// MCLR 使用しない
		& BOREN_OFF		// BOD 無効
		& CP_OFF		// Program Memory code protection 無効
		& CPD_OFF		// Data memory code protection 無効
);

void main () {
	GPIO = 0;

	// コンパレータは使用しない
	CMCON = 0b00000111;
	// A/Dは使用しない
	ANSEL = 0;

	// ポートの入出力方向を設定
	// GP0	OUT - LED1
	// GP1	OUT - LED2
	// GP2	IN - SW1
	// GP3	IN - SW2
	// GP4	OUT - LED3
	// GP5	OUT - LED4
	TRISIO = 0b00001100;

	while (1) {
		// SW1, SW2 の押下状態を取得
		int sw1 = GPIO2;
		int sw2 = GPIO3;
		// スイッチの押下状態に応じて LED を点灯する
		if (!sw1 && !sw2) GPIO0 = 1, GPIO1 = 0, GPIO4 = 0, GPIO5 = 0;
		if (!sw1 &&  sw2) GPIO0 = 0, GPIO1 = 1, GPIO4 = 0, GPIO5 = 0;
		if ( sw1 && !sw2) GPIO0 = 0, GPIO1 = 0, GPIO4 = 1, GPIO5 = 0;
		if ( sw1 &&  sw2) GPIO0 = 0, GPIO1 = 0, GPIO4 = 0, GPIO5 = 1;
	}
}
#include <htc.h>
 コンパイラのインクルード ヘッダ ファイルの格納されたディレクトリを見てみると、デバイス毎にそれぞれヘッダ ファイルが用意されていますが、それらを直接インクルードせずに、このヘッダ ファイルをインクルードします。そうすることで、コンパイラに渡されたプリプロセッサ変数から、適切なメモリ モデルやデバイスに応じたヘッダ ファイルが選択して読み込まれます*1。ヘッダ ファイルでは、各種レジスタ等にアクセスする際に、レジスタのアドレス値ではなく、シンボル名でアクセスできるようにするなどの手続きが行われます。まぁ、おまじない的に入れておけば OK。
__CONFIG
 プログラムが実行される前に行われるデバイスのコンフィグレーションを記述します。使用するオシレータの種類や各種タイマーのスイッチなどがあります。デバイス毎に定数が異なる模様。
CMCON
 入力ポートからの値を比較するコンパレータを使用しないよう設定。ポートが期待した通りの入出力を行っていない場合、コンパレータが効いてしるのかもしれません。
ANSEL
 PIC12F675 は、初期状態で AN0AN3 のアナログ-デジタル変換がオンになっています。今回の実装は入出力ともにオン/オフのデジタル回路なので、全てのチャンネルのアナログ-デジタル変換をオフに設定します。
TRISIO
 各ポートの入出力の方向を設定します。下位ビットから GP0GP5 について、出力(0)として使うのか、入力(1)として使うのか設定します。
GPIOn
 TRISIO で入力に指定したポートから、ポートの状態を取得します。また、出力に指定したポートに、ポートの状態を設定します。これらのマクロは、デバイスのレジスタに紐付けられていて、状態は即座に取得または反映されます。

回路図

回路図

 最初、何も考えずに、スイッチが押された時に入力端子に電圧がかかるようにしていたところ(回路図左上)、何か挙動がおかしいことになりました。スイッチを押していないのに、関係のない LED まで点灯してしまう(よく観察すると非常に短い周期で点滅しているようにも見える)上に、スイッチを触らずに抵抗の足に触れたりするだけで、LED が消えたり点いたりという現象にでくわしました。デジタル回路のくせに(?)変な挙動をするなぁ…ということで、最初はデジタル入出力の設定忘れなど、プログラムソースのバグまで疑ってしまったのですが、結局、回路図左下のように回路を変更し、スイッチが押されると入力が GND に落ちるようにすることで、期待した通りに動作するようになりました(´д`;)
 つまるところ、入力がない時に、端子を宙に浮かせてしまっていたのがマズかったようで、デジタル回路では(でも?)、入力は High または Low に明示的に結線しておかないと、期待した動作をしてくれませんよ、ということらしい。 …知らんがな(´・ω・`)

まとめのようなもの

  • PIC を用いた簡単なデジタル I/O のプログラムと回路を作成した。
  • プログラムの作成、コンパイル、PIC への書き込みを行った。
  • 電子回路を実装し、作成したプログラムの通りに動作することを確認した。
  • Low 入力は明示的に GND に落とすなどする。宙に浮かすとか手を抜く(?)とダメ。
  • PIC12F675 ってなかなかステキやん
    • 内部クロックを持っているので、精度を要求しなければ、別に外部クロック回路を用意しなくてもよい。
    • A/D が 4ch もある。
    • デジタル I/O が 6ch もある。
    • それでいて 8 pin の DIP なので小型機器にも組み込めるので、ガジェット作成に最適。
このエントリーをはてなブックマークに追加  

  1. *1 デバイス用のヘッダ ファイルを直接インクルードしてしまうと、コンパイル時に warning が表示されます

この記事を読んだ人はこんな記事も読んでいます記事リコメンデーションについて

カバー画像:PIC ことはじめ ~ LED フラッシャー

関連記事/トラックバック

関連記事/トラックバックはまだありません

この記事にトラックバックを送るには?

コメントを投稿する

 
 (必須, 匿名可, 公開, トリップが使えます)
 (必須, 匿名可, 非公開, Gravatar に対応しています)
 (必須)
スパム コメント防止のため「投稿確認」欄に ランダムな数字 CAPTCHAについて を入力してから送信してください。お手数ですがご協力のほど宜しくお願いいたします。