Files
F103C8T6/Core/Inc/protocan.h

313 lines
15 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.
#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 ProtoCanCoreData{
uint16_t Type;
uint16_t Body;
uint8_t *Data;
unsigned DataCount;
} CoreData;
struct ProtoCanGeneralAddressSpaceData{
uint16_t RegStartAdr; /**< Начальный адрес регистров. */
uint16_t *Data; /**< Указатель на массив данных. */
unsigned RegCount; /**< Количество регистров. */
} GeneralAddressSpaceData;
struct ProtoCanModbusData{
uint16_t StrAdr;
uint16_t *Data;
unsigned RegCount:4;
} ModbusData;
struct ProtoCanErrorData{
uint16_t Info;
uint16_t Code;
} ErrorData;
} 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