/** * @file can_sensor.c * @brief Однокадровый транспорт SETCAN SETTINGS для локаций DS18B20. */ #include "can_sensor.h" /** Возвращает 1, если все восемь байтов ROM равны нулю. */ static uint8_t can_sensor_rom_is_zero(const uint8_t *rom) { uint8_t index; for (index = 0U; index < CAN_SENSOR_ID_SIZE; index++) { if (rom[index] != 0U) { return 0U; } } return 1U; } /** Передаёт уже собранный кадр с ограниченным числом повторов. */ static uint8_t can_sensor_send_frame(CanSensor *link, const CanSensor_Frame *frame) { uint8_t attempt; for (attempt = 0U; attempt < link->config.retries; attempt++) { if (link->io.send(link->io.context, frame) != 0U) { link->sent_messages++; return 1U; } } link->send_errors++; return 0U; } void CanSensor_ConfigDefault(CanSensor_Config *config) { if (config == 0) { return; } config->tx_id = CAN_SENSOR_DEFAULT_TX_ID; config->rx_id = CAN_SENSOR_DEFAULT_RX_ID; config->extended = 1U; config->retries = CAN_SENSOR_DEFAULT_RETRIES; } uint8_t CanSensor_Init(CanSensor *link, const CanSensor_Io *io, const CanSensor_Config *config) { if ((link == 0) || (io == 0) || (io->send == 0)) { return 0U; } link->io = *io; if (config != 0) { link->config = *config; } else { CanSensor_ConfigDefault(&link->config); } if (link->config.tx_id == 0U) { link->config.tx_id = CAN_SENSOR_DEFAULT_TX_ID; } if (link->config.rx_id == 0U) { link->config.rx_id = CAN_SENSOR_DEFAULT_RX_ID; } link->config.tx_id &= CAN_SENSOR_HEADER_MASK; link->config.rx_id &= CAN_SENSOR_HEADER_MASK; link->config.extended = 1U; if (link->config.retries == 0U) { link->config.retries = CAN_SENSOR_DEFAULT_RETRIES; } link->sent_messages = 0U; link->send_errors = 0U; link->received_messages = 0U; link->dropped_frames = 0U; return 1U; } uint8_t CanSensor_BuildFrame(const CanSensor_Config *config, CanSensor_Frame *frame, uint8_t response, uint8_t position, uint8_t assembly_serial, const uint8_t *data, uint8_t length) { uint8_t index; uint32_t base; if ((config == 0) || (frame == 0) || (length > CAN_SENSOR_MAX_DATA) || ((length != 0U) && (data == 0))) { return 0U; } base = (response != 0U) ? config->tx_id : config->rx_id; frame->id = (base & CAN_SENSOR_HEADER_MASK) | ((uint32_t)assembly_serial << 8U) | (uint32_t)position; frame->extended = 1U; frame->length = length; for (index = 0U; index < CAN_SENSOR_MAX_DATA; index++) { frame->data[index] = (index < length) ? data[index] : 0U; } return 1U; } uint8_t CanSensor_SendId(CanSensor *link, uint8_t position, uint8_t assembly_serial, const uint8_t *id) { CanSensor_Frame frame; if ((link == 0) || (id == 0) || (link->io.send == 0)) { return 0U; } if (CanSensor_BuildFrame(&link->config, &frame, 1U, position, assembly_serial, id, CAN_SENSOR_ID_SIZE) == 0U) { link->send_errors++; return 0U; } return can_sensor_send_frame(link, &frame); } uint8_t CanSensor_SendError(CanSensor *link, uint8_t position, uint8_t assembly_serial, uint8_t result) { CanSensor_Frame frame; if ((link == 0) || (link->io.send == 0) || (result == CAN_SENSOR_RESULT_OK)) { return 0U; } if (CanSensor_BuildFrame(&link->config, &frame, 1U, position, assembly_serial, &result, 1U) == 0U) { link->send_errors++; return 0U; } return can_sensor_send_frame(link, &frame); } uint8_t CanSensor_HandleFrame(CanSensor *link, const CanSensor_Frame *frame, CanSensor_Message *out) { CanSensor_Message message; uint32_t header; uint8_t index; if ((link == 0) || (frame == 0)) { return 0U; } if (frame->extended == 0U) { return 0U; } header = frame->id & CAN_SENSOR_HEADER_MASK; if (header == (link->config.rx_id & CAN_SENSOR_HEADER_MASK)) { message.request = 1U; } else if (header == (link->config.tx_id & CAN_SENSOR_HEADER_MASK)) { message.request = 0U; } else { return 0U; } message.assembly_serial = (uint8_t)((frame->id >> 8U) & 0xFFU); message.position = (uint8_t)(frame->id & 0xFFU); message.result = CAN_SENSOR_RESULT_OK; for (index = 0U; index < CAN_SENSOR_ID_SIZE; index++) { message.id[index] = (index < frame->length) ? frame->data[index] : 0U; } if (message.request != 0U) { if (frame->length == 0U) { message.operation = CAN_SENSOR_OPERATION_GET; } else if (frame->length == CAN_SENSOR_ID_SIZE) { message.operation = (can_sensor_rom_is_zero(message.id) != 0U) ? CAN_SENSOR_OPERATION_CLEAR : CAN_SENSOR_OPERATION_WRITE; } else { message.operation = CAN_SENSOR_OPERATION_INVALID; message.result = CAN_SENSOR_RESULT_INVALID_DLC; } } else if (frame->length == CAN_SENSOR_ID_SIZE) { message.operation = CAN_SENSOR_OPERATION_RESPONSE; } else if (frame->length == 1U) { message.operation = CAN_SENSOR_OPERATION_ERROR; message.result = frame->data[0]; } else { link->dropped_frames++; return 0U; } link->received_messages++; if (out != 0) { *out = message; } return 1U; } uint8_t CanSensor_Poll(CanSensor *link, CanSensor_Message *out) { CanSensor_Frame frame; if ((link == 0) || (link->io.receive == 0)) { return 0U; } while (link->io.receive(link->io.context, &frame) != 0U) { if (CanSensor_HandleFrame(link, &frame, out) != 0U) { return 1U; } } return 0U; }