Files
templates/c/can-sensor/can_sensor.c

204 lines
6.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @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;
}