Text-LCD Device Control - Device driver Jo, Heeseung
M3 모듈에장착되어있는 Tedxt LCD 장치를제어하는 App 을개발 TextLCD 는영문자와숫자일본어, 특수문자를표현하는데사용되는디바이스 HBE-SM5-S4210 의 TextLCD 는 16 문자 *2 라인을 Display 할수있으며, 이 TextLCD 를제어하기위하여 FPGA 내부에 Controller 가설계되어있음 Text LCD 2
TextLCD Controller 는 LCD_Ctrl_Reg(Character LCD Control Register) 레지스터에의해제어 TextLCD Control Register 의데이터비트구조를나타낸표 Physical Address 0x0500_0010 CLCD_Ctrl_Reg BIT 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 Reserved CLCD_R S CLCD_R W CLCD_E Reset X X X X X 0 0 0 0 0 0 0 0 0 0 0 Bits Name Description 0 CLCD_D0 CLCD Data Bit 0 1 CLCD_D1 CLCD Data Bit 1 2 CLCD_D2 CLCD Data Bit 2 3 CLCD_D3 CLCD Data Bit 3 4 CLCD_D4 CLCD Data Bit 4 5 CLCD_D5 CLCD Data Bit 5 6 CLCD_D6 CLCD Data Bit 6 7 CLCD_D7 CLCD Data Bit 7 8 CLCD_E CLCD Enable Bit (Active High) 9 CLCD_RW CLCD Read/Write Control Bit ( 1 read, 0 Write) 10 CLCD_RS CLCD Data Instruction Register Set CLCD_D7 CLCD_D6 CLCD_D5 CLCD_D4 CLCD_D3 CLCD_D2 CLCD_D1 CLCD_D0 3
기능 제어제어명령 (D0 ~ D7) 신호실행시간 RS R/W 7 6 5 4 3 2 1 0 Clear Display 0 0 0 0 0 0 0 0 0 1 1.64ms Return Home 0 0 0 0 0 0 0 0 1 0 40us Entry Mode Set 0 0 0 0 0 0 0 1 I/D S 40us Display on/off control 0 0 0 0 0 0 1 D C S 40us Cursor or Display Shift 0 0 0 0 0 1 S/C R/L 0 0 40us Function Set 0 0 0 0 1 D/L N F 0 0 40us Set CG RAM Address 0 0 0 1 CG RAM Address 40us Set DD RAM Address 0 0 1 DD RAM Address 40us Read Busy Flag and Address Data Write to CG RAM or DD RAM Data Read to CG RAM or DD RAM 0 1 BF Address Counter 40us 1 0 Write Address 40us 1 1 Read Address 40us 4
각기능들의동작 Clear Display - 모든디스플레이상태를소거하고커서를 Home 위치로돌려놓음 Return Home - DD RAM 의내용은변경하지않고커서만을 Home 으로위치 Entry Mode SET - 데이터를 Read 하거나 Write 할경우에커서의위치를증가시킬것인가 (I/D=1) 감소시킬것인가 (I/D=0) 를결정 - 이때화면을이동할것인지 (S=1) 아닌지 (S=0) 를결정 Display On/Off Control - 화면표시를 On/Off 하거나 (D) - 커서를 On/Off 하거나커서를깜박이게할것인지 (B) 의여부를결정 Cursor or Display Shift - 화면 (S/C=1) 또는커서 (S/C=0) 이동 - 오른쪽 (R/L=1) 또는왼쪽 (R/L=0) 5
각기능들의동작 Function SET - 인터페이스에서데이터의길이를 8 비트 (DL=1) 또는 4 비트 (DL=0) 로지정 - 화면표시행수를 2 행 (N=1) 또는 1 행 (N=0) 으로지정 - 문자의폰트를 5 x 10 도트 (F=1) 또는 5 x 7 도트 (F=0) 로지정 - 전원인가후최초에는주로이명령을보내게되는데, LCD 모듈이리셋되려면약 50ms 가소요되므로충분히기다린후에이코드를전송 - 또한, 4 비트로인터페이스할경우에는 DB4~DB7 을사용하며, 상위 4 비트를먼저전송하고다음에하위 4 비트를전송 Set CG RAM Address - Character Generator RAM 의어드레스를지정 - 이후에송수신하는데이터는 CG RAM 의데이터 Set DD RAM Address - Display Data RAM 의어드레스를지정 - 이후에송수신하는데이터는 DD RAM 의데이터 6
각기능들의동작 Read Busy Flag & Address - LCD 모듈이내부동작중임을나타내는 Busy Flag(BF) 및어드레스카운터의내용을 read - LCD 모듈이각제어코드를실행하는데는일정한시간이필요 - FPGA 가 BF 를읽어 1 일경우에는기다리고, - 0 일경우다음제어코드를보내는방법을사용 7
DD RAM 표시될각문자의 ASCII 코드데이터가저장되어있는메모리 모두 80 개의번지가있는데, 화면의각행과열의위치에는고유한어드레스값이부여 행과행사이의어드레스가연속하여있지않으므로주의 아래표는표시문자의위치에대한 DD RAM 의어드레스 구분 1 2 3 4 13 14 15 16 Line1 0 1 2 3 0D 0E 0F 10 Line2 40 41 42 43 4D 4E 4F 50 8
TextLCD 모듈에서화면에표시할수있는문자중 ASCII 도형문자의종류와코드값 구분 00H 10H 20H 30H 40H 50H 60H 70H 80H 90H 0 0 @ P p 1! 1 A Q a q 2 2 B R b r 3 # 3 C S c s 4 $ 4 D T d t 5 % 5 E U e u 6 & 6 F V f v 7 사용자미사용 7 G W g w 8 정의영역 ( 8 H X h x 9 영역 ) 9 I Y I y A * : J Z j z B + ; K [ k { C, < L l D - = M } m ] E. > N ^ n F /? O _ o 미사용영역 9
Device driver 소스파일 TextLcd 리눅스디바이스드라이버는커널에포함 menuconfig 실행 - Device Drivers -> [*] Misc devices -> [*] Hanback Electronics M3(FPGA) Device Support -> <*>TEXT LCD linux-2.6.35-s4210/drivers/misc/hanback/textlcd.h 참조 linux-2.6.35-s4210/drivers/misc/hanback/textlcd.c 참조 10
textlcd_test.c 프로그램 root@ubuntu:/working/device_driver/textlcd_driver# vi textlcd_test.c 001: #include <stdio.h> 002: #include <stdlib.h> 003: #include <string.h> 004: #include <unistd.h> 005: #include <sys/types.h> 006: #include <sys/stat.h> 007: #include <fcntl.h> 008: #include <sys/ioctl.h> 009: 010: #define TEXTLCD_BASE 0xbc 011: #define TEXTLCD_COMMAND_SET _IOW(TEXTLCD_BASE,0,int) 012: #define TEXTLCD_FUNCTION_SET _IOW(TEXTLCD_BASE,1,int) 11
013: #define TEXTLCD_DISPLAY_CONTROL _IOW(TEXTLCD_BASE,2,int) 014: #define TEXTLCD_CURSOR_SHIFT _IOW(TEXTLCD_BASE,3,int) 015: #define TEXTLCD_ENTRY_MODE_SET _IOW(TEXTLCD_BASE,4,int) 016: #define TEXTLCD_RETURN_HOME _IOW(TEXTLCD_BASE,5,int) 017: #define TEXTLCD_CLEAR _IOW(TEXTLCD_BASE,6,int) 018: #define TEXTLCD_DD_ADDRESS _IOW(TEXTLCD_BASE,7,int) 019: #define TEXTLCD_WRITE_BYTE _IOW(TEXTLCD_BASE,8,int) 020: 021: struct strcommand_varible { 022: char rows; 023: char nfonts; 024: char display_enable; 025: char cursor_enable; 026: char nblink; 027: char set_screen; 028: char set_rightshit; 029: char increase; 030: char nshift; 031: char pos; 032: char command; 033: char strlength; 034: char buf[16]; 035: }; 12
037: int main(int argc, char **argv) 038: { 039: int i,dev; 040: char buf0[16] = "Welcome to the "; 041: char buf1[16] = "Embedded World!!"; 042: char buf2[16] = " HANBACK "; 043: char buf3[16] = " Electronics "; 044: 045: struct strcommand_varible strcommand; 046: strcommand.rows = 0; 047: strcommand.nfonts = 0; 048: strcommand.display_enable = 1; 049: strcommand.cursor_enable = 0; 050: strcommand.nblink = 0; 051: strcommand.set_screen = 0; 052: strcommand.set_rightshit = 1; 053: strcommand.increase = 1; 054: strcommand.nshift = 0; 055: strcommand.pos = 10; 056: strcommand.command = 1; 057: strcommand.strlength = 16; 13
059: dev = open("/dev/textlcd", O_WRONLY O_NDELAY ); 060: 061: if (dev!= -1) { 062: write(dev,buf0,16); 063: strcommand.pos = 40; 064: ioctl(dev,textlcd_dd_address,&strcommand,32); 065: write(dev,buf1,16); 066: sleep(1); 067: 068: ioctl(dev,textlcd_clear,&strcommand,32); 069: 070: strcommand.pos = 0; 071: ioctl(dev,textlcd_dd_address,&strcommand,32); 072: for(i=0;i<16;i++) { 073: strcommand.buf[0]=buf2[i]; 074: ioctl(dev,textlcd_write_byte,&strcommand,32); 075: } 14
076: 077: strcommand.pos = 40; 078: ioctl(dev,textlcd_dd_address,&strcommand,32); 079: for(i=0;i<16;i++) { 080: strcommand.buf[0]=buf3[i]; 081: ioctl(dev,textlcd_write_byte,&strcommand,32); 082: } 083: 084: if(argc>=2) { 085: sleep(1); 086: ioctl(dev,textlcd_clear,&strcommand,32); 087: write(dev,argv[1],strlen(argv[1])); 088: if(argc==3) { 089: strcommand.pos = 40; 090: ioctl(dev,textlcd_dd_address,&strcommand,32); 091: write(dev,argv[2],strlen(argv[2])); 092: } 093: } 094: 095: close(dev); 15
096: } else { 097: printf( "application : Device Open ERROR!\n"); 098: exit(1); 099: } 100: return 0; 101: } 16
Makefile 작성 CC = arm-linux-gcc CFLAGS = -DNO_DEBUG EXEC = textlcd_test OBJS = $(EXEC).o all: $(EXEC) $(EXEC): $(OBJS) $(CC) -o $@ $^ clean: rm -f $(OBJS) $(EXEC) 17
컴파일 make clean 하면먼저컴파일된실행예제파일삭제 make 명령어로컴파일실행 root@ubuntu:/working/device_driver/textlcd_driver# ls Makefile textlcd_test.c root@ubuntu:/working/device_driver/textlcd_driver# make clean;make ------------------ 다음과같은메시지가출력된다 ----------------- rm f textlcd_test.o textlcd_test arm-linux-gcc c DNO_DEBUG o textlcd_test.o textlcd_test.c arm-linux-gcc o textlcd_test textlcd_test.o root@ubuntu:/working/device_driver/textlcd_driver# ls Makefile textlcd_test textlcd_test.c textlcd_test.o 테스트 nfs/tftpboot/modem 으로 board 에전송후 board 에서실행 18