ESPHome 2025.5.0
Loading...
Searching...
No Matches
esp32_can.cpp
Go to the documentation of this file.
1#ifdef USE_ESP32
2#include "esp32_can.h"
3#include "esphome/core/log.h"
4
5#include <driver/twai.h>
6
7// WORKAROUND, because CAN_IO_UNUSED is just defined as (-1) in this version
8// of the framework which does not work with -fpermissive
9#undef CAN_IO_UNUSED
10#define CAN_IO_UNUSED ((gpio_num_t) -1)
11
12namespace esphome {
13namespace esp32_can {
14
15static const char *const TAG = "esp32_can";
16
17static bool get_bitrate(canbus::CanSpeed bitrate, twai_timing_config_t *t_config) {
18 switch (bitrate) {
19#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32C3) || \
20 defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32H2)
22 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_1KBITS();
23 return true;
25 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_5KBITS();
26 return true;
28 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_10KBITS();
29 return true;
31 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_12_5KBITS();
32 return true;
34 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_16KBITS();
35 return true;
37 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_20KBITS();
38 return true;
39#endif
41 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_25KBITS();
42 return true;
44 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_50KBITS();
45 return true;
47 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_100KBITS();
48 return true;
50 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_125KBITS();
51 return true;
53 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_250KBITS();
54 return true;
56 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_500KBITS();
57 return true;
59 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_800KBITS();
60 return true;
62 *t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_1MBITS();
63 return true;
64 default:
65 return false;
66 }
67}
68
70 twai_general_config_t g_config =
71 TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t) this->tx_, (gpio_num_t) this->rx_, TWAI_MODE_NORMAL);
72 if (this->tx_queue_len_.has_value()) {
73 g_config.tx_queue_len = this->tx_queue_len_.value();
74 }
75 if (this->rx_queue_len_.has_value()) {
76 g_config.rx_queue_len = this->rx_queue_len_.value();
77 }
78
79 twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();
80 twai_timing_config_t t_config;
81
82 if (!get_bitrate(this->bit_rate_, &t_config)) {
83 // invalid bit rate
84 this->mark_failed();
85 return false;
86 }
87
88 // Install TWAI driver
89 if (twai_driver_install(&g_config, &t_config, &f_config) != ESP_OK) {
90 // Failed to install driver
91 this->mark_failed();
92 return false;
93 }
94
95 // Start TWAI driver
96 if (twai_start() != ESP_OK) {
97 // Failed to start driver
98 this->mark_failed();
99 return false;
100 }
101 return true;
102}
103
105 if (frame->can_data_length_code > canbus::CAN_MAX_DATA_LENGTH) {
107 }
108
109 uint32_t flags = TWAI_MSG_FLAG_NONE;
110 if (frame->use_extended_id) {
111 flags |= TWAI_MSG_FLAG_EXTD;
112 }
113 if (frame->remote_transmission_request) {
114 flags |= TWAI_MSG_FLAG_RTR;
115 }
116
117 twai_message_t message = {
118 .flags = flags,
119 .identifier = frame->can_id,
120 .data_length_code = frame->can_data_length_code,
121 .data = {}, // to suppress warning, data is initialized properly below
122 };
123 if (!frame->remote_transmission_request) {
124 memcpy(message.data, frame->data, frame->can_data_length_code);
125 }
126
127 if (twai_transmit(&message, this->tx_enqueue_timeout_ticks_) == ESP_OK) {
128 return canbus::ERROR_OK;
129 } else {
131 }
132}
133
135 twai_message_t message;
136
137 if (twai_receive(&message, 0) != ESP_OK) {
138 return canbus::ERROR_NOMSG;
139 }
140
141 frame->can_id = message.identifier;
142 frame->use_extended_id = message.flags & TWAI_MSG_FLAG_EXTD;
143 frame->remote_transmission_request = message.flags & TWAI_MSG_FLAG_RTR;
144 frame->can_data_length_code = message.data_length_code;
145
146 if (!frame->remote_transmission_request) {
147 size_t dlc =
148 message.data_length_code < canbus::CAN_MAX_DATA_LENGTH ? message.data_length_code : canbus::CAN_MAX_DATA_LENGTH;
149 memcpy(frame->data, message.data, dlc);
150 }
151
152 return canbus::ERROR_OK;
153}
154
155} // namespace esp32_can
156} // namespace esphome
157
158#endif
virtual void mark_failed()
Mark this component as failed.
canbus::Error read_message(struct canbus::CanFrame *frame) override
optional< uint32_t > rx_queue_len_
Definition esp32_can.h:31
TickType_t tx_enqueue_timeout_ticks_
Definition esp32_can.h:29
optional< uint32_t > tx_queue_len_
Definition esp32_can.h:30
canbus::Error send_message(struct canbus::CanFrame *frame) override
bool setup_internal() override
Definition esp32_can.cpp:69
bool has_value() const
Definition optional.h:87
value_type const & value() const
Definition optional.h:89
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint8_t can_data_length_code
Definition canbus.h:61