아..미쳐가는중-_-;;
몇주째 조금씩 건드리다
근 2,3일간 본격적으로 그래픽 LCD 제어를 공부하는 중인데
엘시디에 점 하나 찍는게 왜이리 어렵죠 ㅜㅠ
차영배님이 쓰신 "C-언어로 배우는 8051 기초&응용" 이란 책으로 공부중인데
이 책에 나온 그래픽 엘시디 회로랑 거의 동일하게 회로를 구성했거든요.
단지 포트 번호만 약간 다를 뿐이라 소스코드상에서 제 회로에 맞게 제대로 변경했는데
왜 제어가 안되는건지 당췌 알수가 없네요;
이 책은 희한하게,
timing도에 대한 언급이 전혀 없네요.
분명 제가 듣기로는 타이밍이 상당히 중요하다고 들었는데;;;;;;
enable 신호를 넣고 딜레이를 준다던가 하는것도 전혀 없구요. 음;
회로도를 봐도 8051 포트랑 lcd랑 다이렉트로 연결해놨구요.
으음. 혹시 이 책의 소스가 틀린걸까요.ㅇ_ㅇ;;
혹시나 해서 아래에 소스 첨부해봅니다.
시간 남으시는 분들 한번 봐주세요..소스가 틀려서 안되는것인지-_-;
아. LCD는 디바이스마트에서 구입했는데, KS0107 계열입니다. 이 책에서도 이 계열의 LCD로 설명했길래 일부러 같은 계열로 구한건데..왜 안되는지..
미쳐가는 중입니다 ㅜㅠ
참고로 아래의 소스는 LCD에 "마이다스" 라는 글자를 출력하는겁니다.
#include <AT89X51.h>
// P0.0-P0.7 : 데이터 버스
// P2.0=RS, P2.1=RW, P2.2=E, P2.4=CS1, P2.5=CS2
#define DI P2_0 // LCD 핀 정의
#define RW P2_1
#define E P2_2
#define CS1 P2_3
#define CS2 P2_4
#define BUSY P0_7
/* "M" 상위 64 x 8 폰트 */
code unsigned char M[]={ /* "마"의 윗 부분 */
0xfc,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
0xfc,0x00,0x00,0xff,0x80,0x80,0x00,0x00,
/* "이"의 윗 부분 */
0xf0,0x08,0x04,0x02,0x02,0x02,0x02,0x02,
0x04,0x08,0xf0,0x00,0x00,0xff,0x00,0x00,
/* "다"의 윗 부분 */
0xfc,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
0x04,0x00,0x00,0xff,0x80,0x80,0x00,0x00,
/* "스"의 윗 부분 */
0x00,0x00,0x00,0x80,0x40,0x20,0x10,0x0c,
0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x00};
/* "M" 하위 64 x 8 폰트 */
code unsigned char M1[]={ /* "마"의 아래 부분 */
0x3f,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x3f,0x00,0x00,0xff,0x00,0x00,0x00,0x00,
/* 이의 아래 부분 */
0x0f,0x10,0x20,0x40,0x40,0x40,0x40,0x40,
0x20,0x10,0x0f,0x00,0x00,0xff,0x00,0x00,
/* "다"의 아래 부분 */
0x3f,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
0x20,0x00,0x00,0xff,0x00,0x00,0x00,0x00,
// "스"의 아래 부분
0x24,0x22,0x21,0x20,0x20,0x20,0x20,0x20,
0x20,0x20,0x20,0x20,0x21,0x22,0x24,0x00};
/* LCD0 비지 플래그를 체크 */
void busy0(void)
{
BUSY = 1; // P0.7 초기 설정
CS1 = 1;
RW = 1;
DI = 0;
// 비지 플래그 검사
do {
E = 1;
E = 0;
} while(BUSY); // LCD0 동작 중?
CS1 = 0; // LCD0 동작 불가능
}
/* LCD0 write */
void lcd0_wr(unsigned char send)
{
busy0();
P0 = send; // LCD0으로 코맨드 출력
CS1 = 1;
RW = 0;
DI = 0;
E = 1;
E = 0;
CS1 = 0;
}
/* LCD0 페이지 지정 */
void lcd0_page(unsigned char page)
{
page &= 0x07; // 0-7로 마스크
page |= 0xb8; // 페이지 명령 포맷을 만든다.
lcd0_wr(page); // 페이지 라이트
}
/* LCD0 어드레스 지정 */
void lcd0_address(unsigned char address)
{
address &= 0x3f; // 0-63 어드레스 마스크
address |= 0x40; // 어드레스 명령 포맷
lcd0_wr(address); // 어드레스 라이트
}
/* LCD1 비지 플래그를 체크 */
void busy1(void)
{
BUSY = 1; // P1.7 초기 설정
CS2 = 1;
RW = 1;
DI = 0;
// 비지 플래그 검사
do {
E = 1;
E = 0;
} while(BUSY); // LCD0 동작 중?
CS2 = 0; // LCD0 동작 불가능
}
/* LCD1 write */
void lcd1_wr(unsigned char send)
{
busy1();
P0 = send; // LCD1로 코맨드 출력
CS2 = 1;
RW = 0;
DI = 0;
E = 1;
E = 0;
CS2 = 0;
}
/* LCD1 페이지 지정 */
void lcd1_page(unsigned char page)
{
page &= 0x07; // 0-7로 마스크
page |= 0xb8; // 페이지 명령 포맷을 만든다.
lcd1_wr(page); // 페이지 라이트
}
/* LCD1 어드레스 지정 */
void lcd1_address(unsigned char address)
{
address &= 0x3f; // 0-63 어드레스 마스크
address |= 0x40; // 어드레스 명령 포맷
lcd1_wr(address); // 어드레스 라이트
}
/* LCD0으로 폰트 출력 */
void font0(unsigned char font)
{
busy0(); // 비지 플래그 체크
P0 = font; // 폰트 출력
CS1 = 1;
RW = 0;
DI = 1;
E = 1;
E = 0;
CS1 = 0;
}
/* LCD1로 폰트 출력 */
void font1(unsigned char font)
{
busy1(); // 비지 플래그 체크
P0 = font; // 폰트 출력
CS2 = 1;
RW = 0;
DI = 1;
E = 1;
E = 0;
CS2 = 0;
}
/* LCD0을 모드 클리어 */
void lcd0_clear(void)
{
unsigned char i,j;
for(j=0; j<8; j++){
// 0-7 페이지
lcd0_page(j);
lcd0_address(0x00); // 어드레스 0으로 셋
// 어드레스 0-63까지 폰트 0x00을 출력
for(i=0; i<64; i++) font0(0x00); // 폰트 0을 출력
}
}
/* LCD1을 모드 클리어 */
void lcd1_clear(void)
{
unsigned char i,j;
for(j=0; j<8; j++){
/* 0-7 페이지 */
lcd1_page(j);
lcd1_address(0x00); /* 어드레스 0으로 셋 */
/* 어드레스 0-63까지 폰트 0x00을 출력 */
for(i=0; i<64; i++) font1(0x00); /* 폰트 0을 출력 */
}
}
/* LCD0,1을 모두 클리어시킨다 */
void clear(void)
{
lcd0_clear(); /* LCD0 클리어 */
lcd1_clear(); /* LCD1 클리어 */
}
/* 페이지, 어드레스, 폰트 포인터를 받아서 LCD로 디스플레이 */
void display(unsigned char page, unsigned char address, unsigned char flag)
{
unsigned char i,font;
/*LCD0,LCD1 페이지 설정 */
lcd0_page(page);
lcd1_page(page);
/*LCD0 어드레스 설정 */
lcd0_address(address);
/* 64개의 폰트를 디스플레이 */
for(i=0; i < 64; i++){
if (flag == 0) font = M[i]; /* M[] 폰트를 리드 */
else font = M1[i]; /* M1[] 폰트를 리드 */
/* 어드레스가 64가 넘으면 LCD1로 디스플레이*/
if (address >= 64){
lcd1_address(address-64); /* LCD1 어드레스 설정 */
font1(font); /* LCD1로 폰트 출력 */
}
/* 어드레스가 64가 넘지 않으면 LCD0으로 디스플레이*/
else font0(font); /* LCD0로 폰트 출력 */
address++; /* 어드레스 +1 증가 */
}
}
/* 메인 프로그램 */
void main( void )
{
CS1 = CS2 = E = 0; // CS1, CS2, E 초기 설정
lcd0_wr(0x3f); // LCD0 ON
lcd1_wr(0x3f); // LCD1 ON
lcd0_wr(0xc0); // LCD0 start line
lcd1_wr(0xc0); // LCD1 start line
/* LCD 전 화면을 클리어시킨다 */
clear();
/* 페이지 3, 어드레스 32, 상위 64x8 문자 폰트 배열을 디스플레이 */
display(3, 32, 0);
/* 페이지 4, 어드레스 32, 하위 64x8 문자 폰트 배열을 디스플레이 */
display(4, 32, 1);
while(1); /* 무한 루프 */
}
busy 함수는 잘 작동안되는 경우가 많지요..속도의 차이때문에요....
시간에 마진을 좀 주는게 좋고요.. 약간 후진 lcd같은 경우는 초기화가 잘 안되서
초기화 작업을 두세번 해주는게 도움이 되요
올리신 자료만으로는 더 깊은 설명은 힘드네요
KS0107 계열은 모르겠으나
HD44780은문자를 쓸때 RW 1 RS0 으로 한다음 데이터값을 준다음
인에이블 신호를 만들고 정확히는 얼만지는 모르겠으나 얼마 이상의 딜레이를 주어야 합니다
넘어가는 타이밍도 한번 보시길바랍니다
저도 허접이라서 ...
제생각도 타이밍 ㅋ_ㅋ 비지비트 체크도 괜찮은 방법이지만 안되신다면 딜레이함수로 구현하는것두 괜찮을꺼 같네요 ㅋ