#ifndef _protocan #define _protocan #include "main.h" #include "can.h" #define _DEMO #define ONLINE 1; #define OFFLINE 0; #define ID_MAIN_DEVICE 0x000 #define CURRENT_TYPE_DEVICE 0b001 #define CURRENT_ID_DEVICE 0b0010 #define PROTOCAN_RX_BUFFER_SIZE 128 #define SensorToModbusRegister(SensorType, SensorID) SensorType << 11 | SensorID #define HighByteOfWord(WORD) (WORD>>8)&0xFF #define LowByteOfWord(WORD) WORD&0xFF /** * @brief Статус инициализации протокола CAN. * * Это перечисление описывает возможные статусы после попытки инициализации. */ typedef enum { PROTOCAN_INIT_OK = 0x00U, /**< Инициализация прошла успешно. */ PROTOCAN_INIT_HCAN_ERROR = 0x01U, /**< Ошибка при инициализации модуля CAN. */ PROTOCAN_INIT_HRTC_ERROR = 0x02U, /**< Ошибка при инициализации модуля RTC. */ PROTOCAN_INIT_TIM_ERROR = 0x04U /**< Ошибка при инициализации таймера. */ } PROTOCAN_INIT_StatusTypeDef; /** * @brief Статус выполнения операции протокола CAN. * * Это перечисление описывает возможные результаты выполнения функций протокола. */ typedef enum { PROTOCAN_OK = 0x00U, /**< Операция прошла успешно. */ PROTOCAN_ERROR = 0x01U, /**< Обнаружена ошибка во время выполнения. */ PROTOCAN_BUSY = 0x02U, /**< Канал занят, выполнение невозможно в данный момент. */ PROTOCAN_TIMEOUT = 0x03U /**< Истек таймаут ожидания. */ } PROTOCAN_StatusTypeDef; /** * @brief Уровень приоритета CAN-сообщения. * * Это перечисление определяет важность и приоритет обработки сообщения. */ typedef enum { PROTOCAN_PRIORITY_CRITICAL = 0, /**< Критический приоритет, рекомендуется обработка без задержек. */ PROTOCAN_PRIORITY_STANDARD = 1 /**< Стандартный приоритет, менее важный. */ } ProtoCanPriorityType; /** * @brief Маршрут CAN-сообщения. * * Это перечисление задает направление маршрута отправки сообщения. */ typedef enum { PROTOCAN_ROUTE_FROM_PM = 0, /**< Сообщение отправляется от управляющего модуля (PM). */ PROTOCAN_ROUTE_FROM_DEVICE = 1 /**< Сообщение отправляется от устройства (Device). */ } ProtoCanRouteType; /** * @brief Типы сообщений CAN. * * Перечисление определяет различные типы сообщений, используемые в протоколе. */ typedef enum { PROTOCAN_MSGTYPE_BROADCAST = 0b0000, /**< Широковещательное сообщение. */ PROTOCAN_MSGTYPE_DISCRETE = 0b0001, /**< Дискретное цифровое сообщение. */ PROTOCAN_MSGTYPE_ANALOG = 0b0010, /**< Аналоговое сообщение. */ PROTOCAN_MSGTYPE_GENERAL_ADDRESS_SPACE = 0b0011, /**< Сообщение общего адресного пространства. */ PROTOCAN_MSGTYPE_MODBUS_COIL = 0b0100, /**< Сообщение Modbus - Coil. */ PROTOCAN_MSGTYPE_MODBUS_DISCRETE = 0b0101, /**< Сообщение Modbus - Discrete. */ PROTOCAN_MSGTYPE_MODBUS_HOLDING = 0b0110, /**< Сообщение Modbus - Holding. */ PROTOCAN_MSGTYPE_MODBUS_INPUT = 0b0111, /**< Сообщение Modbus - Input. */ PROTOCAN_MSGTYPE_ERROR = 0b1000, /**< Сообщение об ошибке. */ PROTOCAN_MSGTYPE_PULSE = 0b1111, /**< Импульсное сообщение. */ }ProtoCanMsgType; /** * @brief Типы широковещательных сообщений CAN. * * Перечисление задает различные типы широковещательных команд, используемых в протоколе. */ typedef enum { PROTOCAN_BROADCAST_STATUS = 0b000000000000, /**< Статус устройства. */ PROTOCAN_BROADCAST_ONOFF = 0b000000000001, /**< Включение/выключение устройства. */ PROTOCAN_BROADCAST_RESTARTDEVICE = 0b000000000010, /**< Перезагрузка устройства. */ PROTOCAN_BROADCAST_RTCSETUP = 0b000000000011, /**< Настройка RTC (часы реального времени). */ PROTOCAN_BROADCAST_END = 0b111111111111 /**< Конец диапазона широковещательных сообщений. */ }ProtoCanBroadcastType; /** * @brief Структура и представление широковещательного сообщения CAN. * * Объединение позволяет обращаться к данным сообщения либо как к отдельным полям, либо как к целому 16-битному значению. */ typedef union{ struct msgBody_Broadcast{ unsigned Body:4; /**< Поле для дополнительных данных или кода задачи (4 бита). */ ProtoCanBroadcastType Type:12; /**< Тип широковещательного сообщения (12 бит). */ } Fields; /**< Структура с разбивкой по полям. */ unsigned Body; /**< Общее 16-битное представление сообщения. */ } msgBodyBroadcastType; /** * @brief Типы дискретных сообщений CAN. * * Перечисление задает различные виды дискретных команд или событий. */ typedef enum { PROTOCAN_DISCRETE_ACCIDENT = 0b0000, /**< Аварийное состояние. */ PROTOCAN_DISCRETE_WARNING = 0b0001, /**< Предупредительный сигнал. */ PROTOCAN_DISCRETE_CONTROL_SIGNALS = 0b0010, /**< Управляющие сигналы. */ PROTOCAN_DISCRETE_FLAGS = 0b0011, /**< Флаги состояния. */ PROTOCAN_DISCRETE_RESET = 0b0100, /**< Сброс устройства. */ PROTOCAN_DISCRETE_CHANGE_MODE = 0b0101, /**< Смена режима работы. */ PROTOCAN_DISCRETE_REQUEST_LIST_OF_PARAMETERS = 0b0110, /**< Запрос списка параметров. */ PROTOCAN_DISCRETE_END = 0b1111 /**< Конец диапазона дискретных сообщений. */ }ProtoCanDiscreteType; /** * @brief Структура и представление дискретного сообщения CAN. * * Объединение позволяет обращаться к данным сообщения как к отдельным полям или как к целому 16-битному значению. */ typedef union{ struct msgBody_Discrete{ unsigned Body:12; /**< Поле данных или кода (12 бит). */ ProtoCanDiscreteType Type:4; /**< Тип дискретного сообщения (4 бита). */ } Fields; /**< Структура с разбивкой по полям. */ unsigned Body; /**< Общее 16-битное представление сообщения. */ } msgBodyDiscreteType; /** * @brief Типы аналоговых сообщений CAN. * * Перечисление определяет различные типы аналоговых данных или команд. */ typedef enum { PROTOCAN_ANALOG_UNIVERSAL = 0b0000, /**< Универсальный тип. */ PROTOCAN_ANALOG_SETTINGS = 0b0001, /**< Настройки. */ PROTOCAN_ANALOG_U = 0b0010, /**< Напряжение (U). */ PROTOCAN_ANALOG_I = 0b0011, /**< Ток (I). */ PROTOCAN_ANALOG_T = 0b0100, /**< Температура (T). */ PROTOCAN_ANALOG_END = 0b1111 /**< Конец диапазона типов. */ }ProtoCanAnalogType; /** * @brief Структура и представление аналогового сообщения CAN. * * Объединение позволяет обращаться к данным сообщения как к отдельным полям или как к целому 16-битному значению. */ typedef union{ struct msgBody_Analog{ unsigned SensorID:12; /**< Идентификатор датчика (12 бит). */ ProtoCanAnalogType Type:4; /**< Тип аналоговых данных (4 бита). */ } Fields; /**< Структура с разбивкой по полям. */ unsigned Body; /**< Общее 16-битное представление сообщения. */ }msgBodyAnalogType; /** * @brief Структура и представление сообщения Modbus CAN. * * Объединение позволяет обращаться к данным как к отдельным полям или как к целому 16-битному значению. */ typedef union{ struct msgBody_Modbus{ unsigned RegCount:4; /**< Количество регистров (4 бита). */ unsigned StrAdr:12; /**< Адрес строки или регистра (12 бит). */ } Fields; /**< Поля структуры сообщения Modbus. */ unsigned Body; /**< Общее 16-битное представление сообщения. */ } msgBodyModbusType; /** * @brief Структура и представление сообщения об ошибке CAN. * * Объединение позволяет обращаться к данным как к отдельным полям или как к целому 16-битному значению. */ typedef union{ struct msgBody_Error{ unsigned ErrorCode:8; /**< Код ошибки (8 бит). */ unsigned Info:8; /**< Дополнительная информация (8 бит). */ } Fields; /**< Поля ошибки. */ unsigned Body; /**< Общее 16-битное представление сообщения об ошибке. */ } msgBodyErrorType; struct controlflags{ unsigned IsPulse:1; unsigned IsRtrMode:1; }; /** * @brief Поля идентификатора протокола CAN. * * Объединение позволяет обращаться к различным полям идентификатора, а также как к 29-битному целому числу. */ typedef union{ struct protoCanIdFields{ unsigned MsgBody:16; /**< Поле сообщения (16 бит). */ ProtoCanMsgType MsgType:4; /**< Тип сообщения (4 бита). */ unsigned DeviceID:4; /**< Идентификатор устройства (4 бита). */ unsigned DeviceType:3; /**< Тип устройства (3 бита). */ ProtoCanRouteType Route:1; /**< Маршрут (1 бит). */ ProtoCanPriorityType Priority:1; /**< Приоритет (1 бит). */ } Fields; /**< Структура с разбивкой по полям. */ unsigned int BitAll:29; /**< Общее представление 29-битного идентификатора. */ } ProtoCanId_t; /** * @brief Структура для общего адресного пространства CAN. * * Используется для хранения данных о регистре и его содержимом. */ typedef struct{ struct ProtoCanGeneralAddressSpaceData{ uint16_t RegStartAdr; /**< Начальный адрес регистров. */ uint16_t *Data; /**< Указатель на массив данных. */ unsigned RegCount; /**< Количество регистров. */ } GeneralAddressSpaceData; } ProtoCanData_t; /** * @brief Структура данных устройства CAN. * * Включает статус, идентификатор, таймер последнего импульса и шаг последнего импульса. */ typedef struct{ unsigned Status:1; /**< Статус устройства (флаг). */ ProtoCanId_t Id; /**< Идентификатор CAN. */ unsigned TimeFromLastPulse; /**< Время с последнего импульса (мс). */ unsigned LastPulseStep; /**< Шаг последнего импульса. */ } ProtoCanDevice_t; struct RXMsg{ struct INFO{ unsigned EXT:1; unsigned RTR:1; }info; ProtoCanId_t eID; uint16_t DLC; uint8_t Data[8]; }; uint16_t AvailableCanRxMsg(void); PROTOCAN_INIT_StatusTypeDef PROTOCAN_INIT(CAN_HandleTypeDef *tmp_hcan, RTC_HandleTypeDef *tmp_hrtc, TIM_HandleTypeDef *tmp_tim); void PROTOCAN_DEINIT(uint8_t stage); void PROTOCAN_FILTERS(void); void PROTOCAN_LOOP(void); PROTOCAN_StatusTypeDef PROTOCAN_SEND(ProtoCanId_t id, ProtoCanData_t data); void ProtoCanPulseCallback(TIM_HandleTypeDef *htim); void ProtoCanRxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan); PROTOCAN_StatusTypeDef PROTOCAN_BroadcastProcessing(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToBroadcastStatus(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToBroadcastOnOff(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToBroadcastRestart(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToBroadcastRtcSetup(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef PROTOCAN_DiscreticProcessing(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToDiscreteAccident(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToDiscreteWarning(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToDiscreteControlSignals(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToDiscreteFlags(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToDiscreteReset(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToDiscreteChangeMode(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToDiscreteRequestListOfParameters(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef PROTOCAN_AnalogProcessing(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToAnalogUniversal(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToAnalogSettings(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToAnalogUSens(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToAnalogISens(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToAnalogTSens(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToGeneralAddressSpace(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef CanRequestError(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef PROTOCAN_ModbusProcessing(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToModbusCoil(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToModbusDiscrete(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToModbusHolding(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToModbusInput(struct RXMsg _rxMsg); void PROTOCAN_RTC_SYNC(uint8_t *data); #endif