[Atmega128A] LCD 활용

Wook's Notepad·2022년 2월 20일
0

Atmega128a를 활용해 이것저것 활용해보며 작품을 하나 만들어보려고 생각중입니다.

이전에 아두이노로 해보았던 것들이 atmega를 활용하니 상대적으로 까다롭고 귀찮은게 많네요... 역시 아두이노는 초보자에겐 정말 좋은 kit 이라는 생각이 다시 한번 들었습니다 ..!

아직 매우 기초적인 수준이라 우선은 간략한 개념 및 활용방법 소개와 제가 학교수업에서 만들었던 프로젝트들을 소개하는 포스팅이 주가 될 것 같습니다

[출처 / https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=ga1267&logNo=220046182859 ]

우선 회로도입니다.
*저항위에 화살표가 있는건 가변저항입니다 (lcd를 활용할땐 보통 10k옴 가변저항을 활용하시면 됩니다)

LCD 기판상에서 1-3번 핀은 전원, 4-6번은 제어, 7-14번은 데이터, 15-16은 백라이트 제어에 각각 할당된 핀들입니다.

그 다음 코드입니다.

#ifndef LCD_H_
#define LCD_H_
#define F_CPU 16000000UL
#include <avr/io.h>

#include <util/delay.h>

#define sbi(x, y) (x |= (1 << y))  // x의 y 비트를 설정(1)
#define cbi(x, y) (x &= ~(1 << y)) // x의 y 비트를 클리어(0)

// CON 포트는 포트 C와 연결됨을 정의
#define LCD_CON      PORTC
// DATA 포트는 포트 A와 연결됨을 정의
#define LCD_DATA     PORTA
// DATA 포트의 출력 방향 설정 매크로를 정의
#define LCD_DATA_DIR DDRA
// DATA 포트의 입력 방향 설정 매크로를 정의
#define LCD_DATA_IN  PINA
// RS 신호의 비트 번호 정의
#define LCD_RS   0
// RW 신호의 비트 번호 정의
#define LCD_RW   1
// E 신호의 비트 번호 정의
#define LCD_E    2

// 텍스트 LCD로 부터 상태(명령)를 읽는 함수
unsigned char LCD_rCommand(void){
	unsigned char temp=1;
	
	LCD_DATA_DIR = 0X00;
	
	cbi(LCD_CON, LCD_RS); // 0번 비트 클리어, RS = 0, 명령
	sbi(LCD_CON, LCD_RW); // 1번 비트 설정, RW = 1, 읽기
	sbi(LCD_CON, LCD_E);  // 2번 비트 설정, E = 1
	_delay_us(1);
	
	temp = LCD_DATA_IN;      // 명령 읽기
	_delay_us(1);
	
	cbi(LCD_CON, LCD_E);  // 명령 읽기 동작 끝
	
	LCD_DATA_DIR = 0XFF;
	_delay_us(1);
	
	return temp;
}

// 텍스트 LCD의 비지 플래그 상태를 확인하는 함수
char LCD_BusyCheck(unsigned char temp){
	if(temp & 0x80)          return 1;
	else            return 0;
}

// 텍스트 LCD에 명령을 출력하는 함수 - 단, 비지플래그 체크하지 않음
void LCD_wCommand(char cmd){
	cbi(LCD_CON, LCD_RS); // 0번 비트 클리어, RS = 0, 명령
	cbi(LCD_CON, LCD_RW); // 1번 비트 클리어, RW = 0, 쓰기
	sbi(LCD_CON, LCD_E);  // 2번 비트 설정, E = 1
	
	LCD_DATA = cmd;          // 명령 출력
	_delay_us(1);
	cbi(LCD_CON, LCD_E);  // 명령 쓰기 동작 끝
	
	_delay_us(1);
}
void LCD_setcursor(char col, char row)
{
	LCD_wBCommand(0x80 | col * 0x40 + row);
}
// 텍스트 LCD에 명령을 출력하는 함수 - 단, 비지플래그 체크함
void LCD_wBCommand(char cmd){
	while(LCD_BusyCheck(LCD_rCommand()))
	_delay_us(1);
	cbi(LCD_CON, LCD_RS); // 0번 비트 클리어, RS = 0, 명령
	cbi(LCD_CON, LCD_RW); // 1번 비트 클리어, RW = 0, 쓰기
	sbi(LCD_CON, LCD_E);  // 2번 비트 설정, E = 1
	
	LCD_DATA = cmd;          // 명령 출력
	_delay_us(1);
	cbi(LCD_CON, LCD_E);  // 명령 쓰기 동작 끝
	
	_delay_us(1);
}

