Character LCD 실습

Download Report

Transcript Character LCD 실습

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