PIC32でタクトスイッチと連動したLチカをやってみる

Flashing LED by pushing a switch on PIC32
 
前回の記事で単純なLチカを確認できたら、外部発振器の設定をしてみましょう。ハードウェアの設定はpragmaで行います。8MHz水晶発振子で40MHzのクロックを生成させるには次のようにします。PIC32MXシリーズではシステムクロックは40~120MHzの範囲でないといけないため、入力分数を1/4にして20MHzで動作させるということはできません。
pll.c
#include <p32xxxx.h>

#pragma config FNOSC = PRIPLL // 発信源 = 主外部発振器
#pragma config POSCMOD = XT // 主発振の方法 = 外部高精度発振器を使う
#pragma config FPLLIDIV = DIV_2 // PLL入力分数 = x1/2
#pragma config FPLLMUL = MUL_20 // PLL逓倍比 = x20
#pragma config FPLLODIV = DIV_2 // PLL出力分数 = x1/2
// 8(主発振の周波数)/2(入力分数)*20(逓倍比)/2(出力分数)=40
こちらは4MHz発振子を使った場合の設定例です。
pll4.c
#pragma config FPLLIDIV = DIV_2 // PLL入力分割(1/2)
#pragma config FPLLMUL = MUL_20 // PLL倍率(x20)
#pragma config FPLLODIV = DIV_1 // PLL出力分割(1/1)
// 8/2*20/1=20
続いて配線です。ブレッドボードにタクトスイッチと1kΩ抵抗を追加し、RB1ピンにつなぎます。
今回のプログラミングで注意しないといけないのは、標準の入力はアナログモードのため、RB1ピンを入力モードにしただけだとでは正しい結果を得られない点です。つまり、オン・オフの判定をしたいのであれば、対象のピンをデジタルモードに明示的に指定する必要があります。以上を踏まえてコードを書いてみましょう。
main.c
#include <p32xxxx.h>

#pragma config FNOSC = PRIPLL // 発信源 = 主外部発振器
#pragma config POSCMOD = XT // 主発振の方法 = 外部高精度発振器を使う
#pragma config FPLLIDIV = DIV_2 // PLL入力分数 = x1/2
#pragma config FPLLMUL = MUL_20 // PLL逓倍比 = x20
#pragma config FPLLODIV = DIV_2 // PLL出力分数 = x1/2

int main(int argc, char** argv) {
    // B0ピンを出力にする
    TRISBbits.TRISB0 = 0;
    
    // B1ピンのアナログを無効にする(つまり、B1ピンがデジタルモードになる)
    ANSELBbits.ANSB1 = 0;
    
    // B1ピンを入力にする
    TRISBbits.TRISB1 = 1;
      
    while(1){
        // スイッチが入ると電気がGNDに流れてRB1が0になる
        // つまりRB1が0のときRB0を1にすることで、スイッチを押すとLEDが点く
        PORTBbits.RB0 = ~PORTBbits.RB1;
    }
    
    return (EXIT_SUCCESS);
}
しかしながら、ピンの入出力を正しく設定したにもかかわらず、なおも正しく動作しないと思います。

原因は早すぎるクロック数にあります。PORTレジスタは入力も出力も受け付けることができる反面、検出までにわずかな時間がかかるため、クロックに処理が追いついていないのです。

この問題に対処するにはPORTレジスタではなく、読み込み専用のLATレジスタを使います。以下のようにLATレジスタに置き換えてみましょう。
lat.c
LATBbits.LATB0 = ~PORTBbits.RB1;
//PORTBbits.RB0 = ~PORTBbits.RB1; クロック数が高い場合、入力の受付も兼ねたこのレジスタでは正しく対応できない
これでスイッチの入力に反応して、LEDが点灯するようになります。


入門編のため、この記事ではループを使ってGPIOを操作しましたが、ちゃんとしたプログラムでは、ループではなく割り込み処理で制御しましょう。割り込み処理を使ったプログラミングはこちらをご覧ください。
2018/09/23