// 텍스트 LCD를 초기화하는 함수
void LCD_Init(void){
	_delay_ms(100);
	// 비지 플래그를 체크하지 않는 Function Set
	LCD_wCommand(0x38);
	_delay_ms(10);
	// 비지 플래그를 체크하지 않는 Function Set
	LCD_wCommand(0x38);
	_delay_us(200);
	// 비지 플래그를 체크하지 않는 Function Set
	LCD_wCommand(0x38);
	_delay_us(200);
	
	// 비지 플래그를 체크하는 Function Set
	LCD_wBCommand(0x38);
	// 비지 플래그를 체크하는 Display On/Off Control
	LCD_wBCommand(0x0c);
	// 비지 플래그를 체크하는 Clear Display
	LCD_wBCommand(0x01);
}

// 텍스트 LCD에 1바이트 데이터를 출력하는 함수
void LCD_wData(char dat){
	while(LCD_BusyCheck(LCD_rCommand()))
	_delay_us(1);
	
	sbi(LCD_CON, LCD_RS); // 0번 비트 설정, RS = 1, 데이터
	cbi(LCD_CON, LCD_RW); // 1번 비트 클리어, RW = 0, 쓰기
	sbi(LCD_CON, LCD_E); // 2번 비트 설정, E = 1
	
	LCD_DATA = dat;       // 데이터 출력
	_delay_us(1);
	cbi(LCD_CON, LCD_E);  // 데이터 쓰기 동작 끝
	
	_delay_us(1);
}

// 텍스트 LCD에 문자열을 출력하는 함수
void LCD_wString(char *str){
	while(*str)
	LCD_wData(*str++);
}

#endif /* LCD_H_ */

위 코드는 main 코드에 추가해도 별 문제는 없지만, 코드 자체가 길고 복잡하다보니 아무래도 헤더파일로 추가하면 나중에 간단하게 불러오기도 편하고 좋습니다.

#define F_CPU 16000000L
#include <avr/io.h>
#include <util/delay.h>

#include "lcd.h"

int main(void){
	DDRC = 0xFF;
	DDRA = 0xFF;

	LCD_Init();
	LCD_wBCommand(0x80 | 0x00);
	LCD_wString("Atmega128A");
	LCD_wBCommand(0x80 | 0x40);
	LCD_wString("Hello World!");
	while (1){}
    
	return 0;
} 

LCD 상에 특정 문구를 출력하기 위한 main 코드입니다.

*[출처 / https://blog.naver.com/kim-nan-hee/222011623301]

LCD는 구조적으로 각 칸들이 모여 마치 좌표계와 같이 구성되어 컨트롤되는데, 헤더파일 안에서 선언된 함수를 통해 LCD의 좌표계 상에서 커서를 설정하여 문자를 출력하게 됩니다.

아두이노를 이용해 공부할때부터 저는 구글링을 통해 오픈소스를 긁어와 이해하고 적용하는 방식이 초보자들이 실력을 키우는데 너무 좋은 방법이라고 생각합니다. 모두들 주저하지 말고 한글, 영어로 구글링해 오픈소스를 보고, 해석하며 실력을 많이 늘리시면 좋을 것 같습니다!

0개의 댓글