【電子工作】PICマイコン「2進-10進-16進 LCD 表示ボード」製作
デジタル回路の基本2進数、対応するビットへの意識の向上は重要です。
本サイトでは、関連するこれらの情報を他のカテゴリ「情報工学の基礎」にも紹介しています。
はじめに
本機能と同様な、7セグLEDを利用した表示ボードは下記を参照下さい。
【電子工作】PICマイコン「2進-16進 7セグ 表示ボード」製作
本記事では、2進スイッチ入力から、2進・10進・16進をLCDに表示する回路を紹介いたします。
入力スイッチ
スイッチレバーを動かすことでON/OFFを行う一般的なトグルスイッチを使用し、2進数をイメージ(指で数える代わりに)して、パチパチと上げ下げの操作で入力します。
LCD表示器
LCD:「Liquid Crystal Display」の略 つまり液晶ディスプレイです。
ここでは、小型で汎用のキャラクタLCDモジュール(8文字×2行バックライト付き)を使用しました。
8文字×2行で16文字の情報量がありますので、上段に10、16進数、下段に2進数で構成し出力させます。
I²C
Inter-Integrated Circuitの略(アイ・スクエアド・シー、アイ・アイ・シー、アイ・ツー・シー)
2本のライン(SDA (Serial Data)、SCL (Serial Clock))上に、複数のデバイス(スレーブ)をアドレス指定で可能な短距離のシリアル通信規格
本回路はこのI²C規格のLCDディスプレイを利用して、2進、10進及び16進を上記のフォーマットで出力します。
PIC
Master Synchronous Serial Port (MSSP) でI2Cが利用できるPIC、
I2C通信SCL,SDA:2ピン、2進値4ビット入力用:4ピン この構成可能な 汎用小型8ピンPIC 12F1822 を使用します。
I²C関するMSSP関連の詳細な手順やレジスタ設定の内容など、下記サイトを利用させていただきました。
参考サイト
部品表
回路図
スイッチに連動された2進表記LED、入力信号をプルダウン回路で構成しています。
デモモード
0から15までの値を自動的に表記します。
- デモモードスイッチ
入力スイッチの3ビット目がONされた状態で電源スイッチをONその状態を3秒保持
することにより、デモモードとして自動的に1周実行します。(8ピンPICで通常入出力を6ピン使用する都合上、デモモードの意識を上記のように設定しました)
プログラム
- デモモードの判定
スイッチタイミング判定(上記)
デモモード:0->15までの指示ビットを設定し共通ルーチンの実行
それ以外:標準実行(プルダウン入力(ON:「+」信号)から指示ビット設定
- 共通ルーチンの実行
指示ビットを判定し、対応する2、10、16進情報をLCD出力
/*===============================================================================
/
/ 2進・10進・16進 Display Board
/
/ PIC 12F1822
/
/
/
/ MPLAB X IDE v5.45 , XC8
/ https://www.pochiweb.com
/
/================================================================================
/ 12F1822
/
/ 01-Vdd 08-VSS
/ 02-RA5 ← bin #3 S/W(P/D) 07-RA0 ← bin #0 S/W(P/D)
/ 03-RA4 ← bin #2 S/W(P/D) 06-RA1 → I2C SDL LCA
/ 04-RA3 ← bin #1 S/W(P/D) 05-RA2 → I2C SDA LCA
/
/================================================================================
*/
#define _XTAL_FREQ 4000000 // 4MHz発振
#define CONTRAST 0x28 // LCD コントラスト 3.3V
// #define CONTRAST 0x18 // LCD コントラスト 5.0V(reserve)
#include <xc.h>
// === CONFIG1 ===
#pragma config FOSC = INTOSC // 内部発振使用
#pragma config WDTE = OFF // watchdog タイマ OFF
#pragma config PWRTE = OFF // パワーアップタイマ(立上り待機)OFF
#pragma config MCLRE = OFF // MCLR デジタル
#pragma config CP = OFF // コードプロテクト OFF
#pragma config CPD = OFF // データコードプロテクト OFF
#pragma config BOREN = ON // ブラウンアウトリセット ON
#pragma config CLKOUTEN = OFF // クロックアウト OFF
#pragma config IESO = OFF // 内部外部クロック切換え OFF
#pragma config FCMEN = OFF // クロックモニタ OFF
// === CONFIG2 ===
#pragma config WRT = OFF // プログラムメモリ書込み保護 OFF
#pragma config PLLEN = OFF // PLL x 4 OFF
#pragma config STVREN = ON // スタックオーバリセット ON
#pragma config BORV = LO // ブラクンアウト電圧 LO
#pragma config LVP = OFF // 低電圧プログラミング OFF
unsigned char bin_sw; // 2進値域
unsigned char bif_bin_sw; // 2進値域(前)
unsigned char auto_demo; // auto demo flag
//
// === プロトタイプ ===
//
void i2cLcdWrite(char, char, char); // LCD I2C 初期化
void i2cTxData(char); // I2C 1文字保存書込送信
void LCD_dat(char); // LCD データ入力
void LCD_cmd(char); // LCD コマンド入力
void LCD_clr(void); // LCD クリア
void LCD_posyx(char,char); // LCD x,y
void LCD_int(void); // LCD 初期化
void out_lcddisp(void); // LCD 出力
void LCD_MSG_1Line(const char *); // LCD 1行目
void LCD_MSG_2Line(const char *); // LCD 2行目
//
// === MAIN ===
//
void main() {
//
OSCCON = 0b01101010; // 内部クロック4Mhz
PORTA = 0x00; // PortA クリア
TRISA = 0xFF; // PortA すべて入力
ANSELA = 0x00; // すべてデジタル
WPUA = 0x00; // 弱プルアップ OFF
nWPUEN = 0;
// === I2C SSP1設定
SSP1STAT = 0b10000000; // スルーレート制御 無効
SSP1ADD = 9; // クロック設定 100k@4MHz
SSP1CON1 = 0b00101000; // I2C Master modeにする
//
LCD_int(); // LCD初期化
//
bin_sw = 0x00; // 2進S/W 初期化
//
// // DEMO 判定
if (RA5 == 1) { // (1000 S/W ON & Power ON & 3SEC)
__delay_ms(1000);
if (RA5 == 1) {
LCD_MSG_1Line("Dec:Hex:"); // "DEMO表記 上段出力"
LCD_MSG_2Line("Bin:DEMO"); // "DEMO表記 下段出力"
__delay_ms(3000);
if (RA5 == 1) { // DEMO 実行
for (bin_sw = 0; bin_sw <= 15; bin_sw++) {
out_lcddisp();
__delay_ms(1000);
}
}
}
}
//
while(1) {
// S/W情報 -> 2進変換
bin_sw = PORTA; // 2進S/W セット
bin_sw = bin_sw & 0x39; // マスク
bin_sw >>= 2; // 2ビット右シフト
if(RA0 == 1) // RA0(0ビット目) ON?
bin_sw |= 0b00000001; // 0ビットOR
out_lcddisp(); // LCD出力処理
}
}
//
void out_lcddisp(void){
//
LCD_int();
switch(bin_sw){
case 0b00000000: // 0000
LCD_MSG_1Line("D:00 H:0"); // 上段出力
LCD_MSG_2Line(" B:0000 "); // 下段出力
break;
case 0x00000001: // 0001
LCD_MSG_1Line("D:01 H:1"); //
LCD_MSG_2Line(" B:0001 "); //
break;
case 0b00000010: // 0010
LCD_MSG_1Line("D:02 H:2"); //
LCD_MSG_2Line(" B:0010 "); //
break;
case 0b00000011: // 0011
LCD_MSG_1Line("D:03 H:3"); //
LCD_MSG_2Line(" B:0011 "); //
break;
case 0b00000100: // 0100
LCD_MSG_1Line("D:04 H:4"); //
LCD_MSG_2Line(" B:0100 "); //
break;
case 0b00000101: // 0101
LCD_MSG_1Line("D:05 H:5"); //
LCD_MSG_2Line(" B:0101 "); //
break;
case 0b00000110: // 0110
LCD_MSG_1Line("D:06 H:6"); //
LCD_MSG_2Line(" B:0110 "); //
break;
case 0b00000111: // 0111
LCD_MSG_1Line("D:07 H:7"); //
LCD_MSG_2Line(" B:0111 "); //
break;
case 0b00001000: // 1000
LCD_MSG_1Line("D:08 H:8"); //
LCD_MSG_2Line(" B:1000 "); //
break;
case 0b00001001: // 1001
LCD_MSG_1Line("D:09 H:9"); //
LCD_MSG_2Line(" B:1001 "); //
break;
case 0b00001010: // 1010
LCD_MSG_1Line("D:10 H:A"); //
LCD_MSG_2Line(" B:1010 "); //
break;
case 0b00001011: // 1011
LCD_MSG_1Line("D:11 H:B"); //
LCD_MSG_2Line(" B:1011 "); //
break;
case 0b00001100: // 1100
LCD_MSG_1Line("D:12 H:C"); //
LCD_MSG_2Line(" B:1100 "); //
break;
case 0b00001101: // 1101
LCD_MSG_1Line("D:13 H:D"); //
LCD_MSG_2Line(" B:1101 "); //
break;
case 0b00001110: // 1110
LCD_MSG_1Line("D:14 H:E"); //
LCD_MSG_2Line(" B:1110 "); //
break;
case 0b00001111: // 1111
LCD_MSG_1Line("D:15 H:F"); //
LCD_MSG_2Line(" B:1111 "); //
break;
default:
LCD_MSG_1Line("D:xx H:x"); //
LCD_MSG_2Line(" B:xxxx "); //
break;
}
}
//********************************************************************
// I2C 関連
//********************************************************************
//-------- ByteI2C送信
void i2cLcdWrite(char addr, char cont, char data){
SSP1CON2bits.SEN = 1; // Start condition 開始
while(SSP1CON2bits.SEN); // Start condition 確認
i2cTxData(addr); // アドレス送信
i2cTxData(cont); // 制御コード送信
i2cTxData(data); // データ送信
SSP1CON2bits.PEN = 1; // Stop condition 開始
while(SSP1CON2bits.PEN); // Stop condition 確認
}
//-------- Data送信
void i2cTxData(char data){
PIR1bits.SSP1IF = 0; // 終了フラグクリア
SSP1BUF = data; // データセット
while(!PIR1bits.SSP1IF); // 送信終了待ち
}
//********************************************************************
// LCD 関連
//********************************************************************
//-------- 1文字表示
void LCD_dat(char chr){
i2cLcdWrite(0x7C, 0x40, chr);
__delay_us(50); // 50μsec
}
//-------- コマンド出力
void LCD_cmd(char cmd){
i2cLcdWrite(0x7C, 0x00, cmd);
if(cmd & 0xFC) // 上位6ビットに1がある命令
__delay_us(50); // 50usec
else
__delay_ms(2); // 2msec ClearおよびHomeコマンド
}
// === 全消去
void LCD_clr(void){
LCD_cmd(0x01); //Clearコマンド出力
}
// === カーソル位置指定
void LCD_posyx(char ypos, char xpos){
unsigned char pcode;
switch(ypos & 0x03){
case 0: pcode=0x80;break;
case 1: pcode=0xC0;break;
}
LCD_cmd(pcode += xpos);
}
// === 初期化
void LCD_int(void){
__delay_ms(100);
LCD_cmd(0x38); // 8bit 2行 表示命令モード
LCD_cmd(0x39); // 8bit 2行 拡張命令モード
LCD_cmd(0x14); // OSC BIAS 設定1/5
// コントラスト設定
LCD_cmd(0x70 + (CONTRAST & 0x0F));
LCD_cmd(0x5C + (CONTRAST >> 4));
// LCD_cmd(0x6A); //Ffollwer for 5.0v (reserve)
LCD_cmd(0x6B); // Ffollwer for 3.3v
__delay_ms(200);
LCD_cmd(0x38); // 表示命令モード
LCD_cmd(0x0C); // Display On
LCD_cmd(0x01); // Clear Display
}
// === LCD 1行目 文字列出力
void LCD_MSG_1Line(const char *str){
while(*str) //文字列の終わり(00)まで継続
LCD_dat(*str++); //文字出力しポインタ+1
}
// === LCD 2行目 文字列出力
void LCD_MSG_2Line(const char *str){
LCD_posyx(1,0); //
while(*str) //文字列の終わり(00)まで継続
LCD_dat(*str++); //文字出力しポインタ+1
}
(動画:倍速、繰返しにてサンプル再生しています)
まとめ
- 16文字の情報が表示可能なLCDを用いることにより、2,10,16進の変換情報が表示可能で動作
- 3.3Vの対応可能なPIC,LCDに伴い、本ボードの電源はリチウム電池(3.0V)を使用しました。
スイッチの「パチパチ♪」操作
遊び感覚で、2進数・ビット意識の向上にどうぞ。