티스토리 뷰
이번 프로젝트에서 사용하는 LCD 모듈은 WaveShare사에서 만든 3.3V용 파란색 LCD모듈이다. 제조사 홈페이지에서 해당 모듈을 검색하면 LCD모듈에 사용된 드라이버 칩이 SUNPLUS사의 SPLC780D을 사용하였다고 나온다.
1602 LCD는 히타치사에서 만든 HD44780 드라이버 칩을 사용하는것이 거의 표준처럼 되어 있다. 따라서 SPLC780D도 HD44780과 호환 제품이다.
인터넷에서 HD44780 데이터쉬트 문서를 검색하면 다운 받을수 있다.
문서를 다운 받았으면 서너번 정도 대충 읽어본다. SPLC780D 문서는 48페이지로 되어 있는데 이것 저것 빼고 나면 실제로 드라이버 코드를 만드는데 필요한 정보는 몇페이지 되지 않으므로 크게 부담없이 읽어 볼 수 있다.
문서 분석이 어느정도 되었으면 드라이버 코드를 하나씩 구현해 보도록 하겠다.
우선, AVR과 LCD 모듈을 연결하기 위한 포트 설정부터 한다. LCD제어를 위한 시그널에 대한 핀정의를 회로에 맞게 작성한다.
그리고 보드의 회로 구성에 따라 달라질수 있는 부분에 대한 코드를 만든다. 혹시 회로를 다르게 구현하게되면 이 부분만 회로에 맞게 수정하면 된다.
AVR의 포트를 이용하여 LCD를 제어하는 부분은 모두 inline 함수로 정의하였다. 겉으로 보이는것은 일반 함수와 같지만 실제 동작은 매크로처럼 동작된다. 이렇게 하는 이유는 코드의 가독성을 높이면서 성능 저하를 감소할 수 있기 때문이다.
LCD를 제어하기 위한 명령어는 다음과 같다.
위의 명령어에 대한 내용을 헤더파일에 다음과 같이 작성한다.
그리고, 몇가지 코드에 필요한 내용과 LCD 드라이버 코드의 API 함수 prototype을 선언해 준다.
데이터쉬트 문서에 CPU에서 LCD를 제어하는 방법에 대한 타이밍도를 설명하고 있다.
LCD칩의 내부에는 Data register와 Instruction Register가 있는데, RS 시그널로 이를 선택할 수 있다. 위의 타이밍도를 보면 알겠지만 Instruction register에 접근할때에는 RS신호를 low상태로 만들고, Data register에 접근하기 위해서 RS 신호를 high로 만든다.
이들 레지스터에 값을 쓸때는 R/W 신호를 low로 만들어야 하고, 레지스터에서 값을 읽을때는 R/W 신호를 high로 만들어야 한다.
레지스터에 쓴값을 LCD 칩에 적용시키거나, LCD 내부의 상태를 읽어 오기 위해서는 E 신호를 low에서 high로 토글시켜 주어야 한다.
위의 타이밍도를 보면 레지스터에 값을 쓴 후 E 신호를 이용하여 동작을 수행시키면 LCD 칩 내부에서 이를 처리하기 위한 시간이 필요하다. 이를 확인하기 위하여 RS를 low로 만들고 R/W를 high로 만들면 Busy flag값을 읽어 볼수 있다. Busy flag 값이 1이면 LCD칩에서는 CPU의 명령을 처리하고 있음을 나타내므로 이 비트값이 0이될때까지 기다려 주어야 한다.
즉, 이 말은 LCD 레지스터에 값을 쓰기 전에 Busy flag 상태를 체크하는 동작이 필요하다는것과 같다. 이를 위하여 다음과 같은 코드를 만들었다.
lcd_wait_busy() 함수는 Busy flag 값을 체크하는 기능도 수행하면서 현재 address counter값을 읽어 오는 기능도 수행한다. Address counter값을 이용하여 줄바꿈 기능을 수행할수 있게 된다.
Instruction register나 data register에 값을 쓰기 위한 코드는 다음과 같다.
이렇게 LCD register에 대한 read/write 코드를 완성하였으므로, 프로그램이 처음 시작될때 초기화하는 과정을 만들어 보겠다.
문서에 LCD의 초기화 과정에 대한 설명이 다음과 같이 나와있다.
위의 초기화 과정을 코드로 구현하면 다음과 같다.
코드의 마지막줄은 문서에 나오는 초기화 과정에는 없지만 초기화 과정이 정상적으로 수행되었는지 확인하기 위하여 추가한 코드이다.
이렇게하여 HD44780 호환 LCD 모듈의 초기화 드라이버 코드가 완성되었다. 여기까지 구현한 후 정상적으로 동작되는지 확인해 보도록 한다.
정상적으로 수행되면 다음과 같은 화면을 볼 수 있다.
윗줄 첫번째 글자의 위치에서 커서가 보이고 깜빡이는 동작을 수행하면 초기화 과정이 정상적으로 수행되었다고 볼 수 있다.
이제 실제로 글씨가 제대로 출력되는지 확인해 보도록 하겠다.
먼저 앞의 초기화 코드 마지막줄에서 CURSOR_ON과 BLINK_ON을 삭제한다. LCD의 경우 커서와 블링크 기능이 그닥 필요하지 않기 때문이다. 만약 사용자의 입력이 필요한 경우에는 이 옵션을 켜두는것이 좋을것이다.
한 글자만 출력하기 위해서는 lcd_putc()를 사용하고, 문자열을 출력하는 경우에는 lcd_puts()를 사용한다. 특정 위치에서부터 출력이 필요한 경우 lcd_pos() 함수를 이용하여 시작 위치를 조정할 수 있다. Data register에 값을 쓰는 동작을 수행할 때 실제 글자가 나타나는 위치는 현재 설정되어 있는 data address counter가 가리키는 곳이 된다.
1602 LCD의 경우 두줄이 표시되는데 각각의 시작 주소는 다음 그림과 같다.
윗줄은 0x00부터 시작되고, 두번째 줄은 0x40부터 시작된다.
위의 코드를 만들어서 실행 시키면 다음과 같은 결과를 얻을 수 있다.
"Hello, LCD 1602"는 위줄의 첫번째칸에서부터 시작되었고, Cnt=xxx 는 두번째줄의 네번째칸에서부터 시작되는것을 볼 수 있다.
'프로젝트 > LCD1602' 카테고리의 다른 글
LCD1602 - ADC 출력 (2) | 2016.07.16 |
---|---|
LCD1602 드라이버 코드 - CGRAM (1) | 2016.07.15 |
LCD1602 드라이버 코드 - 4비트 모드(2) (0) | 2016.07.14 |
LCD1602 드라이버 코드 - 4비트 모드 (4) | 2016.07.14 |
LCD1602 - 회로 구성 (0) | 2016.07.10 |