본문 바로가기
임베디드/Atmega328p

16x2 LCD D0, D1 -> C 포트에 꼽은 코드

by sj0020 2020. 11. 7.

D0, D1이 RX, TX에 꽂혀있어서 업로드가 잘 안되는 듯함. rx tx 뽑아서 업로드 하고 꽂고 다시 업로드 하면 될때도 있고. 이렇게 여러번 해도 안될때도 있고. 꼽힌채로 업로드 해서 될 때 도 있음

-> rx tx를 C 포트에 꼽으면 되는가? 해서 아래 코드를 시도해봄 

 

/*
 * LCD16x2.c
 *
 * Created: 2020-11-06 오후 2:00:16
 * Author : User
 */ 

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

#define RS	PORTB0
#define RW	PORTB1
#define E	PORTB2


int main(void)
{
	int r, c;
	char *string[] = {"1st line", "pin23"};
	lcdInit();
	
	for (r=0; r<2; r++){
		for(c =0; c<16; c++){
			if (string[r][c] == '\0'){
				if (r == 0){
					//DDRAM 주소 설정 및 커서 위치 이동
					LCD_command(0xC0);
				}
				break;
			}
			else{
				LCD_data_write(string[r][c]);
			}			
		}		
	}
    while (1);
    
}

void get_E_Strobe()
{
	volatile int i; //
	
	PORTB |= 1 << E; //E signal high
	for (i=0; i<10; i++);  //for문을 도는데에 최소 230가 걸림.시간을 delay 시켜주는 코드
	PORTB &= ~(1 << E);	// E signal low 
}

void wait_BusyFlag()
{
	volatile int i;
	unsigned char bf;
	
	//unsigned char c_data = 0b00000011 & data;
	//PORTC = c_data;
	//unsigned char d_data = 0b11111100 & data;
	//PORTD = d_data;
	
	//Busy Flag(LCD의D7)를 읽기 위해 PORTD를 입력핀으로 설정
	DDRD = 0x0;
	DDRC = 0x0;
	// RS -> low, RW -> high
	PORTB = (PORTB & ~(1 <<RS)) | 1 << RW;
	
	do{
		PORTB |= 1 << E;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
		for (i=0; i<10; i++);
		// bf가 1이면 내부 동작 진행중
		// bf가 0이면 내부 동작 완료. 다음 동작 명령 수령 가능.
		bf = PIND & (1 << PORTD7);
		PORTB &= ~(1 << E);
	} while(bf); //bf가 1이면 계속 처리... 0이 될때까지 동작		
}

// 명령 레지스터에 명령어 전달
void LCD_command(unsigned char data)
{
	wait_BusyFlag();	//bf가 0이 될때까지 대기
	DDRD = 0xFF;		//D포트를 출력으로 설정
	DDRC = 0xFF;
	unsigned char c_data = 0b00000011 & data;
	unsigned char d_data = 0b11111100 & data;
	PORTD = d_data;		// 명령어 전달. data 출력
	PORTC = c_data;
	// lcd command(화면 클리어~ DDRAM 주소 설정)을 위한 RS, RW 설정
	PORTB &= ~(1 << RS | 1 << RW);
	get_E_Strobe();
}

//data 레지스터에 데이터 기록
void LCD_data_write(unsigned char data)
{
	wait_BusyFlag();
	DDRD = 0xFF;
	DDRC = 0xFF;
	unsigned char c_data = 0b00000011 & data;
	unsigned char d_data = 0b11111100 & data;
	PORTD = d_data;
	PORTC = c_data;
	// ram 데이터 쓰기. RS -> high, RW -> low
	PORTB = (PORTB | 1 << RS) & ~(1 << RW);
	get_E_Strobe();
}

void lcdInit()
{
	DDRB |= 1 << RS | 1 << RW | 1 << E;
	PORTB &= ~(1 << RS | 1 << E | 1 << RW);
	
	// 인터페이스 / 디스플레이 설정 - 00 0011 11--
	// DL: 1 - 8bit interface
	// N: 1 - 2줄 표시
	// F: 1 - 문자 5x10 dot
	LCD_command(0x3C);
	
	// 커서 초기 위치 - 00 0000 001-
	// 커서 위치를 제 1행 1열로 이동.
	LCD_command(0x02);
	
	// 화면 클리어 - 00 0000 0001
	// 아스키코드 0x20 으로 화면 처리후 커서 위치를 1행 1열로 이동
	LCD_command(0x01);
	
	// 문자 입력 모드 - 00 0000 0110
	// 커서를 오른쪽으로 이동하면서 문자 입력
	LCD_command(0x06);
	
	// 디스플레이 on/off 제어 - 00 0000 1111
	// D: 1 - 디스플레이 on
	// C: 1 - 커서 on
	// B: 1 - 커서 깜빡임 on
	LCD_command(0x0f);
}