반도체, 임베디드 Study/~ING

STM32 - I2C를 이용한 LCD 문자 출력 (함수 분석) ~ing

잇(IT) 2024. 7. 1. 13:52
728x90

https://insoobaik.tistory.com/624

 

STM32 - LCD 문자 출력 (I2C)

https://insoobaik.tistory.com/626 STM32 - I2C 이론보호되어 있는 글입니다. 내용을 보시려면 비밀번호를 입력하세요.insoobaik.tistory.comI2C 이론에 이어 I2C 통신을 이용하여 LCD에 문자를 출력해볼 것이다.LCD

insoobaik.tistory.com

이전에 LCD에 I2C를 이용하여 문자를 출력했었는데, LCD를 출력하기까지 함수를 제대로 파악하지 않고 사용했다.

이번 글은 LCD를 사용하기 위한 함수에 대해 자세히 알아보기 위해 LCD 관련 DataSheet와 함수에 대해 파악해보려 한다.


 LCD 관련 코드

#include "lcd.h"
extern I2C_HandleTypeDef hi2c1;  // change your handler here accordingly

#define SLAVE_ADDRESS_LCD 0x4E // change this according to ur setup

void lcd_send_cmd (char cmd)
{
  char data_u, data_l;
	uint8_t data_t[4];
	data_u = (cmd&0xf0);
	data_l = ((cmd<<4)&0xf0);
	data_t[0] = data_u|0x0C;
	data_t[1] = data_u|0x08;
	data_t[2] = data_l|0x0C;
	data_t[3] = data_l|0x08;
	HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 4, 100);
}

void lcd_send_data (char data)
{
	char data_u, data_l;
	uint8_t data_t[4];
	data_u = (data&0xf0);
	data_l = ((data<<4)&0xf0);

	data_t[0] = data_u|0x0D;
	data_t[1] = data_u|0x09;
	data_t[2] = data_l|0x0D;
	data_t[3] = data_l|0x09;
	HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 4, 100);
}

void lcd_init (void)
{
	lcd_send_cmd (0x02);
	lcd_send_cmd (0x28);
	lcd_send_cmd (0x0c);
	lcd_send_cmd (0x80);
	for (int i=0;i<60;i++)
		{
			lcd_send_data (' ');  // clear lcd
		}
}

void lcd_send_string (char *str)
{
	while (*str) lcd_send_data (*str++);
}

위 코드는 LCD에 문자를 출력하기 위해 사용했던 코드들이다.

 

 

위 DataSheet와 아래 LCD 동작 테이블이 위와 같이 정의되어 있는 것을 확인할 수 있다.

 

첫번째 DataSheet를 보게 되면 현재 사용하는 LCD의 경우 Pin 4개를 통해 Data를 전달하고 있기 때문에 4bit씩 상위, 하위를 나누어 총 8bit를 전달하게 된다.

 

두번째 그림을 보게 되면 LCD는 Enable 값이 1에서 0으로 떨어질 때 값을 전달하는 것을 확인할 수 있고, RS가 0일 때 LCD에 명령에 대한 Data를 전달하게 되고, RS가 1일 때 LCD에 Data를 전달하는 것을 유추할 수 있다.

 

!!!!!!! 주의

I2C의 SCL, SDA는 Pull-up 저항으로 설정해야 한다.

그 이유는 I2C는 위와 같이 Master에 SDA, SCL을 연결해주는데, Pull-Up 저항을 주지 않으면 회로에 전압이 걸리지 않기 때문이다.

I2C 통신이 이루어지지 않고 있는 상황일 때에는 SDA와 SCL은 High 상태를 유지하고, Master가 I2C 통신을 시작하면 SDA가 Low상태로 내려가고, SCL은 I2C 통신이 시작되었음을 인지하고 클럭 신호를 전달하게 된다.

SCL이 Low에서 High로 돌아왔을 때 SDA가 Low에서 High로 변하게 되면 I2C 통신이 완료된다.


lcd_send_cmd 함수

void lcd_send_cmd (char cmd)
{
  char data_u, data_l;
	uint8_t data_t[4];
	data_u = (cmd&0xf0);
	data_l = ((cmd<<4)&0xf0);
	data_t[0] = data_u|0x0C;
	data_t[1] = data_u|0x08;
	data_t[2] = data_l|0x0C;
	data_t[3] = data_l|0x08;
	HAL_I2C_Master_Transmit (&hi2c1, SLAVE_ADDRESS_LCD,(uint8_t *) data_t, 4, 100);
}

위 함수는 즉 8bit의 데이터를 4bit씩 나누어 전달하기 때문에 data_u, data_l 상위, 하위 변수로 나누며, 전달된 data를 shift 시켜 4bit 데이터를 저장한다.

8bit의 데이터를 전달하기 위해서는 데이터 전달 Pin을 4개 더 사용해야 하지만 4bit의 데이터를 전달하게 되면 데이터 전달 Pin이 절반으로 줄어들게 된다. 하지만 데이터의 전달 양은 2배로 늘어나게 된다.

4bit씩 전달하는 위 코드의 경우 data_t[] 배열에 담기는 8bit의 상위 4bit는 Data에 관련된 bit에 해당하고, 하위 4bit는 en, rs, rw 값에 해당한다.

0000(data)00(enable)0(R/W)0(R/S)

 

1.

	data_t[0] = data_u|0x0C;
	data_t[1] = data_u|0x08;

즉, 위 2줄 코드의 의미는 상위 4비트의 데이터를 en 1- > 0 (데이터를 전달받는 타이밍), RS 0(명령어를 전달)에 의미를 가진다.

	data_t[2] = data_l|0x0C;
	data_t[3] = data_l|0x08;

위 2줄 코드의 의미는 하위 4비트의 데이터를 상위 4비트와 같은 방식으로 전달하게 된다.

 

 

728x90