임베디드 리눅스 -TextLCD
실습13 텍스트 LCD 제어 프로그램
* 실습목표
mmap 함수를 이용하여 텍스트 LCD 디바이스를 제어한다.
텍스트 LCD 응용 프로그램으로는 자신의 학번과 이름을 텍스트 LCD에 디스플레이 하고, 좌우로 시프트되는 프로그램을 작성한다.
* 기초지식
텍스트LCD는 DR(Data Register)과 IR(Instruction Register)을 이용하여 LCD에 글자를 표시하고 있다. 그러나 타겟보드의 메인 CPU는 DR/IR 레지스터를 직접 액세스하지 못하고, 텍스트 LCD모듈에서 인터페이스 나온11개 비트(D0~D7,RS,R/W,E)를 이용하여 제어해야한다.
텍스트LCD는 모듈의 물리번지는 0x1070 0000'이므로 mmap함수를 이용한 응용프로그램은 이 번지를 사용하여 TextLcd를 사용할 수 있다.
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <asm/fcntl.h>
#include <stdio.h>
#define ADDRESSOFTEXTLCD 0x10700000
void setcommand(unsigned short command);
void initialize_textlcd();
void setcommand(unsigned short command);
void writebyte(char ch);
void initialize_textlcd();
void write_string(char *str,int length);
int function_set(int rows, int nfonts);
int display_control(int display_enable, int cursor_enable,int nblink);
int cusror_shit(int set_screen, int set_rightshit);
int entry_mode_set(int increase, int nshift);
int return_home();
int clear_display();
int set_ddram_address(int pos);
unsigned int *pTextlcd;
//텍스트 LCD 프로그램에서 사용하며 각종 헤더를 첨가 텍스트LCD 하드웨어 주소를 설정
//전역변수 및 사용자들이 사용해야할 함수들 선언
int main(int argc, char **argv)
{
//입력하는 매개 변수의 숫자를 이용하여 매개변수가 없을 때에는 텍스트LCD의 첫 번째줄과 두 번째 줄에
//쓸 문자열을 선언하고있다.
int fd;
int i, len1=7, len2=12;
char buf1[ 100] = "Hello!";
char buf2[ 100] = "EmbededWorld";
if(argc == 2) {
len1= strlen(argv[1]);
len2= 0;
strcpy(buf1,argv[1]);
}else if(argc >=3){
len1 = strlen(argv[1]);
len2 = strlen(argv[2]);
strcpy(buf1,argv[1]);
strcpy(buf2,argv[2]);
}
if((fd=open("/dev/mem", O_RDWR|O_SYNC)) < 0){
perror("mem open fail\n");
exit(1);
}
//mmap을 이용하여 텍스트 LCD의 하드웨어 어드레스를 응용 프로그램에서 사용할 가상주소를 얻기
pTextlcd = mmap(NULL, 4, PROT_WRITE, MAP_SHARED, fd, ADDRESSOFTEXTLCD);
if((int)pTextlcd < 0){
pTextlcd = NULL;
close(fd);
printf("mmap error\n");
return -1;
}
initialize_textlcd(); //텍스트LCD 초기화하기
//writebyte함수를 이용하여 첫 번째 줄에 buf1에 들어있는 문자열을 쓴다.
//set_ddramm_address 함수를 이용하여 텍스트LCD커서를 두 번째 줄의 처음으로 바꾸고 다시 buf2 //에있는 문자열을 쓴다
for(i= 0; i<len1; i++) writebyte(buf1[i]);
for(i=0; i<20; i++) cursor_shit(1,1);
clear_display();
set_ddram_address(0x40);
usleep(2000000);
for(i=0; i<(19-len2); i++) cursor_shit(0,1);
for(i=0; i<len2; i++) writebyte(buf2[i]);
for(i=0; i<20; i++) cursor_shit(1,0);
clear_display();
return_home();
munmap(pTextlcd, 4); //munmap을 사용하여 mmap을 이용하여 매핑한 메모리를 해제
close(fd); //close로 fd반환
}
void setcommand(unsigned short command)
{
//명령어를 받아 텍스트 LCD의 명령값을 전달한다. 전달하는 방법은 XScale의 데이터 라인 0dptj 10비트를 아래//의 텍스트 LCD의 write 타이밍도를 보고 조작하여 전달한다.
command &= 0x00FF;
*pTextlcd = command | 0x0000;
*pTextlcd = command|0x0400;
*pTextlcd = command | 0x0000;
usleep(50);
}
void writebyte(char ch)
{
//제어 명령표의 'Data Write to GG RAM 혹은 DD RAM‘ 을 사용하기 위해 만들었다.
//이 함수는 텍스트 LCD에 직접 글자를 쓰는 함수이다.
unsigned short data;
data = ch & 0x00FF;
*pTextlcd = data|0x100;
*pTextlcd = data|0x500;
*pTextlcd = data|0x100;
usleep(50);
}
int clear_display(){
//제어명령표의 Clear Display(0x1)을 설정한 후 setcommand()함수로 명령어를 전달하여 텍스트 LCD의 화면을 //지우고 커서를 home에 위치시킨다.
unsigned short command = 0x01;
setcommand(command);
usleep(2000);
return 1;
}
int return_home(){
//제어 명령표의 Return Home(0x02)을 설정한 후 setcommand()함수로 명령어를 전달하여 커서를 home에위치
unsigned short command = 0x02;
setcommand(command);
usleep(2000);
return 1;
}
int entry_mode_set(int increase, int nshift){
//제어 명령표의 Entry Mode Set(0x04)을 설정하고 인수로 받은 increase를 데이터의 비트에 대응시키고 //setcommand 함수를 사용하여 텍스트LCD모듈에 전달한다.
unsigned short command = 0x04;
command = increase?(command | 0x2):command;
command = nshift?(command | 0x1):command;
setcommand(command);
return 1;
}
int display_control(int display_enable, int cursor_enable, int nblink){
//인수로 받은 값에 따라 화면을 On/Off하거나 커서를 깜빡이는 함수
unsigned short command = 0x08;
command = display_enable?(command | 0x04) : command;
command = cursor_enable?(command | 0x02) : command;
command = nblink?(command | 0x01) : command;
setcommand(command);
return 1;
}
int cursor_shit(int set_screen, int set_rightshit){
//인수로 받은 값에 따라 화면 또는 커서를 왼쪽 오른쪽으로 시프트 하는 함수
unsigned short command = 0x10;
command = set_screen?(command | 0x08) : command;
command = set_rightshit?(command | 0x04) : command;
setcommand(command);
return 1;
}
// 텍스트 LCD를 초기화를 구현하는 함수들
int function_set(int rows, int nfonts){
unsigned short command = 0x30;
if(rows ==2) command |= 0x08;
else if(rows ==1) command &= 0xf7;
else return -1;
command = nfonts?(command | 0x04) : command;
setcommand(command);
return 1;
}
int set_ddram_address(int pos){
unsigned short command = 0x80;
command += pos;
setcommand(command);
return 1;
}
void initialize_textlcd(){
function_set(2,0);
display_control(1,0,0);
clear_display();
return_home();
entry_mode_set(1,0);
usleep(2000);
}