【PICマイコン入門9】BCD変換プログラムの作り方  | アナデジ太郎の回路設計

【PICマイコン入門9】BCD変換プログラムの作り方 

BCD変換 ソフト設計

この記事でわかること

・BCD変換プログラムの仕組み
・PIC16F1ファミリのADC機能の使い方
・ダイナミック点灯による7セグLED&バーグラフ表示

本記事では、PICマイコンのADC入力機能を用いて、
可変抵抗の電圧をAD変換した16進数の値をBCD(※1)変換し、
7セグメントLED(※2)で10進数表示させるプログラムについて解説します。

※1:Binary Coded Decimal(2進化10進数)
   4桁の2進数を使って10進数の0~9を表現する方法

※2:以下、7セグLEDと記す

本記事で使用する新居浜高専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の使い方については下記で解説しています。

AD変換値を7セグLEDとバーグラフに表示する回路

キットの回路は下図のような構成となっています。

7セグLED&8ビットLED回路

PICマイコンのRA0ピンをアナログ入力に設定し、
可変抵抗VR1により、入力電圧を0~5Vまで変化させます。

PICマイコンのAD変換機能により、アナログ入力された0~5Vは
10bitのデジタル値に変換されます。
(2進数 11111 11111=16進数0x3FF)

このAD変換値を9段階に区分けして、
8ビットLED(D4~D11)でバーグラフ表示させます。
(入力電圧が大きくなるに従い、LEDの点灯数が増える)

また、この16進数をBCD変換により、4桁の10進数にして7セグLEDに表示します。
(16進数表示0x3FF=10進数表示1023)

AD変換によるLED点灯状態

デジタル出力(RC0~RC7)は、7セグLEDの各セグメント及び、
8ビットLEDに接続されています。

どのLEDを点灯させるかは、デジタル出力(RA3~RA5)が
デコーダ(IC2)に入力され、Y0~Y6のうちどれか1つだけL出力し、
PNPトランジスタ(TR6~TR12)がONすることで、LEDに電源が供給されます。
(TR10、TR11は他のLED制御用のため、回路図には未記載)

デコーダ真理値表

この回路では、各LEDを同時に点灯させることはできませんが、
各LEDの点灯を高速で切り替えることで、人の目には同時点灯に見えます。
これをダイナミック点灯制御と呼びます。

ダイナミック点灯

本回路におけるベース抵抗などの回路定数の設定や、
7セグLEDのダイナミック点灯制御については下記記事で解説しています。



PICマイコンの初期設定

プログラムでは、PICマイコンの初期設定として、
コンフィグレーション設定(※3)によるクロックの動作モード設定、
初期設定関数SetConfig( )でAD変換機能の設定を行います。
 ※3:クロックなどの動作環境設定

プログラムコードの詳細は、ソースファイル(nnct_kit_v3.c)を参照下さい。

コンフィグレーション設定

#pragma config FEXTOSC = HS
 外部発振器モード選択:HS(水晶振動子 4MHz以上)

#pragma config RSTOSC = EXT4X
 発振器の動作モード:PLL(※4)の4逓倍回路を使用
 ※4:Phase Locked Loop(位相同期ループ):クロック周波数を増加させる回路

PIC16F18857ではPLLにより、外部からのクロック信号の周波数を4倍に増やすことができ、
本キットでは、8MHzの水晶振動子から32MHzのシステムクロック周波数Foscを生成してます。

コンフィグレーション設定については、下記記事で解説しています。

AD変換機能の設定

初期設定関数SetConfig( )で、以下のレジスタ設定を行います。

初期設定関数SetConfig

ANSELA(ポートAアナログ選択)レジスタ
 ポートA(RA0~RA7)をアナログ入力にするか指定します。
 レジスタ値0x03(0000 0011)により、RA0,RA1をアナログ入力に設定します。
 (但し、本プログラムではRA1は未使用)

ANSELAレジスタ

ADCON0(ADC制御0)レジスタ
 このレジスタの各ビットには、
 AD変換の各種設定が割付けられています。 

ADCON0レジスタ

  ADON(ADC有効化)ビット=1(ADC有効)
  ADCS(ADCクロック選択)ビット=0(ADCLKを使用)
  ADFRM0(ADC結果形式)ビット=1(右寄せモード※5)

 ※5:AD変換値は10bitデータ(0~1023)ですが、
   これを上下各8bitのAD変換結果レジスタ(ADRESH、ADRESL)にセットするときのモードを指定します。

AD変換結果のセット方法

  ADFRM0 = 1の場合、右寄せモードとなり、
  ADRESHは、10bit変換結果の上位2bit、ADRESLは下位8ビットを格納します。

ADCLK(ADCクロック選択)レジスタ
  AD変換を行うクロックの設定を行います。

ADCLKレジスタ

  本プログラムでは最も低速となるシステム周波数Foscの1/128にしています。
   0x3F(63)=Fosc/128=32MHz/128 =250kHz
  
  この設定だと、AD変換1 ビットあたりの処理時間TADは、
   TAD=1/250kHz=4us
   10ビットデータの変換に要する時間はデータシートより11.5×TADとあるので、
   4us×11.5=46usとなります。

