본문 바로가기
  • Masacorgi 's Dev Bloggg
TIL/Firmware

[펌웨어] 시리얼 명령 처리 흐름이란?

by masacorgi 2025. 6. 1.

이번엔 펌웨어 내부에서 시리얼로 들어온 명령을 어떻게 처리하는지,
즉 “명령어 → 파싱 → 실행 → 응답”이라는 전체 흐름을 코드 중심으로 이해보기로 한다.


UART로 MCU에 명령어를 보내면, MCU는 이를 파싱하고 특정 작업을 실행한 후 응답을 보낸다.
이 흐름은 센서 설정, 장치 제어, 상태 요청 등 다양한 펌웨어 기능의 핵심이다.



1. 기본 구조 요약


1. UART 수신
2. 명령 파싱 (프레임 확인, 명령어 확인)
3. 명령 실행 (센서 읽기, 출력 제어 등)
4. 응답 전송

2. 명령 프레임 예시


명령어 예제 (7바이트):

0xAA 0x55  0x10  0x00  0x00  0x00  0x10
필드 설명
0xAA 0x55 헤더
0x10 명령어 코드 (예: 센서 읽기)
0x00~0x00 데이터 없음
0x10 체크섬 (명령어의 XOR)

3. 코드 예제: Arduino 시리얼 명령 처리


// 시리얼 명령어 처리 예제

#define CMD_GET_SENSOR 0x10
#define HEADER1 0xAA
#define HEADER2 0x55

uint8_t buffer[7];
uint8_t idx = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available()) {
    buffer[idx++] = Serial.read();

    // 7바이트 수신 완료
    if (idx == 7) {
      idx = 0;

      // 헤더 확인
      if (buffer[0] == HEADER1 && buffer[1] == HEADER2) {
        uint8_t cmd = buffer[2];
        uint8_t checksum = buffer[6];

        // XOR 체크섬 확인
        if ((cmd ^ buffer[3] ^ buffer[4] ^ buffer[5]) == checksum) {
          if (cmd == CMD_GET_SENSOR) {
            sendSensorResponse(); // 센서 응답 전송
          }
        }
      }
    }
  }
}

void sendSensorResponse() {
  uint8_t temp = 25;  // 온도 25도
  uint8_t humid = 50; // 습도 50%
  uint8_t response[7];

  response[0] = HEADER1;
  response[1] = HEADER2;
  response[2] = CMD_GET_SENSOR;
  response[3] = 0x02;       // 데이터 길이
  response[4] = temp;
  response[5] = humid;
  response[6] = CMD_GET_SENSOR ^ 0x02 ^ temp ^ humid; // 체크섬

  Serial.write(response, 7); // 응답 전송
}


4. 구조체로 리팩토링하면?


코드의 가독성과 유지보수를 높이려면 구조체와 포인터로 패킷을 다루는 것도 좋다.
(→ 이전글 참고 : [[펌웨어]구조체와 포인터는 왜 중요한가](https://masacorgi.tistory.com/119) )

5. 참고자료