PIC16F886のLED点滅プログラムの改修

日々雑記
PDPhotos / Pixabay
この記事は約4分で読めます。

デアゴファルコン号の電飾にと作製したプログラムを手直ししました。

前回の記事では、PICが扱える電流の総量を上回ってしまい、誤動作が頻発していましたが1個あたりの消費電流を抑える事で12個のLEDの点滅を制御することができました。

すぐに忘れてしまいそうなので、メモっておきます。

積み残していた課題

ここに行き着くまでに、かなり時間を費やしてしまったため、いくつか課題を残したままでした。

  1. 点滅の周期がおかしい(1サイクル100msec(0.1sec)になっていない)
  2. PORTBに接続を試みるも、制御できなくてPORTCを使用した

動きはしたものの、この2点が引っ掛かってましたが、Webの記事を読み漁って無事解決できました。

ディレイ関数を正確に使うための方法

ドアの点滅は2秒で20パターン出現したため、1サイクル約0.1秒と考えたのですが、実際はもっと誤差がありそうでした。

前回のコーディング

前回は、周波数を125MHzで指定して。。

#define _XTAL_FREQ 125000000

その後

__delay_ms(3);

と記載してましたが、これら2つのパラメタがうまく連動せず仕組みがよくわからないままでした。

この2つのパラメタを変えてみても、うまく点滅したりダンマったり。。

OSCCONレジスタに内部発振器の周波数を設定

不安定な原因は、内部発振を用いる時は設定必須の様ですが、これを指定していませんでした。

以下の設定を追加しました。

    OSCCON = 0b01110000; // 内部発振 8MHz使用に設定

これで、__delay_ms()と__delay_us()が制御可能になりました。

こちらのサイト様の記事を参考にさせて頂きました。




内蔵発振器を使うときはOSCCONの設定を忘れずに - 明日から本気出す( ´・ω・`)

1msec待ち関数を自作

ヘッダファイル pic.hを見ると、_delay()と__delay_ms()、__delay_us()の関係は次の様になっています。

extern __nonreentrant void _delay(unsigned long);
// NOTE: To use the macros below, YOU must have previously defined _XTAL_FREQ
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))

__delay_ms()、__delay_us()はマクロのため、_delay()に変数は指定できないので、__delay_ms()を使用して指定したmsecだけ待ちを発生させる関数を自作して、これを呼び出すことで正確に遅延制御ができるようになりました。

// 1msec遅延関数

void wait_msec(unsigned int n)
{
    while(n)
    {
        __delay_ms(1);    // wait 1msec
        n--;
    }
}

こちらの記事を参考にさせて頂きました。

まとめ

遅延制御に関連した設定のまとめです。

#define _XTAL_FREQ 8000000    //  Clock 8MHz

// 1msec遅延関数

void wait_msec(unsigned int n)
{
    while(n)
    {
        __delay_ms(1);    // wait 1msec
        n--;
    }
}


main()

{
    OSCCON = 0b01110000; // 内部発振 8MHz使用に設定 
    
    unsigned int waittime=100; //遅延時間(msec)
    
while(1) {
    RA0=1;
    wait_msec(waittime);
    RA0=0;
    wait_msec(waittime);
  }

}

PORT Bを入出力ポートとして使うための設定

こちらは、単純なモレでした。

PORT Bの用途はANSELHレジスタで明示が必要

次の1行を追加してPORTBが使用可能になりました。

ANSELH = 0b00000000;

こちらのサイト様を参考にさせて頂きました。

RB6/7を入出力ポートとして使う方法

順調に進んできたと思いきや、RB6が発光しません。

CONFIGレジスタのFOSCの指定は必須の様です。設定をINTRC_CLKOUTからINTRC_NOCLKOUTに変更して無事にRA~RC各8個、24個のLEDを制御できる事が確認できました。

#pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)

コメント

タイトルとURLをコピーしました