<LCD表示文字の取得>

<PICによるCW SEND>で紹介した文字のEEPROM書き込みは結構ボタン操作が辛い。
1文字入力しては、書込みボタンを押してEEPROMに書き込んでいた。
それで、まず書き込みたい文字を入力して、LCDに表示された文字列をボタン操作1回で
EEPROMに書き込む事は出来ないだろうか検討しました。LCDに表示された文字を
取込む必要があります。

LCDのインストラクションコードの中にDDRAM DataReadと言うのがあります。これは
LCDの表示文字を取得する命令のようである。ただ、この使い方が今一分からなかった。
ネットをぐぐっても具体的なプログラム記述がない(-_-;)

そこで、いろいろ試行錯誤した結果、LCDの表示文字を取得するプログラムを作ることが出来ました。
LCDの表示文字を取得するには、例えばLCDに1GZの3文字が表示している場合
最初の1の文字のアドレスをDDRAM Address Set命令で設定してからDDRAM DataRead命令する。
これを3文字目のZまで繰り返す。

プログラムのポイントは、以下(@-C)のところです。
@DDRAM DataRead命令の時はRS,RWの制御信号はH(1)にする。
ARC3(DB7),RC2(DB6),RC1(DB5),RC0(DB4)はTRISC=0xFFで入力モードにする。

B次のようにRC3-RC0に取り込んだ各bitデータを変数(lcddata)に入れる。
MSBの取り込処理
	if(RC3==1) lcddata7=0b10000000;
	if(RC2==1) lcddata6=0b01000000;
	if(RC1==1) lcddata5=0b00100000;
	if(RC0==1) lcddata4=0b00010000;
LSBの取り込処理
	if(RC3==1) lcddata3=0b00001000;
	if(RC2==1) lcddata2=0b00000100;
	if(RC1==1) lcddata1=0b00000010;
	if(RC0==1) lcddata0=0b00000001;
Cmoji=(lcddata7 | lcddata6 | lcddata5 | lcddata4 | lcddata3 | lcddata2 | lcddata1 | lcddata0);
このmojiデータをEEPROMに書き込む。


下記のプログラムは、取得文字の8bitをMSB,LSBの4bitづつ2回に分けてLEDで表示させるものです。

1は0x31、Gは0x47、Zは0x5Aなので

(1)
0011
0001

(G)
0100
0111

(Z)
0101
1010

のようにLEDが点灯(1)します。

これで、更なるバージョンアップしたYYCWが出来そうです。(^.^)

画像をクリックして見て下さい。


回路図(2014.12.1訂正)


プログラムソース
*************************main**************************
#include<pic.h>
#include<htc.h>
#include<stdio.h>
#include<string.h>


//(1)
__CONFIG(PWRTEN & WDTDIS  & MCLREN & INTIO);/*内部発振*/
//__CONFIG(PWRTEN & WDTDIS  & MCLREN & HS);/*水晶発振*/

//(2)	内部発振はMAX8MHzまで
// 発振変更はこのOSCCON=0x70;(8000kHzの場合)も変更する	
//#define _XTAL_FREQ 4000000	/* 4MHz */
#define _XTAL_FREQ 8000000	/* 8MHz */
//#define _XTAL_FREQ 10000000   /* 10MHz */
//#define _XTAL_FREQ 20000000	/* 20MHz */
#define JIKAN 500		    /* 500ミリ秒 */
#define PORT PORTC
#define ENABLE RA0
#define RS RA1
#define RW RA4
#define JIKAN1 1100
#define JIKAN2 500

lcd_position(unsigned char);
void putch(unsigned char rxdata);
lcd_init();
ioport();

function_set();
disp_control();
clear_disp();
entry_mode();


int pos=0;

int add_cnt=0;
int tadd_cnt=0;

char msbdata;
char lsbdata;

swra5a();
swra5b();
int f_swra5=0;

int lcddata0=0;
int lcddata1=0;
int lcddata2=0;
int lcddata3=0;
int lcddata4=0;
int lcddata5=0;
int lcddata6=0;
int lcddata7=0;
char moji;

ddram_addset();
lcd_read();

main()
{

//OSCCON=0x60;	/* 4000kHz */
OSCCON=0x70;	/* 8000kHz */


ioport();
lcd_init();		/* LCDを初期化する */

//printfによる表示
lcd_position(0x00);
printf("1GZ");

	while(1){

			if(RA5==0 && f_swra5==0) swra5a();
			if(RA5==1 && f_swra5==1){
				swra5b();

						do{
							ddram_addset();
							__delay_ms(10);
							lcd_read();
							if(add_cnt==20) add_cnt=0;
					
						}while (tadd_cnt<=2);
							tadd_cnt=0;
							add_cnt=0;
							lcd_position(0x00);	//書き込み終了したらカーソルを初期位置にする
			}//if(RA5==1



	}//while

}//main


