XC8 BCD変換関数
アッセンブラ版BCD変換ルーチンをXC8に移植
目的は8桁7セグLEDを制御するルーチン群の1つとしてです。
XC8のprintf関数で行えば良いのですが、この関数はメモリを多量に消費します。
そこで、アッセンブラでの制御と同じ関数群を作り、メモリの少ないPICでもXC8でプログラムできる様にするためです。
関数操作方法は、32bit入力で戻し値が5バイトとなるので、アッセンブラ版と同じようなBCD専用広域変数に収納します。
別バージョンでは、上位桁を切り捨てて、32bitで返します。
実際の挙動に関しては、MPLAB XIDEのシミュレータで観察すると、動作確認が出来て面白くてお勧めです。
アッセンブラ版から見える、BCD変換ルーチンの動作概要
以前の考察で記した物と同じで、未だになぜこの方法でBCDに変換できるのか理屈が全く理解できません・・・ (-_-;)
見ての通り、1bitずつ左シフトしながら、4bit単位で補正処理を繰り返します。
ここでは簡略化のため、変換前の16進バイナリ数値を8bitとして進行していきます。
8bitなので8回左シフトします。ちなみに16bit数値の場合は16回、32bit数値の場合は32回左シフトします。
最後の左シフト後は補正処理しません。
変換されたBCDの格納変数はDEC12、DEC34の2バイトとし、ビットは全てクリアしておきます。
1桁4bitが基本となりますので、ここではDECを16bit変数として扱い、
さらに変換後は最大3桁12bit使用しますので、変数DECの上位4bit(bit15-bit12)は表示を省略します。
変換前の16進バイナリ数値はHEX0の1バイトで、例として値はFFHとします。
下記の用に1ビットずつ左へ(MSBへ)シフトします。
破棄 ← DEC34 ← DEC12 ← HEX0 ← ゼロビット
DEC4,3桁 DEC2,1桁 元値16進
変換前の16進バイナリ数値HEX0は左シフトすると、LSBには0がシフトしてくるとします。
16ビットDEC変数はLSBから順に1bitずつ左シフトされてくるが、左シフトする度に5以上の4ビット列(桁)は+3される事に注意
START - (↓DECビット0000H) -- (↓HEXビット FFH)
ビット列 (0000 0000 0000) ← (1111 1111)
1回目 - (↓DECビット0001H) -- (↓HEXビット )
ビット列 (0000 0000 0001) ← (1111 1110) 左シフト後、DEC1桁目は5未満で補正無し
2回目 - (↓DECビット0003H) -- (↓HEXビット )
ビット列 (0000 0000 0011) ← (1111 1100) 左シフト後、DEC1桁目は5未満で補正無し
3回目 - (↓DECビット0007H) -- (↓HEXビット )
ビット列 (0000 0000 0111) ← (1111 1000) 左シフト後、DEC1桁目は5以上で補正必要
3回目 - (↓DECビット000AH) -- (↓HEXビット )
ビット列 (0000 0000 1010) ← (1111 1000) 補正処理実行、DEC1桁目のみに+3補正
4回目 - (↓DECビット0015H) -- (↓HEXビット )
ビット列 (0000 0001 0101) ← (1111 0000) 左シフト後、DEC1桁目は5以上で補正必要
4回目 - (↓DECビット0018H) -- (↓HEXビット )
ビット列 (0000 0001 1000) ← (1111 0000) 補正処理実行、DEC1桁目のみに+3補正
5回目 - (↓DECビット0031H) -- (↓HEXビット )
ビット列 (0000 0011 0001) ← (1110 0000) 左シフト後、DEC1桁目,2桁目はそれぞれ5未満で補正無し
6回目 - (↓DECビット0063H) -- (↓HEXビット )
ビット列 (0000 0110 0011) ← (1100 0000) 左シフト後、DEC1桁目5未満,2桁目は5以上で補正必要
6回目 - (↓DECビット0093H) -- (↓HEXビット )
ビット列 (0000 1001 0011) ← (1100 0000) 補正処理実行、2桁目のみに+3補正
7回目 - (↓DECビット0127H) -- (↓HEXビット )
ビット列 (0001 0010 0111) ← (1000 0000) 左シフト後、DEC2,3桁目は5未満,1桁目は5以上で補正必要
7回目 - (↓DECビット012AH) -- (↓HEXビット )
ビット列 (0001 0010 1010) ← (1000 0000) 補正処理実行、1桁目のみに+3補正
8回目 - (↓DECビット0255H) -- (↓HEXビット )
ビット列 (0010 0101 0101) ← (0000 0000) 最終の左シフトして終了、補正処理しません
以上、8bit16進バイナリが、ちゃんと12bit10進バイナリに変換されました。
実際はこれを32bitに拡張すれば良いだけで、楽勝です。
作成関数そのものも、このビット列操作を、そのままプログラム化しています。
理屈はサッパリですが、これを考えた人は素晴らしいですね。 (^_^)
目的は8桁7セグLEDを制御するルーチン群の1つとしてです。
XC8のprintf関数で行えば良いのですが、この関数はメモリを多量に消費します。
そこで、アッセンブラでの制御と同じ関数群を作り、メモリの少ないPICでもXC8でプログラムできる様にするためです。
関数操作方法は、32bit入力で戻し値が5バイトとなるので、アッセンブラ版と同じようなBCD専用広域変数に収納します。
別バージョンでは、上位桁を切り捨てて、32bitで返します。
実際の挙動に関しては、MPLAB XIDEのシミュレータで観察すると、動作確認が出来て面白くてお勧めです。
アッセンブラ版から見える、BCD変換ルーチンの動作概要
以前の考察で記した物と同じで、未だになぜこの方法でBCDに変換できるのか理屈が全く理解できません・・・ (-_-;)
見ての通り、1bitずつ左シフトしながら、4bit単位で補正処理を繰り返します。
ここでは簡略化のため、変換前の16進バイナリ数値を8bitとして進行していきます。
8bitなので8回左シフトします。ちなみに16bit数値の場合は16回、32bit数値の場合は32回左シフトします。
最後の左シフト後は補正処理しません。
変換されたBCDの格納変数はDEC12、DEC34の2バイトとし、ビットは全てクリアしておきます。
1桁4bitが基本となりますので、ここではDECを16bit変数として扱い、
さらに変換後は最大3桁12bit使用しますので、変数DECの上位4bit(bit15-bit12)は表示を省略します。
変換前の16進バイナリ数値はHEX0の1バイトで、例として値はFFHとします。
下記の用に1ビットずつ左へ(MSBへ)シフトします。
破棄 ← DEC34 ← DEC12 ← HEX0 ← ゼロビット
DEC4,3桁 DEC2,1桁 元値16進
変換前の16進バイナリ数値HEX0は左シフトすると、LSBには0がシフトしてくるとします。
16ビットDEC変数はLSBから順に1bitずつ左シフトされてくるが、左シフトする度に5以上の4ビット列(桁)は+3される事に注意
START - (↓DECビット0000H) -- (↓HEXビット FFH)
ビット列 (0000 0000 0000) ← (1111 1111)
1回目 - (↓DECビット0001H) -- (↓HEXビット )
ビット列 (0000 0000 0001) ← (1111 1110) 左シフト後、DEC1桁目は5未満で補正無し
2回目 - (↓DECビット0003H) -- (↓HEXビット )
ビット列 (0000 0000 0011) ← (1111 1100) 左シフト後、DEC1桁目は5未満で補正無し
3回目 - (↓DECビット0007H) -- (↓HEXビット )
ビット列 (0000 0000 0111) ← (1111 1000) 左シフト後、DEC1桁目は5以上で補正必要
3回目 - (↓DECビット000AH) -- (↓HEXビット )
ビット列 (0000 0000 1010) ← (1111 1000) 補正処理実行、DEC1桁目のみに+3補正
4回目 - (↓DECビット0015H) -- (↓HEXビット )
ビット列 (0000 0001 0101) ← (1111 0000) 左シフト後、DEC1桁目は5以上で補正必要
4回目 - (↓DECビット0018H) -- (↓HEXビット )
ビット列 (0000 0001 1000) ← (1111 0000) 補正処理実行、DEC1桁目のみに+3補正
5回目 - (↓DECビット0031H) -- (↓HEXビット )
ビット列 (0000 0011 0001) ← (1110 0000) 左シフト後、DEC1桁目,2桁目はそれぞれ5未満で補正無し
6回目 - (↓DECビット0063H) -- (↓HEXビット )
ビット列 (0000 0110 0011) ← (1100 0000) 左シフト後、DEC1桁目5未満,2桁目は5以上で補正必要
6回目 - (↓DECビット0093H) -- (↓HEXビット )
ビット列 (0000 1001 0011) ← (1100 0000) 補正処理実行、2桁目のみに+3補正
7回目 - (↓DECビット0127H) -- (↓HEXビット )
ビット列 (0001 0010 0111) ← (1000 0000) 左シフト後、DEC2,3桁目は5未満,1桁目は5以上で補正必要
7回目 - (↓DECビット012AH) -- (↓HEXビット )
ビット列 (0001 0010 1010) ← (1000 0000) 補正処理実行、1桁目のみに+3補正
8回目 - (↓DECビット0255H) -- (↓HEXビット )
ビット列 (0010 0101 0101) ← (0000 0000) 最終の左シフトして終了、補正処理しません
以上、8bit16進バイナリが、ちゃんと12bit10進バイナリに変換されました。
実際はこれを32bitに拡張すれば良いだけで、楽勝です。
作成関数そのものも、このビット列操作を、そのままプログラム化しています。
理屈はサッパリですが、これを考えた人は素晴らしいですね。 (^_^)
XC8版 BCD変換関数ソースファイル
16進32bit符号無し整数を40bitBCDに変換
BCD.h
BCD.c
16進32bit符号無し整数を32bitBCDに変換
BCD24.h
BCD24.c
XC8版BCD関数使用方法
関数は2種類です BCD関数は10桁表示ができるLCD等での使用が適しています、
BCD24関数は8桁7セグLED表示器等での使用が適しています。
1) void BCD(unsigned long int 引数)
32bit16進バイナリ数値を40bitBCDに変換します
40bitを戻し値とする方法が解らなかったので、広域変数に収納としました。
引数:32bit16進バイナリ符号無し数値(0H~FFFFFFFFH)
戻値:専用広域変数に収納
digit12 0-3bit BCD1桁目
4-7bit BCD2桁目
digit34 0-3bit BCD3桁目
4-7bit BCD4桁目
digit56 0-3bit BCD5桁目
4-7bit BCD6桁目
digit78 0-3bit BCD7桁目
4-7bit BCD8桁目
digit9A 0-3bit BCD9桁目
4-7bit BCD10桁目
2) unsigned long int BCD24(unsigned long int 引数)
32bit16進バイナリ数値を40bitBCDに変換します
変換後は32bitBCDとして返します
変換された40bitBCDの内、上位8bitを切り捨てます
事実上24bit程度のBCD変換と言う事になります。
切り捨てを行ってもエラー等は返しません
引数:32bit16進バイナリ符号無し数値(0H~FFFFFFH)
戻値:8桁の32bitBCD
ヘッダーファイル
上記専用広域変数定義および関数プロトタイプ宣言をしています。
関数群ファイル(とは言っても下記の2関数のみです)
BCD関数
ADJ_BCD関数
ヘッダーも関数も小さいので、メインプログラムに埋め込んでも良いのではと思います。
もちろん、printf関数を使用すれば、このBCD関数は不要ですがね。
別ページに、このBCD関数を使用したデモプログラムがあります。
16進32bit符号無し整数を40bitBCDに変換
BCD.h
BCD.c
16進32bit符号無し整数を32bitBCDに変換
BCD24.h
BCD24.c
XC8版BCD関数使用方法
関数は2種類です BCD関数は10桁表示ができるLCD等での使用が適しています、
BCD24関数は8桁7セグLED表示器等での使用が適しています。
1) void BCD(unsigned long int 引数)
32bit16進バイナリ数値を40bitBCDに変換します
40bitを戻し値とする方法が解らなかったので、広域変数に収納としました。
引数:32bit16進バイナリ符号無し数値(0H~FFFFFFFFH)
戻値:専用広域変数に収納
digit12 0-3bit BCD1桁目
4-7bit BCD2桁目
digit34 0-3bit BCD3桁目
4-7bit BCD4桁目
digit56 0-3bit BCD5桁目
4-7bit BCD6桁目
digit78 0-3bit BCD7桁目
4-7bit BCD8桁目
digit9A 0-3bit BCD9桁目
4-7bit BCD10桁目
2) unsigned long int BCD24(unsigned long int 引数)
32bit16進バイナリ数値を40bitBCDに変換します
変換後は32bitBCDとして返します
変換された40bitBCDの内、上位8bitを切り捨てます
事実上24bit程度のBCD変換と言う事になります。
切り捨てを行ってもエラー等は返しません
引数:32bit16進バイナリ符号無し数値(0H~FFFFFFH)
戻値:8桁の32bitBCD
ヘッダーファイル
上記専用広域変数定義および関数プロトタイプ宣言をしています。
関数群ファイル(とは言っても下記の2関数のみです)
BCD関数
ADJ_BCD関数
ヘッダーも関数も小さいので、メインプログラムに埋め込んでも良いのではと思います。
もちろん、printf関数を使用すれば、このBCD関数は不要ですがね。
別ページに、このBCD関数を使用したデモプログラムがあります。