以前に購入したまま、ずーっと放置していた 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>__CONFIGCMCONANSELAN0~AN3 のアナログ-デジタル変換がオンになっています。今回の実装は入出力ともにオン/オフのデジタル回路なので、全てのチャンネルのアナログ-デジタル変換をオフに設定します。TRISIOGP0~GP5 について、出力(0)として使うのか、入力(1)として使うのか設定します。GPIOnTRISIO で入力に指定したポートから、ポートの状態を取得します。また、出力に指定したポートに、ポートの状態を設定します。これらのマクロは、デバイスのレジスタに紐付けられていて、状態は即座に取得または反映されます。
最初、何も考えずに、スイッチが押された時に入力端子に電圧がかかるようにしていたところ(回路図左上)、何か挙動がおかしいことになりました。スイッチを押していないのに、関係のない LED まで点灯してしまう(よく観察すると非常に短い周期で点滅しているようにも見える)上に、スイッチを触らずに抵抗の足に触れたりするだけで、LED が消えたり点いたりという現象にでくわしました。デジタル回路のくせに(?)変な挙動をするなぁ…ということで、最初はデジタル入出力の設定忘れなど、プログラムソースのバグまで疑ってしまったのですが、結局、回路図左下のように回路を変更し、スイッチが押されると入力が GND に落ちるようにすることで、期待した通りに動作するようになりました(´д`;)
つまるところ、入力がない時に、端子を宙に浮かせてしまっていたのがマズかったようで、デジタル回路では(でも?)、入力は High または Low に明示的に結線しておかないと、期待した動作をしてくれませんよ、ということらしい。 …知らんがな(´・ω・`)