<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ここまで**************************