본문 바로가기
-----ETC-----/C++ 임베디드 시스템 프로그래밍 시리즈

[C++ 임베디드 시스템 프로그래밍 시리즈] Day 2: 임베디드 시스템에서의 C++ 사용 사례

by cogito21_cpp 2024. 8. 1.
반응형

임베디드 시스템에서의 C++ 사용 사례

C++는 임베디드 시스템에서 많은 장점을 제공합니다. 객체 지향 프로그래밍, 효율적인 메모리 관리, 강력한 표준 라이브러리 등 다양한 기능을 통해 임베디드 시스템의 개발을 효율적으로 수행할 수 있습니다. 오늘은 C++가 임베디드 시스템에서 어떻게 사용되는지 구체적인 사례를 통해 살펴보겠습니다.

1. 객체 지향 프로그래밍 (OOP)

객체 지향 프로그래밍(OOP)은 코드의 재사용성과 유지보수성을 높이는 데 도움이 됩니다. 클래스와 객체를 사용하여 하드웨어 구성 요소를 추상화할 수 있습니다.

 

LED 제어 클래스

다음은 LED를 제어하는 클래스를 작성한 예제입니다.

// LED.h
#ifndef LED_H
#define LED_H

class LED {
private:
    int pin;

public:
    LED(int pin);
    void on();
    void off();
};

#endif

// LED.cpp
#include "LED.h"
#include <Arduino.h>

LED::LED(int pin) : pin(pin) {
    pinMode(pin, OUTPUT);
}

void LED::on() {
    digitalWrite(pin, HIGH);
}

void LED::off() {
    digitalWrite(pin, LOW);
}

// main.cpp
#include <Arduino.h>
#include "LED.h"

LED led(13);

void setup() {
    // 초기 설정은 LED 클래스에서 처리
}

void loop() {
    led.on();
    delay(1000);
    led.off();
    delay(1000);
}

 

2. 하드웨어 추상화

하드웨어 추상화(HAL)는 하드웨어 의존성을 줄이고, 코드의 이식성을 높이는 데 도움이 됩니다. HAL을 통해 하드웨어의 세부 사항을 숨기고, 상위 계층의 코드가 하드웨어와 독립적으로 동작할 수 있도록 합니다.

 

GPIO 제어 클래스

다음은 GPIO 핀을 제어하는 클래스를 작성한 예제입니다.

// GPIO.h
#ifndef GPIO_H
#define GPIO_H

enum class PinMode { INPUT, OUTPUT, INPUT_PULLUP };

class GPIO {
private:
    int pin;

public:
    GPIO(int pin);
    void setMode(PinMode mode);
    void write(bool value);
    bool read();
};

#endif

// GPIO.cpp
#include "GPIO.h"
#include <Arduino.h>

GPIO::GPIO(int pin) : pin(pin) {}

void GPIO::setMode(PinMode mode) {
    switch (mode) {
        case PinMode::INPUT:
            pinMode(pin, INPUT);
            break;
        case PinMode::OUTPUT:
            pinMode(pin, OUTPUT);
            break;
        case PinMode::INPUT_PULLUP:
            pinMode(pin, INPUT_PULLUP);
            break;
    }
}

void GPIO::write(bool value) {
    digitalWrite(pin, value ? HIGH : LOW);
}

bool GPIO::read() {
    return digitalRead(pin);
}

// main.cpp
#include <Arduino.h>
#include "GPIO.h"

GPIO led(13);

void setup() {
    led.setMode(PinMode::OUTPUT);
}

void loop() {
    led.write(true);
    delay(1000);
    led.write(false);
    delay(1000);
}

 

3. 템플릿과 제네릭 프로그래밍

템플릿과 제네릭 프로그래밍을 사용하면 코드의 재사용성을 높이고, 다양한 데이터 타입을 처리할 수 있습니다.

 

링 버퍼 클래스

다음은 링 버퍼(Ring Buffer)를 구현한 예제입니다.

// RingBuffer.h
#ifndef RINGBUFFER_H
#define RINGBUFFER_H

template <typename T, size_t Size>
class RingBuffer {
private:
    T buffer[Size];
    size_t head;
    size_t tail;
    size_t count;

public:
    RingBuffer();
    void push(T item);
    T pop();
    bool isEmpty() const;
    bool isFull() const;
};

#endif

// RingBuffer.cpp
#include "RingBuffer.h"

template <typename T, size_t Size>
RingBuffer<T, Size>::RingBuffer() : head(0), tail(0), count(0) {}

template <typename T, size_t Size>
void RingBuffer<T, Size>::push(T item) {
    if (!isFull()) {
        buffer[head] = item;
        head = (head + 1) % Size;
        count++;
    }
}

template <typename T, size_t Size>
T RingBuffer<T, Size>::pop() {
    if (!isEmpty()) {
        T item = buffer[tail];
        tail = (tail + 1) % Size;
        count--;
        return item;
    }
    return T(); // 기본 생성자 호출
}

template <typename T, size_t Size>
bool RingBuffer<T, Size>::isEmpty() const {
    return count == 0;
}

template <typename T, size_t Size>
bool RingBuffer<T, Size>::isFull() const {
    return count == Size;
}

// main.cpp
#include <Arduino.h>
#include "RingBuffer.h"

RingBuffer<int, 5> buffer;

void setup() {
    Serial.begin(9600);
    buffer.push(1);
    buffer.push(2);
    buffer.push(3);
}

void loop() {
    if (!buffer.isEmpty()) {
        int value = buffer.pop();
        Serial.println(value);
        delay(1000);
    }
}

 

마무리

임베디드 시스템에서 C++는 객체 지향 프로그래밍, 하드웨어 추상화, 템플릿과 제네릭 프로그래밍을 통해 효율적이고 유지보수하기 쉬운 코드를 작성하는 데 도움을 줍니다. 오늘 살펴본 예제를 통해 C++의 다양한 기능이 임베디드 시스템 개발에 어떻게 활용되는지 이해할 수 있었습니다. 다음 날에는 개발 환경 설정에 대해 알아보겠습니다.

질문이나 추가적인 피드백이 있으면 언제든지 댓글로 남겨 주세요.

Day 3 예고

다음 날은 "개발 환경 설정 (툴체인, IDE)"에 대해 다룰 것입니다. 다양한 개발 환경과 도구를 설정하여 임베디드 시스템 프로그래밍을 시작할 수 있도록 안내하겠습니다.

반응형