この記事でわかること
・タイマ2割込みを使った1秒周期動作
・2進数カウント処理と、7セグLEDダイナミック表示
・PICマイコンへのスイッチ入力処理方法
PICマイコンによる2進数カウント表示プログラムを紹介します。
これは、8ビットのカウント値を8個のLEDを使って2進数表示すると共に、
7セグメントLEDで16進数表示します。(以下、7セグLEDと記載)
タクトスイッチ(白、赤、黄、青)でカウント値の設定やスタート、ストップを行い、
タイマ割込みを使用して、1秒毎の自動カウントアップ動作ができます。
本記事で使用する新居浜高専PICマイコン学習キットについては下記記事で解説しています。
キットの回路図やプログラムはキットを販売している秋月電子のHPからダウンロードできます。
秋月電子 新居浜高専PICマイコン学習キットVer.3 ACアダプタ付
また、参考書も販売されています。
※本記事はPICマイコン学習方法の一例を紹介するものであり、
ここで紹介するキットやソフトの動作を保証するものではありません。
キット等の購入については自己責任でお願いします。
(不明点等の質問にはお答えできません)
<本ソフトの利用環境と設定について>
本記事におけるMPLABの開発環境は以下の通りです。
・MPLAB X IDE v.15
・XC8 v2.46
・Device Family Pack PIC16F1xxxx_DFP(1.24.387)
※ダウンロードしたプロジェクトファイル(NNCTkit_v3.X)は、
そのままビルドするとエラーになるため、以下の変更を実施しました。
・helpstr.h 9行目
変更前:const __section(“title”) unsigned char title[224]={
変更後:const __section(“help_title“) unsigned char help_title[224]={
セクション名がtitleだとエラーになるので、別の名前にします。
ここではhelp_titleにしましたが、何でも良いです。
この時、配列名はtitleのままでも問題ありませんが、
他のデータ同様、配列名をセクション名と同じにする場合は、
この配列を使用しているソースファイルの方も直します。
・monitor.c 2093行目
変更前:TX1REG = title[i];
変更後:TX1REG = help_title[i];
MPLABの使い方については下記で解説しています。
2進数カウント表示回路
タクトスイッチ(SW1~SW4)がデジタル入力(RB0~RB3)に、
デジタル出力(RC0~RC7)は、7セグLEDの各セグメント及び、8ビットLEDに接続されています。
どのLEDを点灯させるかは、デジタル出力(RA3~RA5)が
デコーダ(IC2)に入力され、Y0~Y6のうちどれか1つだけL出力することで、
PNPトランジスタがONし、LEDに電源供給されることで指定されます。
この回路では、各桁の7セグLEDや8ビットLEDに違う値を同時に点灯することはできませんが、
各LEDの点灯を高速で切り替えることで、人の目には同時点灯に見えます。
これをダイナミック点灯制御と呼びます。
本回路におけるベース抵抗などの回路定数の設定や、ダイナミック点灯制御については下記記事で解説しています。
スイッチ入力は、10kΩでプルアップすることで、
スイッチOFFでHレベル、ONでLレベルが入力されます。
プルアップ抵抗の決め方については下記記事で解説しています。
PICマイコンの初期設定
プログラムでは、PICマイコンの初期設定として、
コンフィグレーション設定(※1)によるクロックの動作モード設定を行います。
※1:クロックなどの動作環境設定
プログラムコードの詳細は、ソースファイル(nnct_kit_v3.c)を参照下さい。
コンフィグレーション設定は以下の通りです。
#pragma config FEXTOSC = HS
外部発振器モード選択:HS(水晶振動子 4MHz以上)
#pragma config RSTOSC = EXT4X
発振器の動作モード:PLL(※2)の4逓倍回路を使用
※2:Phase Locked Loop(位相同期ループ):クロック周波数を増加させる回路
PIC16F18857ではPLLにより、外部からのクロック信号の周波数を4倍に増やすことができ、
本キットでは、8MHzの水晶振動子から32MHzのシステムクロック周波数Foscを生成してます。
コンフィグレーション設定については、下記記事で解説しています。
タイマ2割込み処理
この学習キットのソフト(ソースファイル(nnct_kit_v3.c))では、
タイマ2割込みを使うことで、タイマーや時計などの正確な時間処理を行っています。
タイマ2は、タイマ2レジスタ(T2TMR)の値をカウントアップして、
T2PR(タイマ2周期レジスタ)の値に到達したらゼロに戻り、タイマ2割込みが発生します。
タイマ2の設定は、初期設定関数SetConfigで行っています。
このプログラムでは、タイマ2のカウント速度を1MHz(1us)、
T2PRを199にセットしているので、199+1=200カウント目に割込みが発生し、
割込み処理は1us×200=200us毎に行われます。
タイマ2割込みで行う処理内容は割込み処理関数 isrで定義しています。
このisr関数では、タイマ1割込み処理も定義されており、
ブザー音の階調(周波数)制御に用いられています。
ブザー音制御の詳細については、下記記事で解説しています。
<グローバル変数の定義>
タイマ2割込み処理では、次の2つのグローバル変数(※4)を制御しています。
※4:関数の外で宣言した変数で、同じソースファイル内の関数で共用できる。
グローバル変数については下記記事で解説してます。
・タイマ2割込回数カウンタ(t2_icnt)
割込み発生(200us)毎にカウントアップする
・1秒経過フラグ(sec_flag)
t2_icntの値が設定した定数TIMECONSTを超えたら、1にセットする
この時、t2_icntはゼロにクリアされる
TIMECONSTはソースファイル(nnct_kit_v3.c)の初めにある
define命令によって、固定値(4999)に定義されています。
#define TIMECONST 4999
これによって、200us×5000=1s経過後にsec_flagが1になることで、
1秒間の計測に利用されています。
・7セグ表示用データ(segdata[ ])
この後で解説する2進数カウント表示プログラムで使用します。
ポートC(RC7~RC0)に出力するための配列データで、これもグローバル変数です。
segdata[0]からsegdata[15]は、16進数表記の0~Fに対応しています。
例えば、segdata[0]は1100 0000に定義されているので、RC0~RC5がLレベルとなり、
セグメントA,B,C,D,E,Fが点灯し、7セグLEDで「0」が表示されます。
2進数カウント表示プログラム
カウント値を8ビットLED(D4~D11)に2進数で、7セグLED(D101)に16進数で表示します。
4つのタクトスイッチ(SW1~4)により、SW1とSW2でカウントアップ/ダウン、
SW3でクリア、SW4で1秒毎の自動カウントアップのスタート/ストップ動作を行います。
16進数でFF (15) になったら、ゼロに戻ります。
スイッチ入力は1回押すとカウントが1だけ変化するようにするため、
スイッチ入力フラグ(key_st)を用いて、全てのスイッチがOFFになるまで、
次回のスイッチ入力を受け付けないようにしています。
(スイッチ押したままにしてもカウントが増加しない)
自動カウントアップについては、1秒経過フラグ(sec_flag)を用いて、
1秒間隔でカウントアップ処理を行います。
ダイナミック点灯制御については、
ソースファイル内で定義されたwait関数により、
約2us×(引数の値) だけ待機時間を作ることで各LEDの点灯時間を確保します。
2進数カウンタの動作波形
8ビットLEDと、7セグLEDの動作波形を示します。
RC0出力がLの時、8ビットLEDのD4、7セグLEDのセグメントaが点灯します。
この波形では、D4消灯、7セグLEDはセグメントaが1桁目、2桁目共に点灯となっています。
LEDが点灯するL期間は226usとなっています。
これは、wait関数による待機処理で行っているため、正確な時間制御でないことから、
各L期間には、ばらつきがありますが、各LEDの明るさに差は感じられません。
RC0信号で一瞬だけHレベルになっている部分があるのは、
LED点灯を切替える処理の最初にある「LATC = 0xFF」によって、
ポートC出力を全てH(1)にすることでLEDを全消灯しているからです。