PIC ことはじめ ~ A/D 変換 + 7 セグメント LED

Posted by
ぴろり
Posted at
2012/01/23 13:34
Trackbacks
関連記事 (0)
Comments
コメント (1)
Post Comment
コメントできます
Category
電子工作 カテゴリ

 さて、7 セグメント LED による表示ができるようになったところで、以前、実験した A/D 変換を組み合わせてみたいと思います。これによって、A/D 変換機能でセンサの値を読み込んで、その出力を 7 セグメント LED に数値表示できるようになるはずです。

この記事を Delicious に追加する   このエントリーをはてなブックマークに追加  

ソースコード

 前回作った 7 セグメント LED のドライバをほぼそのまま、A/D 変換の処理を追加します。変更された部分のポイントは、A/D 変換処理を開始したら、そのまま変換処理が終わるのを待つのではなく、変換処理が完了したことを割り込みで処理していることです。

#include <htc.h>

__CONFIG (
        FOSC_INTOSCIO   // 内蔵オシレータ
      & WDTE_OFF        // WDT 無効
      & PWRTE_OFF       // PWRT 無効
      & MCLRE_OFF       // MCLR 使用しない
      & BOREN_OFF       // BOD 無効
      & LVP_OFF         // Low-Voltage Programming 使用しない
      & CPD_OFF         // Data memory code protection 無効
      & DEBUG_OFF       // In-Circuit Debugger 使用しない
      & CP_OFF          // Program Memory code protection 無効
);

static int pattern_7seg [] = {
    //abcdefg.
    0b11111100,     // 0
    0b01100000,     // 1
    0b11011010,     // 2
    0b11110010,     // 3
    //abcdefg.
    0b01100110,     // 4
    0b10110110,     // 5
    0b10111110,     // 6
    0b11100100,     // 7
    //abcdefg.
    0b11111110,     // 8
    0b11110110,     // 9
    0b11101110,     // A
    0b00111110,     // B
    //abcdefg.
    0b10011100,     // C
    0b01111010,     // D
    0b10011110,     // E
    0b10001110,     // F
};



static void ResetTimer0 ()
{
    TMR0 = -200;
}

static int timeout;             // Timer0 のタイムアウトをカウントする
static void ResetTimer0_TimeoutCount ()
{
    timeout = -900;
}

static int seg_num = 0;         // 表示する値
static int seg_idx = 1;         // 表示中のセグメント

// メインルーチン
void main ()
{
    // PORTA の入出力設定
    TRISA = 0b00000001;
    ADCON1bits.PCFG = 0b1110;
    // PORTB の入出力設定
    TRISB = 0b00000000;

    // Timer0 の準備
    OSCCONbits.IRCF = 0b111;    // 内蔵クロックを 8MHz に設定
    // OPTION REGISTER
    OPTION_REGbits.T0CS = 0b0;  // Timer0 は CLKO(=Fosc/4) 基準で動作
    OPTION_REGbits.PSA = 0b0;   // プリスケーラを Timer0 にアサイン
    OPTION_REGbits.PS = 0b001;  // プリスケーラ比を 1:4 に設定
    TMR0 = 0;                   // Timer0 を一応クリア
 
    // Timer0 の割り込みを許可
    INTCONbits.TMR0IE = 0b1;    
    // A/D 変換の割り込みを許可
    INTCONbits.PEIE = 0b1;
    PIE1bits.ADIE = 0b1;
    // グローバル割り込み許可
    INTCONbits.GIE = 0b1;

    // メインループ
    ResetTimer0 ();
    ResetTimer0_TimeoutCount ();
    while (1)
    {
        switch (seg_idx)
        {
        case 1:
            RA3 = 0;
            PORTB = pattern_7seg [seg_num & 0xf];
            RA1 = 1;
            break;
        case 2:
            RA1 = 0;
            PORTB = pattern_7seg [(seg_num >> 4) & 0xf];
            RA2 = 1;
            break;
        case 3:
            RA2 = 0;
            PORTB = pattern_7seg [(seg_num >> 8) & 0xf];
            RA3 = 1;
            break;
        }
    }
}

// 割り込みルーチン
static void interrupt isr (void)
{
    // Timer0 による割り込み
    if (INTCONbits.TMR0IF)
    {
        // 表示するセグメントを切り替える
        seg_idx = (seg_idx % 3) + 1;

        // タイムアウトしたので表示する数値を更新
        if (!timeout++)
        {
            // A/D 変換処理を開始
            ADCON0bits.CHS = 0b000;
            ADCON0bits.ADON = 0b1;
            ADCON0bits.GO_nDONE = 0b1;
            // 処理の終了は割り込みで通知

            ResetTimer0_TimeoutCount ();
        }

        INTCONbits.TMR0IF = 0;  // 割り込みフラグをクリアするのはプログラムの仕事
        ResetTimer0 ();         // タイマを再スタート
    }
    // A/D 変換処理が完了
    else if (PIR1bits.ADIF)
    {
        seg_num = ((int) ADRESH << 2) + (int) (ADRESL >> 6);
        PIR1bits.ADIF = 0;      // 割り込みフラグをクリアするのはプログラムの仕事
    }
}
  • A/D 変換処理が完了した際に割り込みが発生するようにします(73~75行目)
  • 一定間隔で、ポート入力を A/D 変換しています(117~120行目) 変換終了は割り込みで通知されるので、そのまま処理を継続しています。
  • A/D 変換が完了したら割り込みが発生します(129~134行目) このタイミングで 7 セグメント LED に表示される数値(seg_num)を更新します。

回路図

回路図

 A/D 入力ポートにはセンサ類を接続した方が面白いのですが、手持ちがなかったので可変抵抗を接続しました。これによって、ポートへの電圧を VSS から VDD まで自由に変化させることができるので、それに応じて 7 セグメント LED に表示される値が変化するのが観察できます。A/D 変換の10 ビット分のデータを全て表示しているので、可変抵抗をグリグリ回すと、000 から 3FF までぎゅいんぎゅいん値が変化します。もっと値がフラフラするかと思ったのですが、けっこういい感じで動いています。ここまでプロタイプが作れると、後は応用しだいでいろいろなギミックが作れそうですね。

この記事を Delicious に追加する   このエントリーをはてなブックマークに追加  


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

カバー画像:PIC ことはじめ ~ 7 セグメント LED を使う

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

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

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

寄せられたコメント (全 1 件中、最新 5 件まで表示しています)

Posted by
加藤 修加藤 修
at
2017/02/10 13:33
ID
O2Av.s/Y
早速の対応ありがとうございます。
突っ込んだつもりはなかったのですが・・・そもそもは試しに図面通りの回路で
819にビルドして成功したのですが何が(ハードがどこかおかしいとは思いますが)
期待通りにならなかったのでVDDの件は書き間違いと思っていましたが初心者なもの
で7セグが回路的にはカソードと思いはしていましたがこの回路でアノードが可能な
のかとか色々考えてしまったもので大変失礼とは思いましたがコメントさせていただき
ました。いくらハードを見つめても間違を探せれない電圧をあたっても正解はわかり
ませんがRA0位置でボリュームを回転させると0~5Vになります。
LEDが壊れたかTRが壊れてているのか(;´д`)トホホです。
気長にやってみます。
アッセンブラはMPLABIEv8.7・HI-TECHv9.8でWin10
でPICSTARTplur互換機です。ビルドは一回で簡単にできました。

コメントを投稿する

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