AVR LCD

cdm·2024년 1월 2일
0

AVR

목록 보기
7/8

1602 I2C LCD Module

TWI(Two Wire Interface)
TWBR, TWCR, TWDR 등을 사용하여 I2C 통신설정

void TWI_Init(void){
	// TWI Bit Rate Register
	// TWBR = 0x48;		// 0b01001000
	TWBR = (1<<TWBR5) | (1<<TWBR3);		// SCL Frequency, Datasheet for reference
}

void TWI_Start(void) {
	// TWI Control Register
	// Interrupt, Start bit, Enable Set
	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
	while(!(TWCR & (1<<TWINT)));		// TWI Setup complete -> Interrupt flag set
}

void TWI_Transmit(unsigned char data) {
	// TWI Data Register(Data buffer, 8bit)
	TWDR = data;
	TWCR = (1<<TWINT) | (1<<TWEN);		// Transmit -> Interrupt
	while(!(TWCR & (1<<TWINT)));
}

void TWI_Transmit_Addr(unsigned char data, unsigned char addr){
	TWI_Start();
	TWI_Transmit(addr);
	TWI_Transmit(data);
	TWI_Stop();
}

void TWI_Stop(void) {
	// TWCR Register init
	TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
}

c를 왼쪽으로 쉬프트 연산하면 상위 4bit는 원본의 하위 4bit.
원본 8bit를 보내려면 총 함수를 2번 호출해야함.
함수내부에서는 Enable신호를 보내고 데이터를 보내고 다시 Disable신호를 보내는 작업을 함.

LCD초기화 과정

volatile unsigned char PortLCD = 0;		// Higher 4bit(0xF0) == data bit, Lower 4bit(0x0F) == Control bit

void LCD_Init(void) {
	// sendByte(0b00110011, 0);
	sendHalfByte(0b00000011);
	_delay_ms(5);
	sendHalfByte(0b00000011);
	_delay_us(100);
	// sendByte(0b00110010, 0);
	sendHalfByte(0b00000011);
	_delay_ms(1);
	sendHalfByte(0b00000010);
	_delay_ms(1);
	
	sendByte(0b00101000, 0); // Data 4bit, Line 2, Font 5x8
	_delay_ms(1);
	sendByte(0b00001110, 0); //Display ON, Cursor ON, Blink OFF
	_delay_ms(1);

	TWI_Transmit_Addr(PortLCD |= 0x08, 0x4E);	// BackLight ON
	
	TWI_Transmit_Addr(PortLCD &= ~0x02, 0x4E);	// LCD Write ON
}

4bit씩 보내기

void sendHalfByte(unsigned char c) {
	// Higher 4 Bit
	c <<= 4;
	
	TWI_Transmit_Addr(PortLCD |= 0x04, 0x4E); // Enable E, Higher 4bit
	_delay_us(50);
	// Lower 4 Bit
	TWI_Transmit_Addr(PortLCD | c, 0x4E);

	TWI_Transmit_Addr(PortLCD &= ~0x04, 0x4E); // Disable E, Lower 4bit
	_delay_us(50);
}

주소를 설정할 때 주소는 7bit 0x27 -> R/W bit를 추가한 8bit 에서는 0x4E로 보내주어야 함.
7bit+R/W bit (0x27<<1 == 0x4E)

LCD에 문자 출력

void sendByte(unsigned char c, unsigned char mode) {
	if(mode == 0) TWI_Transmit_Addr(PortLCD &= ~0x01, 0x4E);
	else TWI_Transmit_Addr(PortLCD |= 0x01, 0x4E);
	unsigned char hc = 0;
	hc = c >> 4;
	sendHalfByte(hc);
	sendHalfByte(c);
}

void LCD_sendString(char s[]) {
	char n;
	for(n=0; s[n]!='\0'; n++)
		sendByte(s[n], 1);
}

기본적으로 ASCII코드와 LCD의 문자 bit가 일정함.
ex) ASCII 'a' : 0110 0001

시작위치 설정 및 Line 선택

void LCD_setPosition(unsigned char x, unsigned char line) {	// HD44780 data sheet for reference
	switch(line) {
		case 0: 
			sendByte(x | 0x80, 0);
			break;
		case 1: 
			sendByte((x+0x40) | 0x80, 0);
			break;
	}
}

일반적으로 HD44780의 명령어 포맷은 다음과 같음.
첫 번째 라인의 시작 주소: 0x00부터 0x27까지 (0x00, 0x01, ..., 0x27)
두 번째 라인의 시작 주소: 0x40부터 0x67까지 (0x40, 0x41, ..., 0x67)

수정사항: sendHalfByte부분 비효율적임. (0x27 << 1)을 사용하여 한번에 읽기쓰기를 정하고 사용하기.

참고 : https://wowon.tistory.com/263?category=615510
https://github.com/codecranch/avr-twi-lcd/blob/main/lcd.c
https://kogun.tistory.com/23

0개의 댓글