swra5a()
{
__delay_ms(50);
f_swra5=1;
}

swra5b()
{
__delay_ms(50);
f_swra5=0;
}


ddram_addset()
{
	//DDRAMアドレスセット
	RS=0;
	RW=0;
	ENABLE=0;
	__delay_us(80);//	__delay_us(80)
	if(tadd_cnt>=0 && tadd_cnt<=15) PORT=0x08;
	if(tadd_cnt>=16 && tadd_cnt<=19) PORT=0x09;
	if(tadd_cnt>=20 && tadd_cnt<=35) PORT=0x0C;
	if(tadd_cnt>=36 && tadd_cnt<=39) PORT=0x0D;

	ENABLE=1;			/*(7)*/
	__delay_us(200);//	__delay_us(80)
	ENABLE=0;

	ENABLE=0;
	__delay_us(80);//	__delay_us(80)
	PORT=0x00+add_cnt;          /* 0,1,I/D:1,S:0 I/D(increment:+1) S(shift:NO increment*/

	ENABLE=1;			/*(7)*/
	__delay_us(200);//	__delay_us(80)
	ENABLE=0;
	
}

lcd_read()
{
	RS=1;
	RW=1;
	TRISC=0xFF;
	ENABLE=0;
	__delay_us(200);

	ENABLE=1;		//ENABLE=1のすぐ下に下記if文を置く、ENABLE=0の下に置くとNG


	lcddata7=0x00;
	lcddata6=0x00;
	lcddata5=0x00;
	lcddata4=0x00;

	if(RC3==1) lcddata7=0b10000000;
	if(RC2==1) lcddata6=0b01000000;
	if(RC1==1) lcddata5=0b00100000;
	if(RC0==1) lcddata4=0b00010000;
	
	__delay_us(200);
	ENABLE=0;
	



	ENABLE=1;	//ENABLE=1のすぐ下に下記if文を置く、ENABLE=0の下に置くとNG

	lcddata3=0x00;
	lcddata2=0x00;
	lcddata1=0x00;
	lcddata0=0x00;

	if(RC3==1) lcddata3=0b00001000;
	if(RC2==1) lcddata2=0b00000100;
	if(RC1==1) lcddata1=0b00000010;
	if(RC0==1) lcddata0=0b00000001;

	__delay_us(200);

	ENABLE=0;

	TRISC=0xF0;
	RS=0;
	RW=0;

moji=(lcddata7 | lcddata6 | lcddata5 | lcddata4 | lcddata3 | lcddata2 | lcddata1 | lcddata0);
	PORTB=moji;
	__delay_ms(2000);
	PORTB=0;
	__delay_ms(500);
	PORTB=(moji<<4);
	__delay_ms(2000);
	PORTB=0;
	__delay_ms(500);
	++add_cnt;
	++tadd_cnt;

}

ioport()
{
ANSEL=0; 
ANSELH=0;

TRISA=0xEC;	/*RA0,1,4ピンを出力に、RA2,3,5ピンを入力設定*/
TRISB=0x00;	/*全ピンを出力設定*/
TRISC=0xF0;	/*PORTCのRC0-3ピンを出力に、RC4-7を入力ピンに設定*/

PORTA=0x00;	/*PORTA全ピンをLに設定 16進*/
PORTB=0x00;
PORTC=0x00; /*PORTC全ピンをLに設定 16進*/

//PORTA=0b01010101; /*PORTAピンをLHLHLHLHに設定 2進*/
//PORTB=0b10101010; /*PORTBピンをHLHLHLHLに設定 2進*/
//PORTC=0b01010101; /*PORTCピンをLHLHLHLHに設定 2進*/

}

void putch(unsigned char txdata) 	/* PUTCH */
{
		RW=0;
		RS=1;		//RS=RA1
		ENABLE=0;	//ENABLE=RA0
		__delay_us(80);
		PORT=(txdata>>4)&0x0F;
		// 書込みはEが1→0
		ENABLE=1;	
		ENABLE=0;
		PORT=txdata&0x0F;
		// 書込みはEが1→0
		ENABLE=1;
		ENABLE=0;

}
*************************mainここまで**************************


*************************LCDinit**************************

