以前に購入したまま、ずーっと放置していた PIC を触り始めました。ネット上で見つかる PIC の解説ページでは、プログラムにアセンブラを用いたものが多いのですが、アセンブラも電子回路もどちらも素人なので、経験のある C 言語を用いてプログラミングすることにします。どちらも慣れない間は、バグってしまった時に、その原因がプログラムなのか、電子回路なのか判らないですからね... C 言語によるプログラミングでは、生成されるバイナリやメモリの利用効率はアセンブラに多少劣りますが、そのあたりを気にするのは、まぁ、もうちょっと慣れてからでもいいかなと。実際のところ手をつけてみると、プログラム作成はすんなりいったものの、電子回路の実装でハマってしまいましたし orz
#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>
__CONFIG
CMCON
ANSEL
AN0
~AN3
のアナログ-デジタル変換がオンになっています。今回の実装は入出力ともにオン/オフのデジタル回路なので、全てのチャンネルのアナログ-デジタル変換をオフに設定します。TRISIO
GP0
~GP5
について、出力(0)として使うのか、入力(1)として使うのか設定します。GPIOn
TRISIO
で入力に指定したポートから、ポートの状態を取得します。また、出力に指定したポートに、ポートの状態を設定します。これらのマクロは、デバイスのレジスタに紐付けられていて、状態は即座に取得または反映されます。
最初、何も考えずに、スイッチが押された時に入力端子に電圧がかかるようにしていたところ(回路図左上)、何か挙動がおかしいことになりました。スイッチを押していないのに、関係のない LED まで点灯してしまう(よく観察すると非常に短い周期で点滅しているようにも見える)上に、スイッチを触らずに抵抗の足に触れたりするだけで、LED が消えたり点いたりという現象にでくわしました。デジタル回路のくせに(?)変な挙動をするなぁ…ということで、最初はデジタル入出力の設定忘れなど、プログラムソースのバグまで疑ってしまったのですが、結局、回路図左下のように回路を変更し、スイッチが押されると入力が GND に落ちるようにすることで、期待した通りに動作するようになりました(´д`;)
つまるところ、入力がない時に、端子を宙に浮かせてしまっていたのがマズかったようで、デジタル回路では(でも?)、入力は High または Low に明示的に結線しておかないと、期待した動作をしてくれませんよ、ということらしい。 …知らんがな(´・ω・`)