Replace 7 segment LED driver IC to PIC for Hexadecimal format Display Capability

きっかけ

ある日、ふとしたきっかけで始めたことだが、ひょっとすると同じような事をしたいと思った人が

実は結構たくさんいるんじゃないかと考えてFPGAじゃないけど番外編として記事を公開することにします。

デバック情報やエラーコードを表示している7セグLEDにもし16進数を表示できたら

あと5つエラーコードが増やせるのに、通常のドライバーICだと0Ahを超えると暗号じみた意味不明なフォントや、

何も表示されない状態になってしまいます。

ポートを節約しようと つい「4511」「74LS247』や「74LS47」ってDIPバッケージの

ドライバーICを使ってしまったのが後の祭り、これだけのためにいまさらFPGAで基板を作り直すなんて

大げさだし、何よりまして手間がかかりすぎて、とてもやってらんない!

こんな時、昔ならCUPLとかでサクっと置き換え可能なPLDを作ったものだけど、これまた

入手困難だし、ライターや開発環境を新期に購入するなんてアホくさい事はしたくないよと

思ってたところに、ふと目についたのが電子工作好きなら普通に持ってる!?PICの開発ツール

これでロジックIC動作をシミュレートするプログラムを走らせればイケるんじゃないかと

思いついた。 残念ながら電源ピンの位置が一般的なロジックICとは違うので単純にピン互換

とはいけないけど、代替したい石より2ピン多いDIPパッケージのものを選択して電源ピンは

入力ポートにしてしまえば多少の切った張っただけで代替えできる方法を思いついた。

注意点:

気をつける必要があるのは以下のような事です

  • PICはクロック用の内蔵RCオシレターが使える品種をチョイスすること
  • PICでは入力にしか使えないピン(MCLR等)があるので、互換のピンアサインを考えるときにうまく割り振れるようにPIC種別や方向、ズラす向き等を工夫すること
  • 出力ポートがドライブできる最大電流の制限を超えないこと
  • 基本ソフト処理なので極端に高速な動作が要求されない事
  • 切り貼りするピンを最小限に押さえること
  • 高速化のためにインヒビットやイネーブル端子の機能は実装していないこと

実装方法:

以下の事例に示すように、元々付いてたDIPパッケージの4511を外して、その基板に

PICの電源ピンを上に折り返して曲げてから16ピンのICソケットに挿し、ポートの接続を下図のように加工した書き込み済みのPICを取り付ける。

4511(7セグ用BCD表示デコーダー)の置き換え例

Top View

これを横方向から見た図

SIde View

これで与えられたデータが10〜15までの値では無表示だった4511の7セグの表示器が、PICマイコンに交換することで「A〜F」となりフルに16進数で表示できるようになりました。

コード :

(開発環境=MPLAB8.87 XC8コンパイラ使用)

  • ver0.1

コメント:

実行速度のことを全く気にせずに無償版Cコンパイラで書いたので、スタチック点灯なら特に問題ないが

ダイナミック点灯で使った場合には、実行速度が非常に遅くてリフレッシュが高速にできず実用に耐えないとクレームを頂戴した。

ビットシフト命令の多用が敗因である、次の版では表引きの添字演算とポートから出力する値を演算する部分の大半を演算無しで即処理

できるようにアルゴリズムを大幅に変える予定・・・

ver 0.1 Source Code (main.c)

#include <xc.h> #include <pic.h> #include <pic16f1827.h> #include <htc.h> #define _XTAL_FREQ 8000000 // ロック8MHzと仮指定 // Set up Configuration Bits __CONFIG(CLKOUTEN_OFF & IESO_OFF & MCLRE_OFF & WDTE_OFF & PWRTE_ON & STVREN_OFF & FOSC_INTOSC & PLLEN_ON); /* ----<FONT DATA>---- */ unsigned char font7seg[] = { (0xfc), // '0' (0x60), // '1' (0xda), // '2' (0xf2), // '3' (0x66), // '4' (0xb6), // '5' (0xbe), // '6' (0xe0), // '7' (0xfe), // '8' (0xe6), // '9' (0xee), // 'A' (0x3e), // 'B' (0x9c), // 'C' (0x7a), // 'D' (0x9e), // 'E' (0x8e) // 'F' }; main(VOID) { unsigned char incode, indexnum, outcode; OSCCON = 0b01110010 ; // 内部クロックは8MHzとする ANSELA = 0b00000000 ; // AN0-AN4は使用しない全てデジタルI/Oとする ANSELB = 0b00000000 ; // AN5-AN11は使用しない全てデジタルI/Oとする TRISA = 0b00111101 ; // ポートAはRA1,RA6,RA7が出力、他は全て入力にする(RA5は入力専用) TRISB = 0b00001111 ; // ポートBはRB4,RB5,RB6,RB7が出力、他は全て入力にする // PORTA = 0b00000000 ; // RA出力ピンの初期化(全てLOWにする) // PORTB = 0b00000000 ; // RB出力ピンの初期化(全てLOWにする) while(1) { incode = PORTA; indexnum = ((incode & 0b00001000) >> 2); //bit1 indexnum += ((incode & 0b00010000) >> 2); //bit2 incode = PORTB; indexnum += ((incode & 0b00000100) >> 2); //bit0 indexnum += ((incode & 0b00000010) << 2); //bit3 outcode = font7seg[indexnum]; PORTA = ((outcode & 0b10000000) >> 6) + ((outcode & 0b00000110) << 5); PORTB = ((outcode & 0b01111000) << 1); } }

  • ver0.2

コメント

まず、出力側の高速化だが 演算に費やす時間を削減するために、出力ポートAとB用で独立したルックアップテーブルを持たせ

