091

[C/C++] LCD에 원하는 글자를 출력하기 본문

Programming Language/C&C++

[C/C++] LCD에 원하는 글자를 출력하기

공구일 2025. 3. 24. 10:30
728x90

 마이크로컨트롤러와 주변 장치를 연결하는 대표적인 통신 프로토콜에는 UART, I2C, SPI 등이 있음, 저번 글에서는 URAT에 관한 내용을 다뤘고 이번 글에서는 I2C 프로토콜을 이용하여 LCD에 출력하는 코드에 대해 설명할 예정 !

 

01. I2C(Inter-Intergrated Circuit) & LCD(Liqiuid Crystal Display) 

 

(1) I2C : 두 개의 선(SDA, SCL)만으로 여러 개의 장치를 연결할 수 있는 직렬 통신 프로토콜로, SDA와 SCL은 각각 데이터 전송, 클록 신호 전송의 기능의 역할을 함, ESP32에서 Wire 라이브러리를 사용하여 쉽게 구현 가능

 

(2) LCD : 액정 디스플레이로, 전로 장치에서 글자, 숫자, 심볼등을 표시하는 데 사용됨. 1602 LCD는 16*2 디스플레이로 16개의 문자를 2줄로 출력 가능한 LCD를 말함, 기본 주소는 0*27, 0*3F이고, LiquidCrystal_I2C 라이브러리로 쉽게 제어 가능함

 

-> ESP32와 I2C LCD 연결 

* ESP32에서 저 초록색 박스 안에 하얀 연결 선까지 연결하는 점프와이어의 색상은 자유롭게 해도 좋으나 필자는 알아보기 쉽게 하기 위해 색상을 맞춰줌 *

- VCC(빨간색), GND(검정색), GPIO21(하얀색, SDA), GPIO22(노란색, SCL)을 연결해주면 됨. 

 

02.  LCD에 원하는 글자를 출력하기 

 

- LCD1602_Display.h

#ifndef LCD1602_DISPLAY_H //파일이 여러 번 포함되는 걸 방지하는 헤더 가드 코드
#define LCD1602_DISPLAY_H

#include <Wire.h>
#include <LiquidCrystal_I2C.h>  // lcd와 같은 객체가 들어있는 객체

// **LCD1602_Display Class for 16x2 LCD Display**
class LCD1602_Display {
public:
    LCD1602_Display(uint8_t lcd_addr = 0x27, uint8_t cols = 16, uint8_t rows = 2);  
    void init();
    void displayText(String text, int col, int row);
    void clearScreen();
    
private:
    LiquidCrystal_I2C lcd; // LCD 객체를 선언
};
#endif

-> LCD 제어를 위한 클래스인 LCD1602_Display를 클래스를 선언만 하고, cpp(아래파일)에서 구현할 예정임.

 

- LCD1602_Display.cpp

#include "LCD1602_Display.h"
// 클래스의 생성자
LCD1602_Display::LCD1602_Display(uint8_t lcd_addr, uint8_t cols, uint8_t rows) 
    : lcd(lcd_addr, cols, rows) {}
// LCD 초기화 함수
void LCD1602_Display::init() {
    lcd.init();  // lcd 초기화
    lcd.backlight();  // 백라이트 켜기
}
// 특정 위치에 텍스트 출력함수
void LCD1602_Display::displayText(String text, int col, int row) {
    lcd.setCursor(col, row); // 커서 위치 설정
    lcd.print(text);         // 텍스트 출력
}
// LCD 화면 지우기
void LCD1602_Display::clearScreen() {
    lcd.clear();
}

-> 범위 지정 연산자(::)를 이용하여 cpp에서 구현해줌(추상 클래스가 아니더라도 이런 식으로 객체 지향 프로그래밍을 위해 선언과 구현파일을 나누는 경우가 많음)

 

- CH5-1.ino

#include <Wire.h> //I2C 통신을 위한 라이브러리 : 명시적으로 포함시켜줘야함            
#include "LCD1602_Display.h"   //LCD1602 디스플레이 클래스를 위한 헤더 파일
LCD1602_Display lcd(0x27, 16, 2);  //주소가 0x27인 16*2 LCD 객체 생성

bool isLocalControl = false;

void setup() {
    Serial.begin(115200);  // 시리얼 통신 초기화 (PC<=>ESP32)
    Wire.begin(21, 22);    // I2C 통신 초기화 (SDA=21, SCL=22)
    lcd.init();  // LCD 초기화
  }
void loop() {
	if(Serial.available()){
    	String command = Serial.readString();
        if(command == "V?"){
            int adcValue = analogRead(34);
            float voltage = (adcValue / 4095.0) * 3.3;

            Serial.print("Voltage: ");
            Serial.println(voltage, 2); // 소수점 이하 2자리까지 출력하도록 지정
            isLocalControl = true;
		}
    }
    
    if (isLocalControl) {
    	lcd.clearScreen();
        lcd.displayText("Local Control", 0, 0);
        lcd.displayText("Voltage: " + String(voltage, 2) + "V", 0, 1);
    } else {
        lcd.displayText("Remote Control", 0, 0);  // 리모트 컨트롤일 때 LCD에 출력
    }
    
    delay(1000);
    isLocalControl = false;
}

-> LCD1602_Display.h에 포함된 Wire.h이 있음에도 명시적으로 .ino파일에 포함되지 않으면 Wire 라이브러리 함수들이 정의되지 않아서 오류가 발생하므로 별도로 포함시켜 줘야함

 

-> 기본을 리모트 컨트롤 상태로 두고, V?와 같은 로컬 제어 상태일 때 true값으로 만들어줌

 

728x90