/////////////////////////////////////////////////////////////////////////////////////////////////////////
//     イニシャライズ手順 インターフェースデータ長4bit(データシートから)
//
//		電源ONして15ms以上待つ 
//		RS R/W DB7 DB6 DB5 DB4
//(1)	0  0   0   0   1   1 
//			4.1ms以上待つ
//(2)	0  0   0   0   1   1 
//			100μs以上待つ
//(3)	0  0   0   0   1   1 
//(4)	0  0   0   0   1   0
//(5)	0  0   0   0   1   0 ファンクションセット		0 0 1 DL	DL=0で4bit
//(6)	0  0   1   0   0   0					N F * *     N=1で2行    F=0で5×8dot
//(7)	0  0   0   0   0   0 表示オン/オフ
//(8)   0  0   1   1   0   0					1 D C B     D=1で表示オン C=0でカーソル表示しない B=0でブリンクしない
//(9)   0  0   0   0   0   0 表示クリア
//(10)  0  0   0   0   0   1		
//(11)  0  0   0   0   0   0 エントリーモード 
//(12)  0  0   0   1   1   0					0 1 I/D S	I/D=1でアドレスを+1カーソルが右に動く 
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////

#include<htc.h>
//(6) 	内部発振はMAX8MHzまで
//#define _XTAL_FREQ 4000000	/*4Mhz */ 
#define _XTAL_FREQ 8000000	/*8Mhz */ 
//#define _XTAL_FREQ 10000000 	/*10Mhz */ 
//#define _XTAL_FREQ 20000000	/*20Mhz */ 

lcd_init();
lcd_position(unsigned char);
lcd_clear();
void putch(unsigned char);

function_set();
disp_control();
clear_disp();
entry_mode();

//他のI/Oピン使用する時に変更
#define PORT PORTC
#define ENABLE RA0
#define RS RA1
#define RW RA4

char msbdata;
char lsbdata;

//__delay_us(200)__delay_us(500)はNG __delay_us(600);でOK(4MHz、8MHz確認済み)

lcd_init()		/* LCDモジュール初期化  PIC:PIC16F689 確認LCD:SC2004C */
{                       /* RS:RA1 ENABLE:RA0 */
	RW=0;
	RS=0;				/*RS=0 instruction input RS=1 data input*/ 
	ENABLE=0;            /* 8bitモード */

	__delay_ms(15); 	/*(1)__delay_ms(15)*/
	PORT=0x03;                
	ENABLE=1;			
__delay_us(600);
	ENABLE=0;
	__delay_ms(5);
	ENABLE=1;			/*(2)__delay_ms(5)*/
__delay_us(600);	
ENABLE=0;
	__delay_ms(5);
	ENABLE=1;			/*(3)__delay_ms(5)*/
__delay_us(600);
ENABLE=0;


	PORT=0x02;                
	ENABLE=1;			/*(4)*/
__delay_us(600);
	ENABLE=0;
//LCD初期化のインストラクションコードを下記のように関数別にした
//関数別にすることにより、使いたいインストラクションコードを呼びだして使うことが出来る
	function_set();

	msbdata=0x00;
	lsbdata=0x0C;
	disp_control();

	clear_disp();
	entry_mode();

}

function_set()
{
    /* function set */
	RW=0;
	RS=0;
	PORT=0x02;
	ENABLE=1;			/*(5)*/
__delay_us(600);
	ENABLE=0;
	PORT=0x08;				 
	ENABLE=1;			/*(6)*/
__delay_us(600);
ENABLE=0;
}

disp_control()
{
    /* disp control*/
	RW=0;
	RS=0;
	PORT=msbdata;
	ENABLE=1;			/*(7)*/
__delay_us(600);	
ENABLE=0;
	PORT=lsbdata;		          
	ENABLE=1;			/*(8)*/
__delay_us(600);	
ENABLE=0;
}

clear_disp()
{
    /*clear disp*/
	RW=0;
	RS=0;
	PORT=0x00;
	ENABLE=1;			/*(9)*/
__delay_us(600);	
ENABLE=0;
	PORT=0x01;
	ENABLE=1;			/*(10)*/
__delay_us(600);	
ENABLE=0;
}
entry_mode()
{
    /*entry mode*/
	RW=0;
	RS=0;
	PORT=0x00;
	ENABLE=1;			/*(11)*/
__delay_us(600);
ENABLE=0;
	PORT=0x06;              
	ENABLE=1;			/*(12)*/
__delay_us(600);
ENABLE=0;
}
//***************************************************************



//***************************************************************
lcd_position(unsigned char pos)		/* 文字の位置を指定 */
{	
	RW=0;								/* dd ram address set */
	RS=0;

	PORT=(((0x80+pos)>>4)&0x0F);

	ENABLE=1;
__delay_us(600);
	ENABLE=0;
	PORT=((0x80+pos)&0x0F);

	ENABLE=1;
__delay_us(600);
	ENABLE=0;
}


//***************************************************************
lcd_clear()			           /* 画面をクリア */
{
	RW=0;							   /* clear display */
	RS=0;
	PORT=0x00;
	ENABLE=1;
__delay_us(600);
	ENABLE=0;
	PORT=0x01;
	ENABLE=1;
__delay_us(600);
	ENABLE=0;
	
}
//***************************************************************

*************************LCDinitここまで**************************