/** * @file pcan_id.h * @brief Упаковка и разбор 29-битного идентификатора ProtoCAN. * * Раскладка (соответствует ProtoCanId_t из SETCAN/Inc/protocan.h): * * биты 28 Priority * 27 Route * 26:24 DeviceType * 23:20 DeviceID * 19:16 MsgType * 15:0 MsgBody * * Здесь намеренно не используются битовые поля: их раскладка в C * определяется реализацией, и один и тот же заголовок на другом * компиляторе может дать другой порядок. Сдвиги переносимы всегда. */ #ifndef PCAN_ID_H #define PCAN_ID_H #include #include "pcan_config.h" #ifdef __cplusplus extern "C" { #endif #define PCAN_ID_MASK 0x1FFFFFFFUL /* --- Приоритет и маршрут --------------------------------------------------- */ #define PCAN_PRIORITY_CRITICAL 0U #define PCAN_PRIORITY_STANDARD 1U #define PCAN_ROUTE_FROM_PM 0U #define PCAN_ROUTE_FROM_DEVICE 1U /* --- Типы сообщений -------------------------------------------------------- */ typedef enum { PCAN_MSG_BROADCAST = 0x0U, PCAN_MSG_DISCRETE = 0x1U, PCAN_MSG_ANALOG = 0x2U, PCAN_MSG_GAS = 0x3U, /**< общее адресное пространство */ PCAN_MSG_MODBUS_COIL = 0x4U, PCAN_MSG_MODBUS_DISCR = 0x5U, PCAN_MSG_MODBUS_HOLDING = 0x6U, PCAN_MSG_MODBUS_INPUT = 0x7U, PCAN_MSG_ERROR = 0x8U, PCAN_MSG_PULSE = 0xFU } pcan_msgtype_t; /** Разобранный идентификатор. */ typedef struct { uint16_t msg_body; uint8_t msg_type; /**< pcan_msgtype_t */ uint8_t device_id; /**< 0..15 */ uint8_t device_type; /**< 0..7 */ uint8_t route; uint8_t priority; } pcan_id_t; uint32_t pcan_id_pack(const pcan_id_t *id); void pcan_id_unpack(uint32_t raw, pcan_id_t *id); /* --- Раскладки MsgBody ----------------------------------------------------- */ /** BROADCAST: Type[15:4], Body[3:0]. */ static inline uint16_t pcan_body_broadcast(uint16_t type, uint8_t body) { return (uint16_t)(((type & 0x0FFFU) << 4) | (body & 0x0FU)); } /** DISCRETE / ANALOG: Type[15:12], Body[11:0]. */ static inline uint16_t pcan_body_typed(uint8_t type, uint16_t body) { return (uint16_t)(((uint16_t)(type & 0x0FU) << 12) | (body & 0x0FFFU)); } /** MODBUS: StrAdr[15:4], RegCount[3:0]. */ static inline uint16_t pcan_body_modbus(uint16_t addr, uint8_t count) { return (uint16_t)(((addr & 0x0FFFU) << 4) | (count & 0x0FU)); } /** ERROR: Info[15:8], Code[7:0]. */ static inline uint16_t pcan_body_error(uint8_t info, uint8_t code) { return (uint16_t)(((uint16_t)info << 8) | code); } #ifdef __cplusplus } #endif #endif /* PCAN_ID_H */