1 시스템및센서네트워크연구실 마이크로콘트롤러응용설계 - 2 character LCD
2 시스템및센서네트워크연구실 ATmega128
3 시스템및센서네트워크연구실 LED sink / switch pullup 회로 PC0 +5V PC1 PC7 ….. PD2 5V 10K 104 (0.1uF) 470
4 시스템및센서네트워크연구실
5 시스템및센서네트워크연구실 16*2 character LCD 5V 단일전원으로 구동 5*8 또는 5*11 도트의 폰트로 문자를 표시 인터페이스가 표준화되어 있기 때문에 uC 에 쉽게 연결 가능 8 비트 또는 4 비트 데이터 버스 방식으로 구동 CGRAM (Character Generator RAM), CGROM (Character Generator ROM), DDRAM (Data Display RAM) 을 내장하고 있음
6 시스템및센서네트워크연구실 핀 정의 V0 VSS +5V VDD PC0 PC1 PC2 PC4 PC5 PC6 PC7 RS R/W E DB4 DB5 DB6 DB7 +5V LEDA LEDK #3 #2 #1 LCD 밝기 조절
7 시스템및센서네트워크연구실 LCD 기본 동작 레지스터 LCD 에는 8 비트의 인스트럭션 레지스터 (IR) 과 데이터 레지스터 (DR) 이 있음 IR : DDRAM 과 CGRAM 에 대한 어드레스 설정, 메모리 클리어, display on/off, 커서 이동 등에 대한 명령어 코드를 가짐 DR : DDRAM 과 CGRAM 에 써넣은 데이터나 읽은 데이터를 일시적으로 저장하는 역할 RS 와 R/W 에 의하여 제어됨 RS R/W 0 0 IR 쓰기 동작 0 1 busy flag 와 address counter (AC) 읽기 1 0 DR 쓰기 동작 : DR -> DDRAM, CGRAM 1 1 DR 읽기 동작 : DR <- DDRAM, CGRAM
8 시스템및센서네트워크연구실 Busy Flag (BF) LCD 모듈이 다음 명령을 받을 수 있는 지를 나타냄 BF = 1 : LCD 는 내부 동작 수행 중이므로 다음 명령 받을 수 없음 BF = 0 : 다음 명령을 받을 수 있음 Address Counter (AC) DDRAM 이나 CGRAM 의 어드레스를 지정할 때 사용 IR 에 어드레스 셋 명령어를 쓰면 IR 에서 AC 로 어드레스 정보가 전송됨 DDRAM 과 CGRAM 은 명령어에 의하여 선택 DDRAM 이나 CGRAM 에 디스플레이 데이터를 쓰면 AC 는 자동으로 +1 또는 -1 이 됨
9 시스템및센서네트워크연구실 DDRAM (Display Data RAM) LCD 화면 (16*2) 에 출력되는 문자를 저장하는 RAM 8 비트 문자 데이터를 각 행별로 40 문자씩 저장 1 행은 0x00 – 0x27, 2 행은 0x40 – 0x67 의 어드레스를 가짐 각 행은 40 문자씩 저장하지만, LCD 에는 16 문자씩 동시에 출력 가능 따라서, 쉬프트 동작을 이용하여 DDRAM 의 해당 어드레스를 LCD 에 출 력해야 함 초기 상태 0x00 – 0x0F 0x40 – 0x4F 0x21 출력하려면, 전체 행을 왼쪽 2 문자 쉬프트 0x02-0x0F, 0x20, 0x21 0x42-0x4F, 0x50, 0x51
10 시스템및센서네트워크연구실 CGROM (Character Generator ROM) LCD 에 사전에 정의되어 있는 8 비트 문자 코드 ASCII 코드로 정의되어 있음 예 ) a : , A : 프로그램에서는 문자를 그대로 이용할 수 있 음 LCD 에 표시할 문자의 코드값만 DDRAM 에 써주 면, LCD 는 문자코드에 해당하는 문자 패턴을 출 력 CGRAM (Character Generator RAM) 사용자가 정의하는 문자의 패턴을 저장하기 위한 RAM
11 시스템및센서네트워크연구실 LCD 명령어 LCD 제어 명령어
12 시스템및센서네트워크연구실 Clear display LCD 화면 clear 후 커서 home(1 행 1 열 ) 으로 이동, DDRAM 의 AC (address counter) 0 으로 셋 Return home 커서 home 으로 이동, DDRAM 의 AC 0 으로 셋 Entry mode set 커서의 움직이는 방향 설정 및 디스플레이의 쉬프트 가능하게 함 커서 이동 I/D=1 & S=0 : 커서 우측 이동 방향 설정 I/D=0 & S=0 : 커서 좌측 이동 방향 설정 디스플레이 쉬프트 I/D=1 & S=1 : display 좌 쉬프트 가능 설정 I/D=0 & S=1 : display 우 쉬프트 가능 설정 S=0 : display 쉬프트 불가
13 시스템및센서네트워크연구실 Display On/Off control Display(D), cursor(C), blinking of cursor(B) 설정 D=1 : LCD 전체가 on 되어 글자 표시 C=1 : 커서가 나타남 B=1 : 커서의 깜박임 동작 Cursor or display shift 커서 이동 및 display 쉬프트 조정 S/C R/L 0 0 : cursor 위치 좌로 이동, AC 는 : cursor 위치 우로 이동, AC 는 : display 와 cursor 좌로 이동 1 1 : display 와 cursor 우로 이동
14 시스템및센서네트워크연구실 Function set DL : interface data length 설정 DL=1 – 8 비트, DL=0 – 4 비트 DL=0 일 때 DB7-DB4 가 사용되며, 상위 4 비트, 하위 4 비트 순서로 전 송 N : display line 수 설정 N=0 – 1 라인 표시, N=1 – 2 라인 표시 F : display font type 설정 F=0 – 5*11 도트 (N=1 일 때만 사용 가능 ), F=1 – 5*8 도트 Set CGRAM address CGRAM 의 address 설정 Address 설정 후 CGRAM 의 데이터 읽고 쓸 수 있음
15 시스템및센서네트워크연구실 Set DDRAM address DDRAM 의 어드레스 설정 Address 설정 후 DDRAM 의 데이터 읽고 쓸 수 있음 Read busy flag and address counter BF : 내부 동작 상태를 알 수 있는 비지 플래그 BF = 1 : 내부 동작이 진행 중이라 명령을 받아들일 수 없음 BF = 0 : 명령을 받아들일 수 있음 AC : address counter 의 값을 읽을 수 있음 Write data to RAM DDRAM 또는 CGRAM 에 데이터를 쓸 수 있음 Read data from RAM DDRAM 또는 CGRAM 으로부터 데이터를 읽을 수 있음
16 시스템및센서네트워크연구실 LCD 프로그램 LCD 함수 정의 void LCD_init(void) : LCD 초기화 함수 사양에서 정의된 시간만큼 안정화 동작을 가짐 초기화 명령어 세팅 void Command(unsigned char) : instruction 쓰기 함수 RS=0 -> RW=0 -> delay -> E(enable signal)=1 -> delay -> E=0 상위 4 비트, 하위 4 비트 순으로 수행 void Data(unsigned char) : 데이터 쓰기 함수 RS=1 -> RW=0 -> delay -> E=1 -> delay -> E=0 상위 4 비트, 하위 4 비트 순으로 수행 void Busy(void) : Busy Flag Check BF 를 체크하지 않고 일정 시간 지연 void LCD_String(char flash *) : 문자열 출력 함수
17 시스템및센서네트워크연구실 // LCD 초기화 함수 void LCD_init(void) { DDRC = 0xFF;// 포트 C 출력 설정 PORTC &= 0xFB;//E = 0; // 충분한 지연시간을 통한 안정화 과정 delay_ms(15); Command(0x20);// D5=1 delay_ms(5); Command(0x20);// D5=1 delay_us(100); Command(0x20);// D5=1 // 초기화 과정 Command(0x28);// function set Command(0x06);// entry mode set Command(0x01);// all clear Command(0x0c);// display on } // 인스트럭션 쓰기 함수 void Command(unsigned char byte) { Busy(); // 인스트럭션 상위 바이트 PORTC = (byte & 0xF0);// 데이터 PORTC &= 0xFE;// RS = 0; PORTC &= 0xFD;// RW = 0; delay_us(1); PORTC |= 0x04;// E = 1; delay_us(1); PORTC &= 0xFB;// E = 0; // 인스트럭션 하위 바이트 PORTC = ((byte<<4) & 0xF0);// 데이터 PORTC &= 0xFE;// RS = 0; PORTC &= 0xFD;// RW = 0; delay_us(1); PORTC |= 0x04;// E = 1; delay_us(1); PORTC &= 0xFB;// E = 0; }
18 시스템및센서네트워크연구실 // 데이터 쓰기 함수 void Data(unsigned char byte) { Busy(); // 데이터 상위 바이트 PORTC = (byte & 0xF0);// 데이터 PORTC |= 0x01;//RS = 1; PORTC &= 0xFD;//RW = 0; delay_us(1); PORTC |= 0x04;//E = 1; delay_us(1); PORTC &= 0xFB;//E = 0; // 데이터 하위 바이트 PORTC = ((byte<<4) & 0xF0); // 데이터 PORTC |= 0x01;//RS = 1; PORTC &= 0xFD;//RW = 0; delay_us(1); PORTC |= 0x04;//E = 1; delay_us(1); PORTC &= 0xFB;//E = 0; } // Busy Flag Check -> 일반적인 BF 를 체크하는 것이 아니라 // 일정한 시간 지연을 이용한다. void Busy(void) { delay_ms(2); } // 문자열 출력 함수 void LCD_String(char flash str[]) { char flash *pStr=0; pStr = str; while(*pStr) Data(*pStr++); } // char flash : pointer declaration for program memory // char eeprom : pointer declaration for EEPROM
19 시스템및센서네트워크연구실 실습 1 // Hello!! // Atmel ATmega128 출력 #include #define LINE20xC0// 2nd Line Move #define HOME0x02// Cursor Home void LCD_init(void); void LCD_String(char flash str[]); void Busy(void); void Command(unsigned char); void Data(unsigned char); void main(void) { LCD_init(); Command(HOME); LCD_String("Hello!!");// 첫번째 라인에 출력 Command(LINE2); LCD_String("Atmel ATmega128");// 두번째 라인에 출력 while(1); } // 앞에 5 개 함수 원형 추가
20 시스템및센서네트워크연구실 실습 2 // 두 라인에 문자열 출력 -> 1 초간 LCD on -> 1 초간 LCD off -> 1 초간 LCD on -> 1 초 간격으로 16 번 오른쪽으로 이동 #include #define LINE20xC0// 2nd Line Move #define HOME0x02// Cursor Home #define RSHIFT0x1C// Display Right Shift #define LSHIFT0x18// Display Left Shift #define DISPON0x0c // Display On #define DISPOFF0x08// Display Off void LCD_init(void); void LCD_String(char flash str[]); void Busy(void); void Command(unsigned char); void Data(unsigned char); void main(void) { int i; LCD_init(); while(1){ Command(HOME); LCD_String("Hello!!"); // 첫 번째 라인에 출력 Command(LINE2); LCD_String("Atmel ATmega128");// 두 번째 라인에 출력 delay_ms(1000);// 1 초 시간 지연 Command(DISPOFF);// Display Off delay_ms(1000);// 1 초 시간 지연 Command(DISPON); // Display On delay_ms(1000);// 1 초 시간 지연 // 16 번 오른쪽으로 쉬프트 for(i=0;i<16;i++) { Command(RSHIFT); delay_ms(1000); }
21 시스템및센서네트워크연구실 실습 3 // 첫번째 라인에 문자열 표시한 후 좌측으로 계속 이동시키는 프로그램 작성 // include, define, function 원형 선언 공통 void main(void) { LCD_init(); // 첫 번째 라인에 출력 Command(HOME); LCD_String("Hello!! -- Atmel ATmega128"); delay_ms(1000);// 1 초 시간 지연 while(1){ Command(LSHIFT); // Display Left Shift delay_ms(500);// 0.5 초 시간 지연 }
22 시스템및센서네트워크연구실 실습 4 // LCD 의 첫번째 라인에 Value : XX 표시 // SW1 을 누르면 1 감소, SW2 를 누르면 1 증가 (0-59 까지 출력 ) int num = 0; void main(void) { int N10=0, N1=0; DDRD = 0b ; // PD0, PD1 입력 설정 (SW1, SW2) EIMSK = 0b ;// 외부 인터럽트 0, 1 인에이블 EICRA = 0b ;// 외부 인터럽트 0, 1 하강 에지 SREG = 0b ;// 전역 인터럽트 인에이블 비트 셋 LCD_init(); while(1){ // while(1) : 무한 루프 Command(HOME); LCD_String(“Value : ”); N10 = num / 10;// 10 자리 추출 N1 = num % 10;// 1 자리 추출 Data(0x30 + N10);// 0x30 – ‘0’ 에 대한 ASCII 코드값 // 즉, 1 을 출력하려면 0x31 을 출력해야 함 Data(0x30 + N1); } // 외부 인터럽트 0 서비스 루틴 interrupt [EXT_INT0] void external_int0(void) { num++; if(num > 59) num = 0; delay_ms(1); } // 외부 인터럽트 1 서비스 루틴 interrupt [EXT_INT1] void external_int1(void) { num--; if(num < 0) num = 59; delay_ms(1); }
23 시스템및센서네트워크연구실 실습 5 // SW1 을 누르면, Computer 의 랜덤 숫자 출력, // SW2 를 누르면 User 의 랜덤 숫자 출력, 두 값을 비교하여 결과 출력 #include // 선언부에 stdlib.h 함수 추가 int num1=0, num2=0; void main(void) { DDRD = 0b ; // PD0, PD1 입력 설정 (SW1, SW2) EIMSK = 0b ;// 외부 인터럽트 0, 1 인에이블 EICRA = 0b ;// 외부 인터럽트 0, 1 하강 에지 SREG = 0b ;// 전역 인터럽트 인에이블 비트 셋 LCD_init(); while(1); // while(1) : 무한 루프 } // 외부 인터럽트 0 서비스 루틴 interrupt [EXT_INT0] void external_int0(void) { Command(HOME); num1 = (char) (rand() % 8); LCD_String(“Com : ”); Data(0x30 + num1); delay_ms(1); } // 외부 인터럽트 1 서비스 루틴 interrupt [EXT_INT1] void external_int1(void) { num2 = (char) (rand() % 8); LCD_String(“ User : ”); Data(0x30 + num2); Command(LINE2); if(mum1 > num2) LCD_String (“Com is win”); if(mum2 >= num1) LCD_String (“User is win”); }
24 시스템및센서네트워크연구실 실습 6 // LCD 를 이용한 간이시계 제작 int sec=0, minn=0, loc=0; void main(void) { int i, min10, min1, sec10, sec1; DDRD = 0b ; // PD0, PD1 입력 설정 (SW1, SW2) EIMSK = 0b ;// 외부 인터럽트 0, 1 인에이블 EICRA = 0b ;// 외부 인터럽트 0, 1 하강 에지 SREG = 0b ;// 전역 인터럽트 인에이블 비트 셋 LCD_init(); while(1){ // while(1) : 무한 루프 Command(HOME); LCD_String(“Time : ”); sec++; if(sec >= 60) { sec = 0; minn++; if(minn >= 60) minn = 0; } min10 = minn / 10;// 분의 10 자리 추출 min1 = minn % 10;// 분의 1 자리 추출 sec10 = sec / 10;// 초의 10 자리 추출 sec1 = sec % 10;// 초의 1 자리 추출 Data(0x30 + min10); Data(0x30 + min1); LCD_String(“: ”); Data(0x30 + sec10); Data(0x30 + sec1); delay_ms(1000);// 대략 1 초를 기다림 } // 외부 인터럽트 0 서비스 루틴 interrupt [EXT_INT0] void external_int0(void) { if(loc == 0) sec++; if(loc == 1) sec += 10; if(loc == 2) minn++; if(loc == 3) minn += 10; if(sec > 59) sec -= 60; if(minn > 59) minn -= 60; } // 외부 인터럽트 1 서비스 루틴 interrupt [EXT_INT1] void external_int1(void) { loc = (loc + 1) % 4; }