ADREF(ADCリファレンス選択)レジスタ
 このレジスタの各ビット(ADPREF、ADNREF)で、
 AD変換の基準電圧を入力するピンを指定します。 

ADREFレジスタ

    ADPREF(VREF+入力ピン選択)ビット= 0x00(VDDピン)
    ADNREF(VREF-入力ピン選択)ビット= 0(VSSピン)

 
 基準電圧を電源ピンの5Vと、GNDピンにすることで、
 アナログ電圧0~5Vを10bitのデジタル値(0~1023)に変換します。

AD変換特性

ADPCH(ADC チャンネル選択)レジスタ
 AD変換入力ピンを指定します。
  0x00にすることで、RA0(ANA0)ピンとなります。



AD変換処理とダイナミック点灯制御

関数 ADconverter( )はAD変換処理と、
7セグLED及び8ビットLEDの点灯制御を行います。

AD変換値は10ビットデータですが、
上下各8ビットのAD変換結果レジスタ (ADRESH、ADRESL) から読出します。

初期設定関数SetConfig( ) により、ADFRM0 = 1 (右寄せモード) に設定されているので、
上位2ビットがADRESH、下位8ビットがADRESLに格納されています。

このため、ADRESHを8ビット左シフトしてから、
16ビット変数であるad_resultにセットし、次にADRESLを加えています。

10ビットAD変換データのセット

このAD変換値ad_resultの大きさに応じて、
8ビットLED(D4~D11)の点灯数を制御しています。

そして、BCD変換関数 bin16_to_bcd( )により、
ad_resultを10進数に変換した値をbcd[3]~bcd[0]にセットし、
4桁の7セグLEDに表示させます。

各7セグLEDの点灯切替の間にforループによる待機処理を入れる事により、
点灯期間を設けることで、ダイナミック点灯制御を行っています。

AD変換関数
AD変換関数



BCD変換プログラム

関数 bin16_to_bcd( ) は、16ビットの2進数bin16をBCD変換し、
5桁の10進数にしたものをbcd[0]~bcd[4]に入れます。

BCD変換関数

本プログラムでは以下の処理を行っています。

 ①bin16のMSBの値 (1/0) を変数sにセットする
 ②bin16を1ビット左シフトする
 ③bcd[0]~[4] それぞれについて、1ビット左シフトする
 ④bcd[0]のLSBに変数sの値をセットする
  (①と④で、bin16からbcd[0]に左シフトする)
 ⑤bcd[0]~[3] それぞれについて、MSBが1なら、上位のbcd[ ] のLSBを1にする
  (bcd[ ]間で左シフトする。bcd[4]は最上位桁なので行わない)
 ⑥bcd[0]~[4] それぞれについて、5以上なら3を加える

①~⑥の処理を16回行う(但し、16回目は⑥は行わない)
 (bin16のビットが全てシフトし終わることになる)

このBCD変換処理方法を理解するために、例として、
8ビットの2進数0111 1101(10進数で125)をBCD変換した場合について説明します。

BCD変換処理方法

まず、10進数に変換する8ビットの2進数をbin8にセットします。

8ビットの2進数の最大値は16進数で0xFF、
これを10進数表記すると255と、3桁分必要となるので、
bcd[2]、bcd[1]、bcd[0]を用意し、図の様にbin8の左側に配置します。

①~⑥の処理を行うことで、bin8を1ビット左シフトした時に、
bin8の最上位ビット(MSB)をbcd[0]にセットし、
bcd[ ]間でも1ビット左シフトを行います。

セットした時、各bcd[ ]が5以上なら+3します。
(但し、最終回となる8回目の左シフト時は行わない)

これをbin8のビットを全てシフトし終わるまで8回行います。

その結果、bcd[2]=1、bcd[1]=2、bcd[0]=5となり、
10進数の125に変換されます。



7セグLEDと8ビットLED点灯時の動作波形

デコーダ(IC2)の出力波形を見ると、
7セグLEDの3桁目、2桁目、1桁目、8ビットLEDの順にLとなり、
各LEDが順繰りに点灯していきます。

デコーダによるLED点灯切替制御

L期間については、forループによる待機処理であり、
正確な時間制御をしていないため、
各LEDのL期間は750~950usと多少ばらついていますが、
明るさに差は感じられません。

このデコーダ信号と、ポートC出力(RC0~7)との関係を見てみます。
RC1出力は7セグLEDではセグメントb、8ビットLEDではD5の点灯を制御します。

ダイナミック点灯制御波形

この波形では、7セグ2桁目はb消灯、1桁目はb点灯、
8ビットLED(D5)は点灯しています。

RC1を見ると、LEDの切替時に一瞬Hになっているのは、
全消灯させるために、切替時にポートC出力を一度Hに戻しているからです。

4桁の7セグから8ビットLEDまで順番に約4.4ms周期で点灯を繰り返しており、
LEDはちらつくことなく、7セグ及び8ビットLEDが全て点灯しているように見えます。