それぞれの表から読んだ値をそのままポートに出力すれば良いようにした、ここだけで12回のビットシフト操作が削減できた。

同様にデータ線を読み取って表引きする側も該当ビットの論理和を直接配列の添字にして表引きするだけで引けるように工夫した

こちら側では6回のビットシフト操作が削減できたので合計18回もビットシフト操作が削減できたことになる・・・

ver 0.2 Source Code (main.c)

#include <xc.h>

#include <pic.h>

#include <pic16f1827.h>

#include <htc.h>

#define _XTAL_FREQ 8000000 // ロック8MHzと仮指定

// Set up Configuration Bits

__CONFIG(CLKOUTEN_OFF & IESO_OFF & MCLRE_OFF & WDTE_OFF & PWRTE_ON & STVREN_OFF & FOSC_INTOSC & PLLEN_ON);

// LED segment Control Data Look-up Table

#include "font7seg.h"

main(VOID)

{

unsigned char incode;

OSCCON = 0b01110010 ; // 内部クロックは8MHzとする

ANSELA = 0b00000000 ; // AN0-AN4は使用しない全てデジタルI/Oとする

ANSELB = 0b00000000 ; // AN5-AN11は使用しない全てデジタルI/Oとする

TRISA = 0b00111101 ; // ポートAはRA1,RA6,RA7が出力、他は全て入力にする(RA5は入力専用)

TRISB = 0b00001111 ; // ポートBはRB4,RB5,RB6,RB7が出力、他は全て入力にする

while(1)

{

PORTA = font7seg_pa[(incode = (0b00011000 & PORTA) | (0b00000110 & PORTB))];

PORTB = font7seg_pb[incode];

}

}

セグメントの点灯データ(font7seg.h)

/*

----<7SEG FONT DATA>----

*/

const unsigned char font7seg_pa[] =

{

//pppppppp RRRR D SSSS SSSH

//AAAAAAAA AABB I EEEE EEE+

//76543210 4321 N GGGG GGG1

//fg a abcd efgh

0b10000010, // 0000 =0 :1111 1100

0b10000010, // 0000 =0 :1111 1100

0b11000010, // 0001 =8 :1111 1110

0b11000010, // 0001 =8 :1111 1110

0b00000000, // 0010 =1 :0110 0000

0b00000000, // 0010 =1 :0110 0000

0b11000010, // 0011 =9 :1111 0111

0b11000010, // 0011 =9 :1111 0111

0b01000010, // 0100 =2 :1101 1010

0b01000010, // 0100 =2 :1101 1010

0b11000010, // 0101 =A :1110 1111

0b11000010, // 0101 =A :1110 1111

0b01000010, // 0110 =3 :1111 0010

0b01000010, // 0110 =3 :1111 0010

0b11000000, // 0111 =B :0011 1111

0b11000000, // 0111 =B :0011 1111

0b11000000, // 1000 =4 :0110 0110

0b11000000, // 1000 =4 :0110 0110

0b10000010, // 1001 =C :1001 1101

0b10000010, // 1001 =C :1001 1101

0b11000010, // 1010 =5 :1011 0110

0b11000010, // 1010 =5 :1011 0110

0b01000000, // 1011 =D :0111 1011

0b01000000, // 1011 =D :0111 1011

0b11000010, // 1100 =6 :1011 1110

0b11000010, // 1100 =6 :1011 1110

0b11000010, // 1101 =E :1001 1111

0b11000010, // 1101 =E :1001 1111

0b00000010, // 1110 =7 :1110 0000

0b00000010, // 1110 =7 :1110 0000

0b11000010, // 1111 =F :1000 1111

0b11000010, // 1111 =F :1000 1111

};

const unsigned char font7seg_pb[] =

{

//pppppppp RRRR D SSSS SSSH

//BBBBBBBB AABB I EEEE EEE+

//76543210 4321 N GGGG GGG1

//b de c abcd efgh

0b10110010, // 0000 =0 :1111 1100

0b10110010, // 0000 =0 :1111 1100

0b10110010, // 0001 =8 :1111 1110

0b10110010, // 0001 =8 :1111 1110

0b10000010, // 0010 =1 :0110 0000

0b10000010, // 0010 =1 :0110 0000

0b10100010, // 0011 =9 :1111 0111

0b10100010, // 0011 =9 :1111 0111

0b10110000, // 0100 =2 :1101 1010

0b10110000, // 0100 =2 :1101 1010

0b10010010, // 0101 =A :1110 1111

0b10010010, // 0101 =A :1110 1111

0b10100010, // 0110 =3 :1111 0010

0b10100010, // 0110 =3 :1111 0010

0b00110010, // 0111 =B :0011 1111

0b00110010, // 0111 =B :0011 1111

0b10000010, // 1000 =4 :0110 0110

0b10000010, // 1000 =4 :0110 0110

0b00110000, // 1001 =C :1001 1101

0b00110000, // 1001 =C :1001 1101

0b00100010, // 1010 =5 :1011 0110

0b00100010, // 1010 =5 :1011 0110

0b10110010, // 1011 =D :0111 1011

0b10110010, // 1011 =D :0111 1011

0b00110010, // 1100 =6 :1011 1110

0b00110010, // 1100 =6 :1011 1110

0b00110000, // 1101 =E :1001 1111

0b00110000, // 1101 =E :1001 1111

0b10000010, // 1110 =7 :1110 0000

0b10000010, // 1110 =7 :1110 0000

0b00010000, // 1111 =F :1000 1111

0b00010000, // 1111 =F :1000 1111

};

アクセスカウンター
アクセスカウンター