さて、7 セグメント LED による表示ができるようになったところで、以前、実験した A/D 変換を組み合わせてみたいと思います。これによって、A/D 変換機能でセンサの値を読み込んで、その出力を 7 セグメント LED に数値表示できるようになるはずです。
前回作った 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 入力ポートにはセンサ類を接続した方が面白いのですが、手持ちがなかったので可変抵抗を接続しました。これによって、ポートへの電圧を VSS から VDD まで自由に変化させることができるので、それに応じて 7 セグメント LED に表示される値が変化するのが観察できます。A/D 変換の10 ビット分のデータを全て表示しているので、可変抵抗をグリグリ回すと、000 から 3FF までぎゅいんぎゅいん値が変化します。もっと値がフラフラするかと思ったのですが、けっこういい感じで動いています。ここまでプロタイプが作れると、後は応用しだいでいろいろなギミックが作れそうですね。
寄せられたコメント (全 1 件中、最新 5 件まで表示しています)
突っ込んだつもりはなかったのですが・・・そもそもは試しに図面通りの回路で
819にビルドして成功したのですが何が(ハードがどこかおかしいとは思いますが)
期待通りにならなかったのでVDDの件は書き間違いと思っていましたが初心者なもの
で7セグが回路的にはカソードと思いはしていましたがこの回路でアノードが可能な
のかとか色々考えてしまったもので大変失礼とは思いましたがコメントさせていただき
ました。いくらハードを見つめても間違を探せれない電圧をあたっても正解はわかり
ませんがRA0位置でボリュームを回転させると0~5Vになります。
LEDが壊れたかTRが壊れてているのか(;´д`)トホホです。
気長にやってみます。
アッセンブラはMPLABIEv8.7・HI-TECHv9.8でWin10
でPICSTARTplur互換機です。ビルドは一回で簡単にできました。