CAN 데이터 송수신 (ESP32 IDF 예제)
1. CAN 통신 개요
CAN(Controller Area Network) 통신은 자동차, 산업 자동화, 로봇 제어 등 다양한 분야에서 사용되는 직렬 통신 프로토콜입니다. 여러 개의 마이크로컨트롤러 간에 신뢰성 높은 데이터 교환이 가능하도록 설계되었으며, 다중 마스터(Multi-Master) 방식을 지원합니다.
ESP32는 기본적으로 CAN 통신을 지원하며, Espressif의 ESP-IDF(ESP32 IoT Development Framework)를 활용하여 CAN 데이터 송수신을 구현할 수 있습니다. 이번 포스팅에서는 ESP32 IDF를 활용한 CAN 메시지 송수신 예제와 필터링 기법, 인터럽트 방식과 폴링 방식의 차이를 설명하겠습니다.
2. ESP32 IDF에서 CAN 드라이버 설정
ESP32의 CAN 드라이버는 기본적으로 twai
드라이버를 사용합니다. ESP-IDF에서는 twai.h
헤더를 포함하여 CAN 통신을 설정할 수 있습니다.
2.1. 프로젝트 설정
ESP32에서 CAN 통신을 사용하려면 먼저 menuconfig
에서 해당 드라이버를 활성화해야 합니다.
idf.py menuconfig
메뉴에서 Component Config -> TWAI Controller로 이동하여 드라이버를 활성화합니다.
2.2. CAN 드라이버 초기화 코드
다음은 ESP32의 TWAI 드라이버를 초기화하는 코드입니다.
#include "driver/twai.h"
void can_driver_init() {
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(GPIO_NUM_21, GPIO_NUM_22, TWAI_MODE_NORMAL);
twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
printf("CAN 드라이버 설치 완료\n");
} else {
printf("CAN 드라이버 설치 실패\n");
return;
}
if (twai_start() == ESP_OK) {
printf("CAN 드라이버 시작\n");
} else {
printf("CAN 드라이버 시작 실패\n");
}
}
위 코드는 ESP32의 GPIO 21과 22를 사용하여 CAN 통신을 활성화하는 코드입니다. 속도는 500kbps로 설정되었으며, 모든 메시지를 수신할 수 있도록 필터를 설정하였습니다.
3. CAN 메시지 송신 코드 예제
ESP32에서 CAN 메시지를 송신하려면 twai_transmit()
함수를 사용해야 합니다. 다음은 CAN 메시지를 송신하는 예제 코드입니다.
void can_send_message() {
twai_message_t message;
message.identifier = 0x123;
message.flags = TWAI_MSG_FLAG_NONE;
message.data_length_code = 4;
message.data[0] = 0xAA;
message.data[1] = 0xBB;
message.data[2] = 0xCC;
message.data[3] = 0xDD;
if (twai_transmit(&message, pdMS_TO_TICKS(1000)) == ESP_OK) {
printf("CAN 메시지 송신 성공\n");
} else {
printf("CAN 메시지 송신 실패\n");
}
}
이 코드에서는 0x123의 ID를 가지는 메시지를 전송합니다. 데이터 바이트는 0xAA, 0xBB, 0xCC, 0xDD
이며, 최대 1000ms 동안 대기하도록 설정되었습니다.
4. CAN 메시지 수신 및 필터링 코드
ESP32에서 CAN 메시지를 수신하려면 twai_receive()
함수를 사용해야 합니다.
void can_receive_message() {
twai_message_t message;
if (twai_receive(&message, pdMS_TO_TICKS(1000)) == ESP_OK) {
printf("CAN 메시지 수신 성공: ID = 0x%X, 데이터 길이 = %d\n", message.identifier, message.data_length_code);
for (int i = 0; i < message.data_length_code; i++) {
printf("데이터[%d] = 0x%X\n", i, message.data[i]);
}
} else {
printf("CAN 메시지 수신 실패\n");
}
}
위 코드는 수신된 CAN 메시지의 ID와 데이터를 출력하는 역할을 합니다.
4.1. 특정 메시지 필터링
특정 ID만 수신하려면 필터 설정을 수정해야 합니다.
twai_filter_config_t f_config = {
.acceptance_code = (0x123 << 21),
.acceptance_mask = ~(0x7FF << 21),
.single_filter = true
};
이렇게 하면 ID가 0x123인 메시지만 수신됩니다.
5. 인터럽트 방식과 폴링 방식 비교
ESP32의 CAN 드라이버는 두 가지 방식으로 메시지를 수신할 수 있습니다.
5.1. 폴링 방식 (Polling)
void polling_receive() {
while (1) {
twai_message_t message;
if (twai_receive(&message, pdMS_TO_TICKS(1000)) == ESP_OK) {
printf("메시지 수신: ID=0x%X\n", message.identifier);
}
}
}
이 방식은 CPU가 계속 메시지를 체크해야 하므로 비효율적일 수 있습니다.
5.2. 인터럽트 방식 (Interrupt)
void IRAM_ATTR can_isr_handler(void *arg) {
twai_message_t message;
if (twai_receive(&message, 0) == ESP_OK) {
printf("CAN 인터럽트 수신: ID=0x%X\n", message.identifier);
}
}
void setup_can_interrupt() {
twai_intr_register(can_isr_handler, NULL);
}
이 방식은 CPU 부하를 줄일 수 있으며, 메시지가 들어오면 자동으로 처리할 수 있습니다.
6. 결론
이번 포스팅에서는 ESP32 IDF를 활용하여 CAN 데이터 송수신을 구현하는 방법을 소개하였습니다. 주요 내용은 다음과 같습니다:
- ESP32에서 CAN 드라이버를 활성화하고 초기화하는 방법
- CAN 메시지를 송신하는 방법
- CAN 메시지를 수신하고 필터링하는 방법
- 폴링 방식과 인터럽트 방식의 차이점
ESP32를 활용한 CAN 통신은 자동차 및 산업 자동화 프로젝트에서 활용될 수 있으며, 실제 응용 사례에서 안정적인 데이터 송수신을 구현하는 데 필수적인 요소입니다.
'CAN 통신' 카테고리의 다른 글
CAN 네트워크 구성 및 다중 노드 통신 실습 (0) | 2025.02.27 |
---|---|
CAN 컨트롤러(MCP2515) 사용 방법 [ ESP32 IDF ] (0) | 2025.02.26 |
MCU에서 CAN 초기화 및 설정 (ESP32 기준) (0) | 2025.02.24 |
CAN 드라이버 및 소프트웨어 스택 개요 (0) | 2025.02.23 |
CAN 인터페이스 및 주요 하드웨어 (0) | 2025.02.22 |