電子工作

【電子工作】PICマイコン「2進-10進-16進 LCD 表示ボード」製作

【電子工作】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進数・ビット意識の向上にどうぞ。