펌웨어에서 구조체와 포인터는 센서데이터 파싱, 시리얼 통신, 메모리 효율화 등 핵심 기능에 가장 많이 쓰이는 도구이다.
펌웨어는 센서 데이터를 바이트 단위로 주고받는다. 이 데이터를 구조체로 정리하고, 포인터로 메모리에 직접 접근하면 코드 가독성 + 속도 둘 다 잡을 수 있다.
1.1 구조체란?
구조체(struct)는 C언어에서 관련 있는 데이터를 하나로 묶은 사용자 정의 타입이다.
1.1.1 예시: 온습도 센서 데이터 구조
typedef struct {
uint8_t temperature; // 섭씨 온도
uint8_t humidity; // 상대 습도
} SensorData;
→ 이 구조체로 SensorData
라는 이름으로 온습도 값을 모아 다룰 수 있다.(편리함)
1.2 포인터란?
C언어의 포인터는 메모리 주소를 저장하는 변수다.
펌웨어에서는 버퍼 데이터를 해석하거나, 하드웨어 레지스터에 접근할 때 자주 쓴다.
uint8_t buffer[2] = {28, 65}; // 센서 응답: 온도 28°C, 습도 65%
SensorData *data = (SensorData*)buffer;
printf("Temp: %d, Humid: %d", data->temperature, data->humidity);
### 1.2.1 설명:
buffer
는 UART 등으로 받은 2바이트 데이터를 저장한 배열SensorData* data
는 구조체 포인터로 변환하여 각 필드에 직접 접근- 메모리 복사 없이 바로 해석 → 빠르고 효율적
1.3 실전 예제: 시리얼 패킷 구조 정의
센서 패킷:0xAA 0x55 0x01 0x02 0x1C 0x64 0x83
(헤더, 명령어, 길이, 온도, 습도, 체크섬)
1.3.1 구조체 정의
typedef struct {
uint8_t header1;
uint8_t header2;
uint8_t command;
uint8_t length;
uint8_t temperature;
uint8_t humidity;
uint8_t checksum;
} SensorPacket;
### 1.3.2 포인터로 파싱
uint8_t rx_buf[7] = {0xAA, 0x55, 0x01, 0x02, 0x1C, 0x64, 0x83};
SensorPacket *packet = (SensorPacket*)rx_buf;
if ((packet->command ^ packet->length ^ packet->temperature ^ packet->humidity) == packet->checksum) {
printf("Temp: %d, Humid: %d", packet->temperature, packet->humidity);
}
→ 이렇게 구조체 + 포인터를 조합하면 가독성, 유지보수성 모두 상승
1.4 내가 느낀 점
지금까지 시리얼 데이터는 그냥 바이트 배열로만 봤다면,
이제는 그 구조를 정의하고, 포인터로 다루는 방식으로 이해할 수 있게 됐다.
펌웨어 코드를 읽거나 직접 쓸 때 큰 무기가 될 개념이다.