ProtoCan
This commit is contained in:
@@ -31,7 +31,7 @@ extern "C" {
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "requester.h"
|
||||
#include "protocan.h"
|
||||
#include "canerrorbox.h"
|
||||
/* USER CODE END Includes */
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#ifndef _requester
|
||||
#define _requester
|
||||
#ifndef _protocan
|
||||
#define _protocan
|
||||
#include "main.h"
|
||||
#include "can.h"
|
||||
#include "rtc.h"
|
||||
#include "tim.h"
|
||||
|
||||
#define _DEMO
|
||||
|
||||
@@ -11,10 +9,7 @@
|
||||
#define OFFLINE 0;
|
||||
|
||||
// TIM defines
|
||||
#define TIM_REQUESTER_Prescaler 64000
|
||||
|
||||
//CAN Settings
|
||||
#define _HCAN hcan
|
||||
#define TIM_PROTOCAN_Prescaler 64000
|
||||
|
||||
//CAN Speed
|
||||
#define CAN_SPEED_PRSC_1000KB 2
|
||||
@@ -51,17 +46,6 @@ typedef union{
|
||||
char AllBit;
|
||||
}Byte;
|
||||
|
||||
/**
|
||||
* @brief HAL Status structures definition
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CRR_OK = 0x00U,
|
||||
CRR_ERROR = 0x01U,
|
||||
CRR_BUSY = 0x02U,
|
||||
CRR_TIMEOUT = 0x03U
|
||||
} CRR_Status;
|
||||
|
||||
_Bool IsLeapYear(uint8_t year);
|
||||
|
||||
#define COUNT_OF_MODBUS_SECTIONS 1
|
||||
@@ -176,25 +160,6 @@ typedef union{
|
||||
}Fields;
|
||||
unsigned int BitAll:29;
|
||||
}extID;
|
||||
|
||||
// typedef union{
|
||||
// struct extID_Fields{
|
||||
// union{
|
||||
// msgBodyBroadcast Broadcast;
|
||||
// msgBodyDiscrete Discrete;
|
||||
// msgBodyAnalog Analog;
|
||||
// msgBodyModbus Modbus;
|
||||
// msgBodyError Error;
|
||||
// unsigned Body:16;
|
||||
// }Msg;
|
||||
// unsigned MsgType:4;
|
||||
// unsigned DeviceID:4;
|
||||
// unsigned DeviceType:3;
|
||||
// unsigned Route:1;
|
||||
// unsigned Priority:1;
|
||||
// }Fields;
|
||||
// unsigned int BitAll:29;
|
||||
//}extID;
|
||||
|
||||
struct device{
|
||||
unsigned Status:1;
|
||||
@@ -299,45 +264,51 @@ struct RXMsg{
|
||||
uint8_t Data[8];
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PROTOCAN_OK = 0x00U,
|
||||
PROTOCAN_HCAN_ERROR = 0x01U,
|
||||
PROTOCAN_HRTC_ERROR = 0x02U,
|
||||
} PROTOCAN_INIT_StatusTypeDef;
|
||||
|
||||
uint16_t AvailableCanRxMsg(void);
|
||||
|
||||
void REQUESTER_Init(void);
|
||||
void REQUESTER_MainWhile(void);
|
||||
void Boot_SystemClock_Config(void);
|
||||
PROTOCAN_INIT_StatusTypeDef PROTOCAN_INIT(CAN_HandleTypeDef *tmp_hcan, RTC_HandleTypeDef *tmp_hrtc);
|
||||
void ProtoCanPulse_TIM_Handler(void);
|
||||
void PROTOCAN_FILTERS(void);
|
||||
void PROTOCAN_LOOP(void);
|
||||
|
||||
CRR_Status REQUESTER_AnalogProcessing(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef CanRequestToAnalogUniversal(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef CanRequestToAnalogUSTAVKI(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef CanRequestToAnalogUSens(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef CanRequestToAnalogISens(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef CanRequestToAnalogTSens(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef PROTOCAN_AnalogProcessing(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef ProtoCanMsgToAnalogUniversal(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef ProtoCanMsgToAnalogUSTAVKI(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef ProtoCanMsgToAnalogUSens(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef ProtoCanMsgToAnalogISens(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef ProtoCanMsgToAnalogTSens(struct RXMsg _rxMsg);
|
||||
|
||||
CRR_Status REQUESTER_BroadcastProcessing(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef CanRequestToBroadcastStatus(struct RXMsg _rxMsg);
|
||||
void CanRequestToBroadcastOnOff(struct RXMsg _rxMsg);
|
||||
void CanRequestToBroadcastRestart(struct RXMsg _rxMsg);
|
||||
void CanRequestToBroadcastRtcSetup(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef PROTOCAN_BroadcastProcessing(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef ProtoCanMsgToBroadcastStatus(struct RXMsg _rxMsg);
|
||||
void ProtoCanMsgToBroadcastOnOff(struct RXMsg _rxMsg);
|
||||
void ProtoCanMsgToBroadcastRestart(struct RXMsg _rxMsg);
|
||||
void ProtoCanMsgToBroadcastRtcSetup(struct RXMsg _rxMsg);
|
||||
|
||||
CRR_Status REQUESTER_DiscreticProcessing(struct RXMsg _rxMsg);
|
||||
void CanRequestToDiscreteAccident(struct RXMsg _rxMsg);
|
||||
void CanRequestToDiscreteWarning(struct RXMsg _rxMsg);
|
||||
void CanRequestToDiscreteControlSignals(struct RXMsg _rxMsg);
|
||||
void CanRequestToDiscreteFlags(struct RXMsg _rxMsg);
|
||||
void CanRequestToDiscreteReset(struct RXMsg _rxMsg);
|
||||
void CanRequestToDiscreteChangeMode(struct RXMsg _rxMsg);
|
||||
void CanRequestToDiscreteRequestListOfParameters(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef PROTOCAN_DiscreticProcessing(struct RXMsg _rxMsg);
|
||||
void ProtoCanMsgToDiscreteAccident(struct RXMsg _rxMsg);
|
||||
void ProtoCanMsgToDiscreteWarning(struct RXMsg _rxMsg);
|
||||
void ProtoCanMsgToDiscreteControlSignals(struct RXMsg _rxMsg);
|
||||
void ProtoCanMsgToDiscreteFlags(struct RXMsg _rxMsg);
|
||||
void ProtoCanMsgToDiscreteReset(struct RXMsg _rxMsg);
|
||||
void ProtoCanMsgToDiscreteChangeMode(struct RXMsg _rxMsg);
|
||||
void ProtoCanMsgToDiscreteRequestListOfParameters(struct RXMsg _rxMsg);
|
||||
|
||||
void REQUESTER_GeneralAddressSpace_Answer(struct RXMsg _rxMsg);
|
||||
void PROTOCAN_GeneralAddressSpace_Answer(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef CanRequestError(struct RXMsg _rxMsg);
|
||||
|
||||
CRR_Status REQUESTER_ModbusProcessing(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef CanRequestToModbusCoil(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef CanRequestToModbusDiscrete(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef CanRequestToModbusHolding(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef CanRequestToModbusInput(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef PROTOCAN_ModbusProcessing(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef ProtoCanMsgToModbusCoil(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef ProtoCanMsgToModbusDiscrete(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef ProtoCanMsgToModbusHolding(struct RXMsg _rxMsg);
|
||||
HAL_StatusTypeDef ProtoCanMsgToModbusInput(struct RXMsg _rxMsg);
|
||||
|
||||
void PROTOCAN_RTC_SYNC(uint8_t *data);
|
||||
|
||||
void REQUESTER_RTC_SYNC(uint8_t *data);
|
||||
void REQUESTER_Pulse_TIM_Handler(void);
|
||||
void Boot_SystemClock_Config(void);
|
||||
void REQUESTER_CAN_FILTERS(void);
|
||||
#endif
|
||||
@@ -134,7 +134,7 @@
|
||||
#define PREFETCH_ENABLE 1U
|
||||
|
||||
#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */
|
||||
#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */
|
||||
#define USE_HAL_CAN_REGISTER_CALLBACKS 1U /* CAN register callback enabled */
|
||||
#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */
|
||||
#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */
|
||||
#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */
|
||||
|
||||
@@ -68,8 +68,6 @@ int main(void)
|
||||
{
|
||||
/* USER CODE BEGIN 1 */
|
||||
SystemClock_Config();
|
||||
REQUESTER_Init();
|
||||
REQUESTER_MainWhile();
|
||||
/* USER CODE END 1 */
|
||||
|
||||
/* MCU Configuration--------------------------------------------------------*/
|
||||
|
||||
991
Core/Src/protocan.c
Normal file
991
Core/Src/protocan.c
Normal file
@@ -0,0 +1,991 @@
|
||||
#include "protocan.h"
|
||||
|
||||
struct device CurrentDevice;
|
||||
struct device Device_on_the_Network[8][16];
|
||||
struct controlflags ControlFlags;
|
||||
|
||||
CAN_HandleTypeDef *_HCAN = 0;
|
||||
RTC_HandleTypeDef *_HRTC = 0;
|
||||
|
||||
uint8_t CurrentStep = 1;
|
||||
uint8_t LastStep = 0;
|
||||
struct RXMsg rxMsg[CAN_RX_BUFFER_SIZE];
|
||||
|
||||
/**
|
||||
* @brief Проверяет, является ли год високосным.
|
||||
* В системе год хранится как смещение от 2000. Например, значение 24 соответствует 2024.
|
||||
* Эта функция добавляет 2000 к значению и проверяет, високосный ли получившийся год.
|
||||
* @param year Смещение от 2000, тип uint8_t (от 0 до 255).
|
||||
* @return _Bool true, если год високосный; false — иначе.
|
||||
*/
|
||||
_Bool IsLeapYear(uint8_t year)
|
||||
{
|
||||
year+=2000;
|
||||
return (year%400==0)||((year%4==0)&&(year%100!=0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Возвращает количество доступных сообщений в буфере приёма CAN.
|
||||
* Используется кольцевой буфер.
|
||||
* Возвращаемое значение — количество элементов между указателями LastStep и CurrentStep.
|
||||
* @return uint16_t Количество доступных сообщений, ожидающих обработки, в буфере.
|
||||
*/
|
||||
uint16_t AvailableCanRxMsg(void)
|
||||
{
|
||||
return ((uint16_t)(CAN_RX_BUFFER_SIZE + (LastStep - CurrentStep + 1)))%CAN_RX_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Инициализация переферии
|
||||
* @details Инициализация указателей на HCAN, HRTC, установка фильтров CAN.
|
||||
* @note Фильтры CAN описаны в разделе PROTOCAN_CAN_FILTERS().
|
||||
*/
|
||||
PROTOCAN_INIT_StatusTypeDef PROTOCAN_INIT(CAN_HandleTypeDef *tmp_hcan, RTC_HandleTypeDef *tmp_hrtc)
|
||||
{
|
||||
//HAL_CAN_Start(_HCAN);
|
||||
//HAL_CAN_ActivateNotification(_HCAN, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_ERROR | CAN_IT_BUSOFF | CAN_IT_LAST_ERROR_CODE);
|
||||
//MX_TIM4_Init();
|
||||
//MX_RTC_Init();
|
||||
if(tmp_hcan)
|
||||
_HCAN = tmp_hcan;
|
||||
else
|
||||
return PROTOCAN_HCAN_ERROR;
|
||||
if(tmp_hrtc)
|
||||
_HRTC = tmp_hrtc;
|
||||
else
|
||||
return PROTOCAN_HRTC_ERROR;
|
||||
PROTOCAN_FILTERS();
|
||||
ControlFlags.IsPulse = 1;
|
||||
return PROTOCAN_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция с обработкой полученных запросов
|
||||
* @details В бесконечном цикле функция ожидает приёма сообщения. После этого сообщение распределяется в зависимости от DataType.
|
||||
* Обработка запроса аналоговых значений - PROTOCAN_AnalogProcessing().
|
||||
* Обработка широковещательных запросов - PROTOCAN_BroadcastProcessing().
|
||||
* Обработка запроса дискретных значений - PROTOCAN_DiscreticProcessing().
|
||||
* Обработка Modbus - PROTOCAN_ModbusProcessing().
|
||||
*/
|
||||
void PROTOCAN_LOOP(void)
|
||||
{
|
||||
//HAL_TIM_Base_Start_IT(&htim4);
|
||||
while(1)
|
||||
{
|
||||
if(AvailableCanRxMsg())
|
||||
{
|
||||
if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_ANALOG)
|
||||
{
|
||||
PROTOCAN_AnalogProcessing(rxMsg[CurrentStep]);
|
||||
}
|
||||
else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_BROADCAST)
|
||||
{
|
||||
PROTOCAN_BroadcastProcessing(rxMsg[CurrentStep]);
|
||||
}
|
||||
else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_DISCRETE)
|
||||
{
|
||||
PROTOCAN_DiscreticProcessing(rxMsg[CurrentStep]);
|
||||
}
|
||||
else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_GENERAL_ADDRESS_SPACE)
|
||||
{
|
||||
PROTOCAN_GeneralAddressSpace_Answer(rxMsg[CurrentStep]);
|
||||
}
|
||||
else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_MODBUS_COIL ||
|
||||
rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_MODBUS_DISCRETE ||
|
||||
rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_MODBUS_HOLDING ||
|
||||
rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_MODBUS_INPUT)
|
||||
{
|
||||
PROTOCAN_ModbusProcessing(rxMsg[CurrentStep]);
|
||||
}
|
||||
else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_ERROR)
|
||||
{
|
||||
CanRequestError(rxMsg[CurrentStep]);
|
||||
}
|
||||
CurrentStep = (uint16_t)(CurrentStep + 1) % CAN_RX_BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция обработки аналоговых запросов.
|
||||
* @param struct RXMsg _rxMsg - структура для полученного сообщения.
|
||||
* @details Функция, сортирующая запросы по типам и вызывающая соответствующие функции. Типы запросов: Универсальный, Уставки, Напряжение, Ток, Температура.
|
||||
* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка).
|
||||
*/
|
||||
HAL_StatusTypeDef PROTOCAN_AnalogProcessing(struct RXMsg _rxMsg)
|
||||
{
|
||||
msgAnalogType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
switch (msg.Fields.SensorType)
|
||||
{
|
||||
case SENSOR_TYPE_ANALOG_UNIVERSAL:
|
||||
{
|
||||
return ProtoCanMsgToAnalogUniversal(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_ANALOG_USTAVKI:
|
||||
{
|
||||
return ProtoCanMsgToAnalogUSTAVKI(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_ANALOG_U:
|
||||
{
|
||||
return ProtoCanMsgToAnalogUSens(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_ANALOG_I:
|
||||
{
|
||||
return ProtoCanMsgToAnalogISens(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_ANALOG_T:
|
||||
{
|
||||
return ProtoCanMsgToAnalogTSens(_rxMsg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//RESERVE SENSOR TYPE
|
||||
return HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция ответа на запрос данных со всех датчиков.
|
||||
* Создает сообщение с определенными данными и отправляет его через CAN-шину.
|
||||
* @param _rxMsg Структура входящего сообщения, используется для формирования ID.
|
||||
* @return HAL_StatusTypeDef Статус выполнения операции HAL, например HAL_OK.
|
||||
*/
|
||||
__weak HAL_StatusTypeDef ProtoCanMsgToAnalogUniversal(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 6;
|
||||
data[0] = 'U';
|
||||
data[1] = 'N';
|
||||
data[2] = 'I';
|
||||
data[3] = 'V';
|
||||
data[4] = 'E';
|
||||
data[5] = 'R';
|
||||
return HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция ответа на запрос уставок по CAN.
|
||||
* Создает сообщение с определенными данными и отправляет его через CAN-шину.
|
||||
* @param _rxMsg Структура входящего сообщения, используется только для формирования ID.
|
||||
* @return HAL_StatusTypeDef Статус выполнения операции HAL, например HAL_OK.
|
||||
*/
|
||||
__weak HAL_StatusTypeDef ProtoCanMsgToAnalogUSTAVKI(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 7;
|
||||
data[0] = 'U';
|
||||
data[1] = 'S';
|
||||
data[2] = 'T';
|
||||
data[3] = 'A';
|
||||
data[4] = 'V';
|
||||
data[5] = 'K';
|
||||
data[6] = 'I';
|
||||
return HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция ответа на запрос данных с датчиков напряжения.
|
||||
* Создает сообщение с указанными параметрами и отправляет его через CAN-шину.
|
||||
* @param _rxMsg Структура входящего сообщения, используемая для формирования идентификатора и данных.
|
||||
* @return HAL_StatusTypeDef Статус выполнения операции HAL, например HAL_OK при успешной отправке.
|
||||
*/
|
||||
__weak HAL_StatusTypeDef ProtoCanMsgToAnalogUSens(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 6;
|
||||
msgAnalogType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'U';
|
||||
data[1] = 'S';
|
||||
data[2] = 47 + msg.Fields.SensorID / 1000;
|
||||
data[3] = 47 + msg.Fields.SensorID / 100 % 10;
|
||||
data[4] = 47 + msg.Fields.SensorID / 10 % 10;
|
||||
data[5] = 47 + msg.Fields.SensorID % 10;
|
||||
return HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция ответа на запрос данных с датчиков тока.
|
||||
* Создает сообщение с определенными параметрами и отправляет его через CAN-шину.
|
||||
* @param _rxMsg Структура входящего сообщения, используется для формирования идентификатора и данных.
|
||||
* @return HAL_StatusTypeDef Статус операции HAL, например HAL_OK при успешной отправке.
|
||||
*/
|
||||
__weak HAL_StatusTypeDef ProtoCanMsgToAnalogISens(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 6;
|
||||
msgAnalogType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'I';
|
||||
data[1] = 'S';
|
||||
data[2] = 47 + msg.Fields.SensorID / 1000;
|
||||
data[3] = 47 + msg.Fields.SensorID / 100 % 10;
|
||||
data[4] = 47 + msg.Fields.SensorID / 10 % 10;
|
||||
data[5] = 47 + msg.Fields.SensorID % 10;
|
||||
return HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция ответа на запрос данных с датчиков температуры.
|
||||
* Создает сообщение с определенным заголовком, формирует данные по ID сенсора и отправляет его через CAN.
|
||||
* @param _rxMsg Структура полученного сообщения, которая используется для формирования идентификатора.
|
||||
* @return HAL_StatusTypeDef Статус выполнения функции HAL, например HAL_OK при успехе.
|
||||
*/
|
||||
__weak HAL_StatusTypeDef ProtoCanMsgToAnalogTSens(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 6;
|
||||
msgAnalogType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'T';
|
||||
data[1] = 'S';
|
||||
data[2] = 47 + msg.Fields.SensorID / 1000;
|
||||
data[3] = 47 + msg.Fields.SensorID / 100 % 10;
|
||||
data[4] = 47 + msg.Fields.SensorID / 10 % 10;
|
||||
data[5] = 47 + msg.Fields.SensorID % 10;
|
||||
return HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция обработки широковещательных запросов.
|
||||
* @param struct RXMsg _rxMsg - структура для полученного сообщения.
|
||||
* @details Функция, выполняющая команды, переданные в широковещательном формате с головного (master) устройства. Типы команд: Запрос статуса, запрос на включение или выключение, рестарт устройств, установка времени.
|
||||
* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка).
|
||||
*/
|
||||
HAL_StatusTypeDef PROTOCAN_BroadcastProcessing(struct RXMsg _rxMsg)
|
||||
{
|
||||
msgBroadcastType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
switch(msg.Fields.BroadcastType)
|
||||
{
|
||||
case SENSOR_TYPE_BROADCAST_STATUS:
|
||||
{
|
||||
//Обработка запроса статуса устройства
|
||||
return ProtoCanMsgToBroadcastStatus(_rxMsg);
|
||||
}
|
||||
case SENSOR_TYPE_BROADCAST_ONOFF:
|
||||
{
|
||||
//Обработка запроса на вкл/выкл
|
||||
ProtoCanMsgToBroadcastOnOff(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_BROADCAST_RESTARTDEVICE:
|
||||
{
|
||||
ProtoCanMsgToBroadcastRestart(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_BROADCAST_RTCSETUP:
|
||||
{
|
||||
//Обработка запроса на синхронизацию времени
|
||||
//С головным устройством
|
||||
ProtoCanMsgToBroadcastRtcSetup(_rxMsg);
|
||||
break;;
|
||||
}
|
||||
default:
|
||||
//RESERVE SENSOR TYPE.
|
||||
return HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Формирует и отправляет широковещательное CAN-сообщение для ответа на запрос статуса.
|
||||
* Устанавливает идентификатор, собирает текущие параметры времени и даты, и отправляет сообщение.
|
||||
* @param _rxMsg Структура полученного по CAN запроса.
|
||||
* @return HAL_StatusTypeDef Статус операции HAL, например HAL_OK при успехе.
|
||||
*/
|
||||
__weak HAL_StatusTypeDef ProtoCanMsgToBroadcastStatus(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.DLC = 7;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
tmp_eID.Fields.DeviceType = CURRENT_TYPE_DEVICE;
|
||||
tmp_eID.Fields.DeviceID = CURRENT_ID_DEVICE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
|
||||
RTC_TimeTypeDef sTime = {0};
|
||||
HAL_RTC_GetTime(_HRTC, &sTime, RTC_FORMAT_BIN);
|
||||
data[0] = sTime.Hours;
|
||||
data[1] = sTime.Minutes;
|
||||
data[2] = sTime.Seconds;
|
||||
|
||||
RTC_DateTypeDef DateToUpdate = {0};
|
||||
HAL_RTC_GetDate(_HRTC, &DateToUpdate, RTC_FORMAT_BIN);
|
||||
data[3] = DateToUpdate.Year;
|
||||
data[4] = DateToUpdate.Month;
|
||||
data[5] = DateToUpdate.Date;
|
||||
data[6] = DateToUpdate.WeekDay;
|
||||
|
||||
return HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Виртуальная слабая функция для переключения режима пульсации ON/OFF.
|
||||
* Меняет состояние флага IsPulse в структуре ControlFlags.
|
||||
* В данном случае — просто инвертирует его логическое значение.
|
||||
* @param _rxMsg Структура полученного CAN-сообщения (Пока не используется в функции).
|
||||
*/
|
||||
__weak void ProtoCanMsgToBroadcastOnOff(struct RXMsg _rxMsg)
|
||||
{
|
||||
ControlFlags.IsPulse = !ControlFlags.IsPulse;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief __weak функция для обработки широковещательного сообщения перезапуска устройства.
|
||||
* Проверяет длину сообщения, извлекает ID из данных и, если она совпадает с текущим устройством,
|
||||
* вызывает системный перезапуск.
|
||||
* @param _rxMsg Структура полученного CAN-сообщения с командой перезапуска.
|
||||
*/
|
||||
__weak void ProtoCanMsgToBroadcastRestart(struct RXMsg _rxMsg)
|
||||
{
|
||||
if(_rxMsg.DLC == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
msgBroadcastType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
if(msg.Fields.Page == (CURRENT_ID_DEVICE / (_rxMsg.DLC*8)))
|
||||
{
|
||||
uint64_t page = 0;
|
||||
for(int i = 0; i < _rxMsg.DLC; i++)
|
||||
{
|
||||
page+=(_rxMsg.Data[i]<<(i*8));
|
||||
}
|
||||
if((page>>CURRENT_ID_DEVICE)&0b1)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief __weak функция для обработки запроса на синхронизацию RTC через широковещательное сообщение.
|
||||
* Проверяет длину сообщения и корректность данных (время и дата). Если все проверки пройдены,
|
||||
* вызывает функцию синхронизации RTC.
|
||||
* @param _rxMsg Структура полученного CAN-сообщения с данными для установки времени и даты.
|
||||
*/
|
||||
__weak void ProtoCanMsgToBroadcastRtcSetup(struct RXMsg _rxMsg)
|
||||
{
|
||||
if(_rxMsg.DLC > 7) {
|
||||
//ERROR
|
||||
} else {
|
||||
int DaysCount_Normal[2][12] = {{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||||
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
|
||||
if( _rxMsg.Data[0] > 23 ||
|
||||
_rxMsg.Data[1] > 59 ||
|
||||
_rxMsg.Data[2] > 59 ||
|
||||
_rxMsg.Data[3] > 99 ||
|
||||
_rxMsg.Data[4] > 12 ||
|
||||
_rxMsg.Data[5] > DaysCount_Normal[IsLeapYear(_rxMsg.Data[3])][_rxMsg.Data[4]] ||
|
||||
_rxMsg.Data[6] > 6) {
|
||||
//ERROR
|
||||
} else {
|
||||
PROTOCAN_RTC_SYNC(_rxMsg.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция обработки дискретных запросов.
|
||||
* @param struct RXMsg _rxMsg - структура для полученного сообщения.
|
||||
* @details Функция, формирующая и отправляющая ответ на запросы. Типы запросов: Аварии, Предупреждения, Управляющие сигналы, Флаги, Рестарт устройства, Изменение режима работы устройства, Запрос на устройство.
|
||||
* @note Запрос на устройство. Головное (master) устройство запрашивает некоторое колличество параметров. В Data - 64 битовых адресса параметров, тип которых задаётся в Sensor ID. Имеется возможность запрашивать непоследовательные параметры.
|
||||
* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка).
|
||||
*/
|
||||
HAL_StatusTypeDef PROTOCAN_DiscreticProcessing(struct RXMsg _rxMsg)
|
||||
{
|
||||
msgDiscreteType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
switch(msg.Fields.Type){
|
||||
case SENSOR_TYPE_DISCRETE_ACCIDENT:
|
||||
{
|
||||
ProtoCanMsgToDiscreteAccident(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_DISCRETE_WARNING:
|
||||
{
|
||||
ProtoCanMsgToDiscreteWarning(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_DISCRETE_CONTROL_SIGNALS:
|
||||
{
|
||||
ProtoCanMsgToDiscreteControlSignals(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_DISCRETE_FLAGS:
|
||||
{
|
||||
ProtoCanMsgToDiscreteFlags(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_DISCRETE_RESET:
|
||||
{
|
||||
ProtoCanMsgToDiscreteReset(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_DISCRETE_CHANGE_MODE:
|
||||
{
|
||||
ProtoCanMsgToDiscreteChangeMode(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_DISCRETE_REQUEST_LIST_OF_PARAMETERS:
|
||||
{
|
||||
ProtoCanMsgToDiscreteRequestListOfParameters(_rxMsg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//RESERVE SENSOR TYPE.
|
||||
return HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обработка запроса аварийных ситуаций.
|
||||
* В текущей реализации — заглушка, ничего не выполняет.
|
||||
* Можно реализовать отправку или обработку аварийных данных.
|
||||
* @param _rxMsg Входящее сообщение с данными запроса.
|
||||
*/
|
||||
__weak void ProtoCanMsgToDiscreteAccident(struct RXMsg _rxMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обработка запроса предупреждений.
|
||||
* В текущей реализации — заглушка.
|
||||
* Можно реализовать обработку или ответ на предупреждения.
|
||||
* @param _rxMsg Входящее сообщение.
|
||||
*/
|
||||
__weak void ProtoCanMsgToDiscreteWarning(struct RXMsg _rxMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обработка запроса управляющих сигналов.
|
||||
* В текущей реализации — заглушка.
|
||||
* Можно реализовать управление сигналами.
|
||||
* @param _rxMsg Входящее сообщение.
|
||||
*/
|
||||
__weak void ProtoCanMsgToDiscreteControlSignals(struct RXMsg _rxMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обработка запроса флагов.
|
||||
* В текущей реализации — заглушка.
|
||||
* Можно реализовать работу с флагами.
|
||||
* @param _rxMsg Входящее сообщение.
|
||||
*/
|
||||
__weak void ProtoCanMsgToDiscreteFlags(struct RXMsg _rxMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обработка рестарта системы по CAN-запросу.
|
||||
* Выполняет программный рестарт системы.
|
||||
* @param _rxMsg Входящее сообщение.
|
||||
*/
|
||||
__weak void ProtoCanMsgToDiscreteReset(struct RXMsg _rxMsg)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обработка запроса на изменение режима.
|
||||
* В текущей реализации — заглушка.
|
||||
* Можно реализовать изменение режима работы.
|
||||
* @param _rxMsg Входящее сообщение.
|
||||
*/
|
||||
__weak void ProtoCanMsgToDiscreteChangeMode(struct RXMsg _rxMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обработка запроса на получение списка параметров.
|
||||
* В текущей реализации — заглушка.
|
||||
* Можно реализовать отправку списка параметров.
|
||||
* @param _rxMsg Входящее сообщение.
|
||||
*/
|
||||
__weak void ProtoCanMsgToDiscreteRequestListOfParameters(struct RXMsg _rxMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обработка и ответ на запрос общего адресного пространства.
|
||||
* Формирует и передает сообщение с данными о статусе "GAS-XXXX", где XXXX — значение из сообщения _rxMsg.
|
||||
* @param _rxMsg Структура входящего сообщения, содержит идентификатор и тело сообщения.
|
||||
*/
|
||||
void PROTOCAN_GeneralAddressSpace_Answer(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 8;
|
||||
data[0] = 'G';
|
||||
data[1] = 'A';
|
||||
data[2] = 'S';
|
||||
data[3] = '-';
|
||||
for(int i = 0; i < 4; i++) {
|
||||
unsigned sym = (_rxMsg.eID.Fields.MsgBody>>(12-(i*4)))&0xF;
|
||||
if(sym >= 10)
|
||||
data[4+i] = sym%10+'A';
|
||||
else
|
||||
data[4+i] = sym+'0';
|
||||
}
|
||||
HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обработка запроса на основе типа Modbus.
|
||||
* В зависимости от типа сообщения, вызывает соответствующую функцию
|
||||
* для отправки Modbus-запроса по CAN-шине.
|
||||
* @param _rxMsg Структура входящего сообщения RXMsg.
|
||||
* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка).
|
||||
*/
|
||||
HAL_StatusTypeDef PROTOCAN_ModbusProcessing(struct RXMsg _rxMsg)
|
||||
{
|
||||
switch(_rxMsg.eID.Fields.MsgType)
|
||||
{
|
||||
case DATA_TYPE_MODBUS_COIL:
|
||||
{
|
||||
return ProtoCanMsgToModbusCoil(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_MODBUS_DISCRETE:
|
||||
{
|
||||
return ProtoCanMsgToModbusDiscrete(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_MODBUS_HOLDING:
|
||||
{
|
||||
return ProtoCanMsgToModbusHolding(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_MODBUS_INPUT:
|
||||
{
|
||||
return ProtoCanMsgToModbusInput(_rxMsg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//ERROR
|
||||
return HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief __weak Функция отправки ответа на запрос Coil Modbus по CAN.
|
||||
* Формирует CAN ответ на запрос Coil Modbus и отправляет его.
|
||||
* @param _rxMsg Структура входящего сообщения RXMsg.
|
||||
* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка).
|
||||
*/
|
||||
__weak HAL_StatusTypeDef ProtoCanMsgToModbusCoil(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 8;
|
||||
msgModbusType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'M';
|
||||
data[1] = 'C';
|
||||
data[2] = ' ';
|
||||
data[3] = 'S';
|
||||
data[4] = msg.Fields.StrAdr;
|
||||
data[5] = ' ';
|
||||
data[6] = 'C';
|
||||
data[7] = msg.Fields.RegCount;
|
||||
return HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief __weak Функция отправки ответа на запрос Discrete Modbus по CAN.
|
||||
* Формирует CAN ответ на запрос Discrete Modbus и отправляет его.
|
||||
* @param _rxMsg Структура входящего сообщения RXMsg.
|
||||
* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка).
|
||||
*/
|
||||
__weak HAL_StatusTypeDef ProtoCanMsgToModbusDiscrete(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 8;
|
||||
msgModbusType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'M';
|
||||
data[1] = 'D';
|
||||
data[2] = ' ';
|
||||
data[3] = 'S';
|
||||
data[4] = msg.Fields.StrAdr;
|
||||
data[5] = ' ';
|
||||
data[6] = 'C';
|
||||
data[7] = msg.Fields.RegCount;
|
||||
return HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief __weak Функция отправки ответа на запрос Holding Modbus по CAN.
|
||||
* Формирует CAN ответ на запрос Holding Modbus и отправляет его.
|
||||
* @param _rxMsg Структура входящего сообщения RXMsg.
|
||||
* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка).
|
||||
*/
|
||||
__weak HAL_StatusTypeDef ProtoCanMsgToModbusHolding(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 8;
|
||||
msgModbusType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'M';
|
||||
data[1] = 'H';
|
||||
data[2] = ' ';
|
||||
data[3] = 'S';
|
||||
data[4] = msg.Fields.StrAdr;
|
||||
data[5] = ' ';
|
||||
data[6] = 'C';
|
||||
data[7] = msg.Fields.RegCount;
|
||||
return HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief __weak Функция отправки ответа на запрос Input Modbus по CAN.
|
||||
* Формирует CAN ответ на запрос Input Modbus и отправляет его.
|
||||
* @param _rxMsg Структура входящего сообщения RXMsg.
|
||||
* @return HAL_StatusTypeDef Статус выполнения команды CAN (успех или ошибка).
|
||||
*/
|
||||
__weak HAL_StatusTypeDef ProtoCanMsgToModbusInput(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 8;
|
||||
msgModbusType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'M';
|
||||
data[1] = 'I';
|
||||
data[2] = ' ';
|
||||
data[3] = 'S';
|
||||
data[4] = msg.Fields.StrAdr;
|
||||
data[5] = ' ';
|
||||
data[6] = 'C';
|
||||
data[7] = msg.Fields.RegCount;
|
||||
return HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief __weak Функция отправки сообщения об ошибке.
|
||||
* Посылает CAN сообщение с кодом ошибки. Используется, когда необходимо оповестить о неуспешной операции.
|
||||
* @param _rxMsg Структура входящего сообщения RXMsg, данными которого формируется ответ-ошибка.
|
||||
* @return HAL_StatusTypeDef Статус выполнения команды CAN.
|
||||
*/
|
||||
__weak HAL_StatusTypeDef CanRequestError(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
tmp_eID.Fields.MsgType = DATA_TYPE_ERROR;
|
||||
msgErrorType msg;
|
||||
msg.Fields.ErrorCode = 0xFF;
|
||||
msg.Fields.Info = 0;
|
||||
tmp_eID.Fields.MsgBody = msg.Body;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 0;
|
||||
return HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Записывает полученное сообщение CAN в буфер rxMsg.
|
||||
* Копирует параметры расширенного ID, типы, длину данных и сам данные в указанный элемент буфера.
|
||||
* @param tmp_eID Расширенный ID сообщения.
|
||||
* @param tmp_IDE Тип идентификатора (например, CAN_ID_EXT).
|
||||
* @param tmp_RTR Тип запроса (например, CAN_RTR_DATA).
|
||||
* @param tmp_DLC Длина данных в сообщении.
|
||||
* @param tmp_DATA Указатель на массив данных, полученных из CAN.
|
||||
* @param tmp_LastStep Индекс позиции в буфере, куда записывать сообщение.
|
||||
*/
|
||||
void TakeRxMsgToBuffer(extID tmp_eID, uint32_t tmp_IDE, uint32_t tmp_RTR, uint32_t tmp_DLC, uint8_t *tmp_DATA, uint16_t tmp_LastStep)
|
||||
{
|
||||
rxMsg[tmp_LastStep].eID.BitAll = tmp_eID.BitAll;
|
||||
rxMsg[tmp_LastStep].info.EXT = tmp_IDE;
|
||||
rxMsg[tmp_LastStep].info.RTR = tmp_RTR;
|
||||
rxMsg[tmp_LastStep].DLC = tmp_DLC;
|
||||
for(int i = 0; i < tmp_DLC; i++)
|
||||
{
|
||||
rxMsg[tmp_LastStep].Data[i] = tmp_DATA[i];
|
||||
}
|
||||
LastStep = tmp_LastStep;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обработка сообщений, ожидающих в FIFO, по прерыванию HAL_CAN_RxFifo0MsgPendingCallback.
|
||||
* Читает все сообщения из FIFO, проверяет их тип, обновляет статус устройств сети или сохраняет сообщение в буфер.
|
||||
* @param hcan Указатель на структуру управления CAN-Hardware.
|
||||
*/
|
||||
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
//Обработка всех сообщений в FIFO
|
||||
CAN_RxHeaderTypeDef RxHeader;
|
||||
uint8_t RCAN_Data[8];
|
||||
while(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RCAN_Data) == HAL_OK)
|
||||
{
|
||||
//Расширенный ID
|
||||
if(RxHeader.IDE == CAN_ID_EXT)
|
||||
{
|
||||
if(!((CAN_RX_BUFFER_SIZE + LastStep - (CurrentStep-1))&CAN_RX_BUFFER_SIZE))
|
||||
{
|
||||
//Буффер переполнен
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t tmp_LastStep = (uint16_t)(LastStep + 1) % CAN_RX_BUFFER_SIZE;
|
||||
|
||||
extID ExtID_Of_RX_MSG;
|
||||
ExtID_Of_RX_MSG.BitAll = RxHeader.ExtId;
|
||||
|
||||
//Полученное сообщение - пульс устройств в сети
|
||||
if(ExtID_Of_RX_MSG.Fields.MsgType == DATA_TYPE_PULSE)
|
||||
{
|
||||
Device_on_the_Network[ExtID_Of_RX_MSG.Fields.DeviceType][ExtID_Of_RX_MSG.Fields.DeviceID].Status = ONLINE;
|
||||
Device_on_the_Network[ExtID_Of_RX_MSG.Fields.DeviceType][ExtID_Of_RX_MSG.Fields.DeviceID].TimeFromLastPulse = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
TakeRxMsgToBuffer(ExtID_Of_RX_MSG, RxHeader.IDE, RxHeader.RTR, RxHeader.DLC, RCAN_Data, tmp_LastStep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция отправки пульса устройства.
|
||||
* @details Пульс устройства. Есть возможность отключить пульс по запросу.
|
||||
*/
|
||||
void PROTOCAN_Pulse_TIM_Handler()
|
||||
{
|
||||
if(ControlFlags.IsPulse)
|
||||
{
|
||||
static unsigned PulseStage = 0;
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
extID currentID;
|
||||
currentID.BitAll = 0;
|
||||
currentID.Fields.MsgBody = 0;
|
||||
currentID.Fields.DeviceID = CURRENT_ID_DEVICE;
|
||||
currentID.Fields.DeviceType = CURRENT_TYPE_DEVICE;
|
||||
currentID.Fields.MsgType = DATA_TYPE_PULSE;
|
||||
currentID.Fields.Route = ROUTE_SLAVE;
|
||||
currentID.Fields.Priority = PRIORITY_STANDARD;
|
||||
TxHeader.ExtId = currentID.BitAll;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
TxHeader.DLC = 1;
|
||||
PulseStage++;
|
||||
unsigned int debugID;
|
||||
debugID = currentID.BitAll;
|
||||
if(PulseStage > 0xFF){
|
||||
PulseStage = 0;
|
||||
}
|
||||
data[0] = PulseStage;
|
||||
HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция установки в RTC полученной даты/время из запроса.
|
||||
* @param uint8_t *data - Байтовый массив, 7 элементов. [0] - Часы. [1] - Минуты. [2] - Секунды. [3] - Год. [4] - Месяц. [5] - Дата. [6] - День недели.
|
||||
*/
|
||||
void PROTOCAN_RTC_SYNC(uint8_t *data)
|
||||
{
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(_HRTC);
|
||||
RTC_TimeTypeDef sTime = {0};
|
||||
RTC_DateTypeDef DateToUpdate = {0};
|
||||
|
||||
sTime.Hours = data[0];
|
||||
sTime.Minutes = data[1];
|
||||
sTime.Seconds = data[2];
|
||||
|
||||
if(HAL_RTC_SetTime(_HRTC, &sTime, RTC_FORMAT_BIN) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
DateToUpdate.Year = data[3];
|
||||
DateToUpdate.Month = data[4];
|
||||
DateToUpdate.Date = data[5];
|
||||
DateToUpdate.WeekDay = data[6];
|
||||
if(HAL_RTC_SetDate(_HRTC, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(_HRTC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Настройка CAN-Фильтра.
|
||||
* На основе переданных ID и маски настраивает фильтр CAN для приема только определённых сообщений.
|
||||
* @param filterBank Номер фильтра (обычно 0..27).
|
||||
* @param idFilter 32-битный идентификатор, используемый для фильтрации.
|
||||
* @param idMask 32-битная маска, определяющая биты, проверяемые фильтром.
|
||||
*/
|
||||
void PROTOCAN_CONFIG_FILTER(uint8_t filterBank, uint32_t idFilter, uint32_t idMask)
|
||||
{
|
||||
CAN_FilterTypeDef canFilterConfig;
|
||||
canFilterConfig.FilterBank = filterBank;
|
||||
canFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
|
||||
canFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
|
||||
canFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
|
||||
canFilterConfig.FilterActivation = ENABLE;
|
||||
canFilterConfig.SlaveStartFilterBank = 14;
|
||||
|
||||
// Разбиваем 32-битный ID и маску для фильтрации на High и Low 16 бит
|
||||
canFilterConfig.FilterIdHigh = (uint16_t)( ((idFilter) >> 13) ); // верхние 16 бит
|
||||
canFilterConfig.FilterIdLow = (uint16_t)( (((idFilter) << 3) ) | CAN_IDE_32 ); // низкие 16 бит,
|
||||
canFilterConfig.FilterMaskIdHigh = (uint16_t)(((idMask) >> 13) );
|
||||
canFilterConfig.FilterMaskIdLow = (uint16_t)( (((idMask) << 3) ) | CAN_IDE_32 );
|
||||
|
||||
if(HAL_CAN_ConfigFilter(_HCAN, &canFilterConfig) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
#define BIT27 (1UL << 27)
|
||||
#define BITS_20_23_MASK (0xFUL << 20) // 4 бита (20..23)
|
||||
#define BITS_24_26_MASK (0x7UL << 24) // 3 бита (24..26)
|
||||
|
||||
uint32_t filter1_id = BIT27 | (CURRENT_TYPE_DEVICE << 24) | (CURRENT_ID_DEVICE << 20);
|
||||
uint32_t filter1_mask = BIT27 | BITS_24_26_MASK | BITS_20_23_MASK; // все проверяемые биты
|
||||
|
||||
#define BITS_16_19_MASK (0xFUL << 16)
|
||||
|
||||
uint32_t filter2_id = DATA_TYPE_BROADCAST << 16;
|
||||
uint32_t filter2_mask = BITS_16_19_MASK;
|
||||
|
||||
uint32_t filter3_id = DATA_TYPE_PULSE << 16;
|
||||
uint32_t filter3_mask = BITS_16_19_MASK;
|
||||
|
||||
/**
|
||||
* @brief Конфигурирует три фильтра CAN для различных типов сообщений.
|
||||
*/
|
||||
void PROTOCAN_FILTERS()
|
||||
{
|
||||
// Первый фильтр: проверяем 20-27 биты, где 27-й всегда 1
|
||||
PROTOCAN_CONFIG_FILTER(0, filter1_id, filter1_mask);
|
||||
|
||||
// Второй фильтр: проверяем 16-19 биты, равны DATA_TYPE_BROADCASTE
|
||||
PROTOCAN_CONFIG_FILTER(1, filter2_id, filter2_mask);
|
||||
|
||||
// Третий фильтр: проверяем 16-19 биты, равны DATA_TYPE_PULSE
|
||||
PROTOCAN_CONFIG_FILTER(2, filter3_id, filter3_mask);
|
||||
}
|
||||
@@ -1,841 +0,0 @@
|
||||
#include "requester.h"
|
||||
|
||||
struct device CurrentDevice;
|
||||
struct device Device_on_the_Network[8][16];
|
||||
struct controlflags ControlFlags;
|
||||
|
||||
uint8_t CurrentStep = 1;
|
||||
uint8_t LastStep = 0;
|
||||
struct RXMsg rxMsg[CAN_RX_BUFFER_SIZE];
|
||||
|
||||
_Bool IsLeapYear(uint8_t year)
|
||||
{
|
||||
year+=2000;
|
||||
return (year%400==0)||((year%4==0)&&(year%100!=0));
|
||||
}
|
||||
|
||||
uint16_t AvailableCanRxMsg(void)
|
||||
{
|
||||
return ((uint16_t)(CAN_RX_BUFFER_SIZE + (LastStep - CurrentStep + 1)))%CAN_RX_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Инициализация переферии
|
||||
* @details Инициализация HAL, CAN, TIM7, RTC.
|
||||
* @note Фильтры CAN описаны в разделе REQUESTER_CAN_FILTERS().
|
||||
*/
|
||||
void REQUESTER_Init(void)
|
||||
{
|
||||
HAL_Init();
|
||||
MX_CAN_Init();
|
||||
HAL_CAN_Start(&_HCAN);
|
||||
REQUESTER_CAN_FILTERS();
|
||||
//HAL_CAN_ActivateNotification(&_HCAN, CAN_IT_RX_FIFO0_MSG_PENDING);
|
||||
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_ERROR | CAN_IT_BUSOFF | CAN_IT_LAST_ERROR_CODE);
|
||||
ControlFlags.IsPulse = 1;
|
||||
MX_TIM4_Init();
|
||||
MX_RTC_Init();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция с обработкой полученных запросов
|
||||
* @details В бесконечном цикле функция ожидает приёма сообщения. После этого сообщение распределяется в зависимости от DataType.
|
||||
* Обработка запроса аналоговых значений - REQUESTER_AnalogProcessing().
|
||||
* Обработка широковещательных запросов - REQUESTER_BroadcastProcessing().
|
||||
* Обработка запроса дискретных значений - REQUESTER_DiscreticProcessing().
|
||||
* Обработка Modbus - REQUESTER_ModbusProcessing().
|
||||
*/
|
||||
void REQUESTER_MainWhile(void)
|
||||
{
|
||||
HAL_TIM_Base_Start_IT(&htim4);
|
||||
unsigned currentAttemptCount;
|
||||
while(1)
|
||||
{
|
||||
if(AvailableCanRxMsg())
|
||||
{
|
||||
currentAttemptCount = 0;
|
||||
if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_ANALOG)
|
||||
{
|
||||
REQUESTER_AnalogProcessing(rxMsg[CurrentStep]);
|
||||
}
|
||||
else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_BROADCAST)
|
||||
{
|
||||
REQUESTER_BroadcastProcessing(rxMsg[CurrentStep]);
|
||||
}
|
||||
else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_DISCRETE)
|
||||
{
|
||||
REQUESTER_DiscreticProcessing(rxMsg[CurrentStep]);
|
||||
}
|
||||
else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_GENERAL_ADDRESS_SPACE)
|
||||
{
|
||||
REQUESTER_GeneralAddressSpace_Answer(rxMsg[CurrentStep]);
|
||||
}
|
||||
else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_MODBUS_COIL ||
|
||||
rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_MODBUS_DISCRETE ||
|
||||
rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_MODBUS_HOLDING ||
|
||||
rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_MODBUS_INPUT)
|
||||
{
|
||||
REQUESTER_ModbusProcessing(rxMsg[CurrentStep]);
|
||||
}
|
||||
else if(rxMsg[CurrentStep].eID.Fields.MsgType == DATA_TYPE_ERROR)
|
||||
{
|
||||
CanRequestError(rxMsg[CurrentStep]);
|
||||
}
|
||||
CurrentStep = (uint16_t)(CurrentStep + 1) % CAN_RX_BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция обработки аналоговых запросов.
|
||||
* @param struct RXMsg _rxMsg - структура для полученного сообщения.
|
||||
* @details Функция, формирующая и отправляющая ответ на запросы. Типы запросов: Универсальный, Уставки, Напряжение, Ток, Температура.
|
||||
|
||||
*/
|
||||
CRR_Status REQUESTER_AnalogProcessing(struct RXMsg _rxMsg)
|
||||
{
|
||||
msgAnalogType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
switch (msg.Fields.SensorType)
|
||||
{
|
||||
case SENSOR_TYPE_ANALOG_UNIVERSAL:
|
||||
{
|
||||
return (CRR_Status)CanRequestToAnalogUniversal(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_ANALOG_USTAVKI:
|
||||
{
|
||||
return (CRR_Status)CanRequestToAnalogUSTAVKI(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_ANALOG_U:
|
||||
{
|
||||
return (CRR_Status)CanRequestToAnalogUSens(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_ANALOG_I:
|
||||
{
|
||||
return (CRR_Status)CanRequestToAnalogISens(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_ANALOG_T:
|
||||
{
|
||||
return (CRR_Status)CanRequestToAnalogTSens(_rxMsg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//RESERVE SENSOR TYPE
|
||||
return CRR_ERROR;
|
||||
break;
|
||||
}
|
||||
return CRR_ERROR;
|
||||
}
|
||||
|
||||
__weak HAL_StatusTypeDef CanRequestToAnalogUniversal(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 6;
|
||||
data[0] = 'U';
|
||||
data[1] = 'N';
|
||||
data[2] = 'I';
|
||||
data[3] = 'V';
|
||||
data[4] = 'E';
|
||||
data[5] = 'R';
|
||||
return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
__weak HAL_StatusTypeDef CanRequestToAnalogUSTAVKI(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 7;
|
||||
data[0] = 'U';
|
||||
data[1] = 'S';
|
||||
data[2] = 'T';
|
||||
data[3] = 'A';
|
||||
data[4] = 'V';
|
||||
data[5] = 'K';
|
||||
data[6] = 'I';
|
||||
return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
__weak HAL_StatusTypeDef CanRequestToAnalogUSens(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 6;
|
||||
msgAnalogType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'U';
|
||||
data[1] = 'S';
|
||||
data[2] = 47 + msg.Fields.SensorID / 1000;
|
||||
data[3] = 47 + msg.Fields.SensorID / 100 % 10;
|
||||
data[4] = 47 + msg.Fields.SensorID / 10 % 10;
|
||||
data[5] = 47 + msg.Fields.SensorID % 10;
|
||||
return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
__weak HAL_StatusTypeDef CanRequestToAnalogISens(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 6;
|
||||
msgAnalogType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'I';
|
||||
data[1] = 'S';
|
||||
data[2] = 47 + msg.Fields.SensorID / 1000;
|
||||
data[3] = 47 + msg.Fields.SensorID / 100 % 10;
|
||||
data[4] = 47 + msg.Fields.SensorID / 10 % 10;
|
||||
data[5] = 47 + msg.Fields.SensorID % 10;
|
||||
return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
__weak HAL_StatusTypeDef CanRequestToAnalogTSens(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 6;
|
||||
msgAnalogType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'T';
|
||||
data[1] = 'S';
|
||||
data[2] = 47 + msg.Fields.SensorID / 1000;
|
||||
data[3] = 47 + msg.Fields.SensorID / 100 % 10;
|
||||
data[4] = 47 + msg.Fields.SensorID / 10 % 10;
|
||||
data[5] = 47 + msg.Fields.SensorID % 10;
|
||||
return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция обработки широковещательных запросов.
|
||||
* @param struct RXMsg _rxMsg - структура для полученного сообщения.
|
||||
* @details Функция, выполняющая команды, переданные в широковещательном формате с головного (master) устройства. Типы команд: Запрос статуса, запрос на включение или выключение, рестарт устройств, установка времени.
|
||||
*/
|
||||
CRR_Status REQUESTER_BroadcastProcessing(struct RXMsg _rxMsg)
|
||||
{
|
||||
msgBroadcastType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
switch(msg.Fields.BroadcastType)
|
||||
{
|
||||
case SENSOR_TYPE_BROADCAST_STATUS:
|
||||
{
|
||||
//Обработка запроса статуса устройства
|
||||
if(CanRequestToBroadcastStatus(_rxMsg)!=HAL_OK)
|
||||
{
|
||||
return CRR_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_BROADCAST_ONOFF:
|
||||
{
|
||||
//Обработка запроса на вкл/выкл
|
||||
CanRequestToBroadcastOnOff(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_BROADCAST_RESTARTDEVICE:
|
||||
{
|
||||
CanRequestToBroadcastRestart(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_BROADCAST_RTCSETUP:
|
||||
{
|
||||
//Обработка запроса на синхронизацию времени
|
||||
//С головным устройством
|
||||
CanRequestToBroadcastRtcSetup(_rxMsg);
|
||||
break;;
|
||||
}
|
||||
default:
|
||||
//RESERVE SENSOR TYPE.
|
||||
return CRR_ERROR;
|
||||
break;
|
||||
}
|
||||
return CRR_OK;
|
||||
}
|
||||
|
||||
__weak HAL_StatusTypeDef CanRequestToBroadcastStatus(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.DLC = 7;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
tmp_eID.Fields.DeviceType = CURRENT_TYPE_DEVICE;
|
||||
tmp_eID.Fields.DeviceID = CURRENT_ID_DEVICE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
|
||||
RTC_TimeTypeDef sTime = {0};
|
||||
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
|
||||
data[0] = sTime.Hours;
|
||||
data[1] = sTime.Minutes;
|
||||
data[2] = sTime.Seconds;
|
||||
|
||||
RTC_DateTypeDef DateToUpdate = {0};
|
||||
HAL_RTC_GetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN);
|
||||
data[3] = DateToUpdate.Year;
|
||||
data[4] = DateToUpdate.Month;
|
||||
data[5] = DateToUpdate.Date;
|
||||
data[6] = DateToUpdate.WeekDay;
|
||||
|
||||
return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
__weak void CanRequestToBroadcastOnOff(struct RXMsg _rxMsg)
|
||||
{
|
||||
ControlFlags.IsPulse = !ControlFlags.IsPulse;
|
||||
}
|
||||
|
||||
__weak void CanRequestToBroadcastRestart(struct RXMsg _rxMsg)
|
||||
{
|
||||
if(_rxMsg.DLC == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
msgBroadcastType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
if(msg.Fields.Page == (CURRENT_ID_DEVICE / (_rxMsg.DLC*8)))
|
||||
{
|
||||
uint64_t page = 0;
|
||||
for(int i = 0; i < _rxMsg.DLC; i++)
|
||||
{
|
||||
page+=(_rxMsg.Data[i]<<(i*8));
|
||||
}
|
||||
if((page>>CURRENT_ID_DEVICE)&0b1)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
__weak void CanRequestToBroadcastRtcSetup(struct RXMsg _rxMsg)
|
||||
{
|
||||
if(_rxMsg.DLC > 7)
|
||||
{
|
||||
//ERROR
|
||||
}
|
||||
else
|
||||
{
|
||||
int DaysCount_Normal[2][12] = {{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||||
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
|
||||
if(_rxMsg.Data[0]>23 ||
|
||||
_rxMsg.Data[1]>59 ||
|
||||
_rxMsg.Data[2]>59 ||
|
||||
_rxMsg.Data[3]>99 ||
|
||||
_rxMsg.Data[4]>12 ||
|
||||
_rxMsg.Data[5] > DaysCount_Normal[IsLeapYear(_rxMsg.Data[3])][_rxMsg.Data[4]] ||
|
||||
_rxMsg.Data[6]>6)
|
||||
{
|
||||
//ERROR
|
||||
}
|
||||
else
|
||||
{
|
||||
REQUESTER_RTC_SYNC(_rxMsg.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция обработки дискретных запросов.
|
||||
* @param struct RXMsg _rxMsg - структура для полученного сообщения.
|
||||
* @details Функция, формирующая и отправляющая ответ на запросы. Типы запросов: Аварии, Предупреждения, Управляющие сигналы, Флаги, Рестарт устройства, Изменение режима работы устройства, Запрос на устройство.
|
||||
* @note Запрос на устройство. Головное (master) устройство запрашивает некоторое колличество параметров. В Data - 64 битовых адресса параметров, тип которых задаётся в Sensor ID. Имеется возможность запрашивать непоследовательные параметры.
|
||||
*/
|
||||
CRR_Status REQUESTER_DiscreticProcessing(struct RXMsg _rxMsg)
|
||||
{
|
||||
msgDiscreteType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
switch(msg.Fields.Type){
|
||||
case SENSOR_TYPE_DISCRETE_ACCIDENT:
|
||||
{
|
||||
CanRequestToDiscreteAccident(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_DISCRETE_WARNING:
|
||||
{
|
||||
CanRequestToDiscreteWarning(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_DISCRETE_CONTROL_SIGNALS:
|
||||
{
|
||||
CanRequestToDiscreteControlSignals(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_DISCRETE_FLAGS:
|
||||
{
|
||||
CanRequestToDiscreteFlags(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_DISCRETE_RESET:
|
||||
{
|
||||
CanRequestToDiscreteReset(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_DISCRETE_CHANGE_MODE:
|
||||
{
|
||||
CanRequestToDiscreteChangeMode(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case SENSOR_TYPE_DISCRETE_REQUEST_LIST_OF_PARAMETERS:
|
||||
{
|
||||
CanRequestToDiscreteRequestListOfParameters(_rxMsg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//RESERVE SENSOR TYPE.
|
||||
return CRR_ERROR;
|
||||
break;
|
||||
}
|
||||
return CRR_OK;
|
||||
}
|
||||
|
||||
__weak void CanRequestToDiscreteAccident(struct RXMsg _rxMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
__weak void CanRequestToDiscreteWarning(struct RXMsg _rxMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
__weak void CanRequestToDiscreteControlSignals(struct RXMsg _rxMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
__weak void CanRequestToDiscreteFlags(struct RXMsg _rxMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
__weak void CanRequestToDiscreteReset(struct RXMsg _rxMsg)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
__weak void CanRequestToDiscreteChangeMode(struct RXMsg _rxMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
__weak void CanRequestToDiscreteRequestListOfParameters(struct RXMsg _rxMsg)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void REQUESTER_GeneralAddressSpace_Answer(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 8;
|
||||
data[0] = 'G';
|
||||
data[1] = 'A';
|
||||
data[2] = 'S';
|
||||
data[3] = '-';
|
||||
for(int i = 0; i < 4; i++) {
|
||||
unsigned sym = (_rxMsg.eID.Fields.MsgBody>>(12-(i*4)))&0xF;
|
||||
if(sym >= 10)
|
||||
data[4+i] = sym%10+'A';
|
||||
else
|
||||
data[4+i] = sym+'0';
|
||||
}
|
||||
HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция обработки Modbus запросов.
|
||||
* @param struct RXMsg _rxMsg - структура для полученного сообщения.
|
||||
* @details Функция, формирующая и отправляющая ответ на запросы.
|
||||
*/
|
||||
CRR_Status REQUESTER_ModbusProcessing(struct RXMsg _rxMsg)
|
||||
{
|
||||
switch(_rxMsg.eID.Fields.MsgType)
|
||||
{
|
||||
case DATA_TYPE_MODBUS_COIL:
|
||||
{
|
||||
return (CRR_Status)CanRequestToModbusCoil(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_MODBUS_DISCRETE:
|
||||
{
|
||||
return (CRR_Status)CanRequestToModbusDiscrete(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_MODBUS_HOLDING:
|
||||
{
|
||||
return (CRR_Status)CanRequestToModbusHolding(_rxMsg);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_MODBUS_INPUT:
|
||||
{
|
||||
return (CRR_Status)CanRequestToModbusInput(_rxMsg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
//ERROR
|
||||
return CRR_ERROR;
|
||||
break;
|
||||
}
|
||||
return CRR_ERROR;
|
||||
}
|
||||
|
||||
__weak HAL_StatusTypeDef CanRequestToModbusCoil(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 8;
|
||||
msgModbusType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'M';
|
||||
data[1] = 'C';
|
||||
data[2] = ' ';
|
||||
data[3] = 'S';
|
||||
data[4] = msg.Fields.StrAdr;
|
||||
data[5] = ' ';
|
||||
data[6] = 'C';
|
||||
data[7] = msg.Fields.RegCount;
|
||||
return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
__weak HAL_StatusTypeDef CanRequestToModbusDiscrete(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 8;
|
||||
msgModbusType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'M';
|
||||
data[1] = 'D';
|
||||
data[2] = ' ';
|
||||
data[3] = 'S';
|
||||
data[4] = msg.Fields.StrAdr;
|
||||
data[5] = ' ';
|
||||
data[6] = 'C';
|
||||
data[7] = msg.Fields.RegCount;
|
||||
return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
__weak HAL_StatusTypeDef CanRequestToModbusHolding(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 8;
|
||||
msgModbusType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'M';
|
||||
data[1] = 'H';
|
||||
data[2] = ' ';
|
||||
data[3] = 'S';
|
||||
data[4] = msg.Fields.StrAdr;
|
||||
data[5] = ' ';
|
||||
data[6] = 'C';
|
||||
data[7] = msg.Fields.RegCount;
|
||||
return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
__weak HAL_StatusTypeDef CanRequestToModbusInput(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 8;
|
||||
msgModbusType msg;
|
||||
msg.Body = _rxMsg.eID.Fields.MsgBody;
|
||||
data[0] = 'M';
|
||||
data[1] = 'I';
|
||||
data[2] = ' ';
|
||||
data[3] = 'S';
|
||||
data[4] = msg.Fields.StrAdr;
|
||||
data[5] = ' ';
|
||||
data[6] = 'C';
|
||||
data[7] = msg.Fields.RegCount;
|
||||
return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
__weak HAL_StatusTypeDef CanRequestError(struct RXMsg _rxMsg)
|
||||
{
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
extID tmp_eID;
|
||||
tmp_eID.BitAll = _rxMsg.eID.BitAll;
|
||||
tmp_eID.Fields.Route = ROUTE_SLAVE;
|
||||
tmp_eID.Fields.MsgType = DATA_TYPE_ERROR;
|
||||
msgErrorType msg;
|
||||
msg.Fields.ErrorCode = 0xFF;
|
||||
msg.Fields.Info = 0;
|
||||
tmp_eID.Fields.MsgBody = msg.Body;
|
||||
TxHeader.ExtId = tmp_eID.BitAll;
|
||||
TxHeader.DLC = 0;
|
||||
return HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param extID tmp_eID
|
||||
* @param uint32_t tmp_IDE
|
||||
* @param uint32_t tmp_RTR
|
||||
* @param uint32_t tmp_DLC
|
||||
* @param uint8_t *tmp_DATA
|
||||
* @param uint16_t tmp_LastStep
|
||||
* @details
|
||||
*/
|
||||
void TakeRxMsgToBuffer(extID tmp_eID, uint32_t tmp_IDE, uint32_t tmp_RTR, uint32_t tmp_DLC, uint8_t *tmp_DATA, uint16_t tmp_LastStep)
|
||||
{
|
||||
rxMsg[tmp_LastStep].eID.BitAll = tmp_eID.BitAll;
|
||||
rxMsg[tmp_LastStep].info.EXT = tmp_IDE;
|
||||
rxMsg[tmp_LastStep].info.RTR = tmp_RTR;
|
||||
rxMsg[tmp_LastStep].DLC = tmp_DLC;
|
||||
for(int i = 0; i < tmp_DLC; i++)
|
||||
{
|
||||
rxMsg[tmp_LastStep].Data[i] = tmp_DATA[i];
|
||||
}
|
||||
LastStep = tmp_LastStep;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback-Функция обработки приёма.
|
||||
* @details Функция, сигнализирующая через флаги в бесконечный цикл REQUESTER_MainWhile о приёме запроса.
|
||||
*/
|
||||
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
// Обработка всех сообщений в FIFO
|
||||
CAN_RxHeaderTypeDef RxHeader;
|
||||
uint8_t RCAN_Data[8];
|
||||
while(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RCAN_Data) == HAL_OK)
|
||||
{
|
||||
//Расширенный ID
|
||||
if(RxHeader.IDE == CAN_ID_EXT)
|
||||
{
|
||||
if(!((CAN_RX_BUFFER_SIZE + LastStep - (CurrentStep-1))&CAN_RX_BUFFER_SIZE))
|
||||
{
|
||||
//Буффер переполнен
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t tmp_LastStep = (uint16_t)(LastStep + 1) % CAN_RX_BUFFER_SIZE;
|
||||
|
||||
extID ExtID_Of_RX_MSG;
|
||||
ExtID_Of_RX_MSG.BitAll = RxHeader.ExtId;
|
||||
|
||||
//Полученное сообщение - пульс устройств в сети
|
||||
if(ExtID_Of_RX_MSG.Fields.MsgType == DATA_TYPE_PULSE)
|
||||
{
|
||||
Device_on_the_Network[ExtID_Of_RX_MSG.Fields.DeviceType][ExtID_Of_RX_MSG.Fields.DeviceID].Status = ONLINE;
|
||||
Device_on_the_Network[ExtID_Of_RX_MSG.Fields.DeviceType][ExtID_Of_RX_MSG.Fields.DeviceID].TimeFromLastPulse = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
TakeRxMsgToBuffer(ExtID_Of_RX_MSG, RxHeader.IDE, RxHeader.RTR, RxHeader.DLC, RCAN_Data, tmp_LastStep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция отправки пульса устройства.
|
||||
* @details Пульс устройства. Есть возможность отключить пульс по запросу.
|
||||
*/
|
||||
void REQUESTER_Pulse_TIM_Handler()
|
||||
{
|
||||
if(ControlFlags.IsPulse)
|
||||
{
|
||||
static unsigned PulseStage = 0;
|
||||
CAN_TxHeaderTypeDef TxHeader;
|
||||
uint32_t TxMailBox = 0;
|
||||
extID currentID;
|
||||
currentID.BitAll = 0;
|
||||
currentID.Fields.MsgBody = 0;
|
||||
currentID.Fields.DeviceID = CURRENT_ID_DEVICE;
|
||||
currentID.Fields.DeviceType = CURRENT_TYPE_DEVICE;
|
||||
currentID.Fields.MsgType = DATA_TYPE_PULSE;
|
||||
currentID.Fields.Route = ROUTE_SLAVE;
|
||||
currentID.Fields.Priority = PRIORITY_STANDARD;
|
||||
TxHeader.ExtId = currentID.BitAll;
|
||||
uint8_t data[8];
|
||||
TxHeader.IDE = CAN_ID_EXT;
|
||||
TxHeader.TransmitGlobalTime = DISABLE;
|
||||
TxHeader.RTR = CAN_RTR_DATA;
|
||||
TxHeader.DLC = 1;
|
||||
PulseStage++;
|
||||
unsigned int debugID;
|
||||
debugID = currentID.BitAll;
|
||||
if(PulseStage > 0xFF){
|
||||
PulseStage = 0;
|
||||
}
|
||||
data[0] = PulseStage;
|
||||
HAL_CAN_AddTxMessage(&_HCAN, &TxHeader, data, &TxMailBox);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция установки в RTC полученной даты/время из запроса.
|
||||
* @param uint8_t *data - Байтовый массив, 7 элементов. [0] - Часы. [1] - Минуты. [2] - Секунды. [3] - Год. [4] - Месяц. [5] - Дата. [6] - День недели.
|
||||
*/
|
||||
void REQUESTER_RTC_SYNC(uint8_t *data)
|
||||
{
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);
|
||||
RTC_TimeTypeDef sTime = {0};
|
||||
RTC_DateTypeDef DateToUpdate = {0};
|
||||
|
||||
sTime.Hours = data[0];
|
||||
sTime.Minutes = data[1];
|
||||
sTime.Seconds = data[2];
|
||||
|
||||
if(HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
DateToUpdate.Year = data[3];
|
||||
DateToUpdate.Month = data[4];
|
||||
DateToUpdate.Date = data[5];
|
||||
DateToUpdate.WeekDay = data[6];
|
||||
if(HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Функция настройки фильтров CAN.
|
||||
* @details Настройка фильтров. Фильр для приёма сообщений с главного устройства. Фильтр для приёма на текущее устройство. Фильтр для приёма пульса других устройств в сети.
|
||||
*/
|
||||
|
||||
void CONFIG_CAN_FILTER(uint8_t filterBank, uint32_t idFilter, uint32_t idMask)
|
||||
{
|
||||
CAN_FilterTypeDef canFilterConfig;
|
||||
canFilterConfig.FilterBank = filterBank;
|
||||
canFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
|
||||
canFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
|
||||
canFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
|
||||
canFilterConfig.FilterActivation = ENABLE;
|
||||
canFilterConfig.SlaveStartFilterBank = 14;
|
||||
|
||||
// Разбиваем 32-битный ID и маску для фильтрации на High и Low 16 бит
|
||||
canFilterConfig.FilterIdHigh = (uint16_t)( ((idFilter) >> 13) ); // верхние 16 бит
|
||||
canFilterConfig.FilterIdLow = (uint16_t)( (((idFilter) << 3) ) | CAN_IDE_32 ); // низкие 16 бит,
|
||||
canFilterConfig.FilterMaskIdHigh = (uint16_t)(((idMask) >> 13) );
|
||||
canFilterConfig.FilterMaskIdLow = (uint16_t)( (((idMask) << 3) ) | CAN_IDE_32 );
|
||||
|
||||
if(HAL_CAN_ConfigFilter(&_HCAN, &canFilterConfig) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
#define BIT27 (1UL << 27)
|
||||
#define BITS_20_23_MASK (0xFUL << 20) // 4 бита (20..23)
|
||||
#define BITS_24_26_MASK (0x7UL << 24) // 3 бита (24..26)
|
||||
|
||||
uint32_t filter1_id = BIT27 | (CURRENT_TYPE_DEVICE << 24) | (CURRENT_ID_DEVICE << 20);
|
||||
uint32_t filter1_mask = BIT27 | BITS_24_26_MASK | BITS_20_23_MASK; // все проверяемые биты
|
||||
|
||||
#define BITS_16_19_MASK (0xFUL << 16)
|
||||
|
||||
uint32_t filter2_id = DATA_TYPE_BROADCAST << 16;
|
||||
uint32_t filter2_mask = BITS_16_19_MASK;
|
||||
|
||||
uint32_t filter3_id = DATA_TYPE_PULSE << 16;
|
||||
uint32_t filter3_mask = BITS_16_19_MASK;
|
||||
|
||||
void REQUESTER_CAN_FILTERS()
|
||||
{
|
||||
// Первый фильтр: проверяем 20-27 биты, где 27-й всегда 1
|
||||
CONFIG_CAN_FILTER(0, filter1_id, filter1_mask);
|
||||
|
||||
// Второй фильтр: проверяем 16-19 биты, равны DATA_TYPE_BROADCASTE
|
||||
CONFIG_CAN_FILTER(1, filter2_id, filter2_mask);
|
||||
|
||||
// Третий фильтр: проверяем 16-19 биты, равны DATA_TYPE_PULSE
|
||||
CONFIG_CAN_FILTER(2, filter3_id, filter3_mask);
|
||||
|
||||
//CONFIG_CAN_FILTER(3, 0, 0);
|
||||
}
|
||||
@@ -86,7 +86,7 @@ ProjectManager.ProjectBuild=false
|
||||
ProjectManager.ProjectFileName=F103C8T6.ioc
|
||||
ProjectManager.ProjectName=F103C8T6
|
||||
ProjectManager.ProjectStructure=
|
||||
ProjectManager.RegisterCallBack=
|
||||
ProjectManager.RegisterCallBack=CAN
|
||||
ProjectManager.StackSize=0x400
|
||||
ProjectManager.TargetToolchain=MDK-ARM V5.32
|
||||
ProjectManager.ToolChainLocation=
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -161,7 +161,7 @@
|
||||
<SizeOfObject>0</SizeOfObject>
|
||||
<BreakByAccess>0</BreakByAccess>
|
||||
<BreakIfRCount>1</BreakIfRCount>
|
||||
<Filename>..\Core\Src\requester.c</Filename>
|
||||
<Filename>D:\Work\MCU\F103C8T6\Core\Src\requester.c</Filename>
|
||||
<ExecCommand></ExecCommand>
|
||||
<Expression>\\F103C8T6\../Core/Src/requester.c\55</Expression>
|
||||
</Bp>
|
||||
@@ -177,10 +177,106 @@
|
||||
<SizeOfObject>0</SizeOfObject>
|
||||
<BreakByAccess>0</BreakByAccess>
|
||||
<BreakIfRCount>1</BreakIfRCount>
|
||||
<Filename>..\Core\Src\requester.c</Filename>
|
||||
<Filename>D:\Work\MCU\F103C8T6\Core\Src\requester.c</Filename>
|
||||
<ExecCommand></ExecCommand>
|
||||
<Expression>\\F103C8T6\../Core/Src/requester.c\690</Expression>
|
||||
</Bp>
|
||||
<Bp>
|
||||
<Number>2</Number>
|
||||
<Type>0</Type>
|
||||
<LineNumber>56</LineNumber>
|
||||
<EnabledFlag>1</EnabledFlag>
|
||||
<Address>0</Address>
|
||||
<ByteObject>0</ByteObject>
|
||||
<HtxType>0</HtxType>
|
||||
<ManyObjects>0</ManyObjects>
|
||||
<SizeOfObject>0</SizeOfObject>
|
||||
<BreakByAccess>0</BreakByAccess>
|
||||
<BreakIfRCount>0</BreakIfRCount>
|
||||
<Filename>D:\Work\MCU\F103C8T6\Core\Src\requester.c</Filename>
|
||||
<ExecCommand></ExecCommand>
|
||||
<Expression></Expression>
|
||||
</Bp>
|
||||
<Bp>
|
||||
<Number>3</Number>
|
||||
<Type>0</Type>
|
||||
<LineNumber>691</LineNumber>
|
||||
<EnabledFlag>1</EnabledFlag>
|
||||
<Address>0</Address>
|
||||
<ByteObject>0</ByteObject>
|
||||
<HtxType>0</HtxType>
|
||||
<ManyObjects>0</ManyObjects>
|
||||
<SizeOfObject>0</SizeOfObject>
|
||||
<BreakByAccess>0</BreakByAccess>
|
||||
<BreakIfRCount>0</BreakIfRCount>
|
||||
<Filename>D:\Work\MCU\F103C8T6\Core\Src\requester.c</Filename>
|
||||
<ExecCommand></ExecCommand>
|
||||
<Expression></Expression>
|
||||
</Bp>
|
||||
<Bp>
|
||||
<Number>4</Number>
|
||||
<Type>0</Type>
|
||||
<LineNumber>63</LineNumber>
|
||||
<EnabledFlag>1</EnabledFlag>
|
||||
<Address>0</Address>
|
||||
<ByteObject>0</ByteObject>
|
||||
<HtxType>0</HtxType>
|
||||
<ManyObjects>0</ManyObjects>
|
||||
<SizeOfObject>0</SizeOfObject>
|
||||
<BreakByAccess>0</BreakByAccess>
|
||||
<BreakIfRCount>0</BreakIfRCount>
|
||||
<Filename>..\Core\Src\protocan.c</Filename>
|
||||
<ExecCommand></ExecCommand>
|
||||
<Expression></Expression>
|
||||
</Bp>
|
||||
<Bp>
|
||||
<Number>5</Number>
|
||||
<Type>0</Type>
|
||||
<LineNumber>64</LineNumber>
|
||||
<EnabledFlag>1</EnabledFlag>
|
||||
<Address>0</Address>
|
||||
<ByteObject>0</ByteObject>
|
||||
<HtxType>0</HtxType>
|
||||
<ManyObjects>0</ManyObjects>
|
||||
<SizeOfObject>0</SizeOfObject>
|
||||
<BreakByAccess>0</BreakByAccess>
|
||||
<BreakIfRCount>0</BreakIfRCount>
|
||||
<Filename>..\Core\Src\protocan.c</Filename>
|
||||
<ExecCommand></ExecCommand>
|
||||
<Expression></Expression>
|
||||
</Bp>
|
||||
<Bp>
|
||||
<Number>6</Number>
|
||||
<Type>0</Type>
|
||||
<LineNumber>695</LineNumber>
|
||||
<EnabledFlag>1</EnabledFlag>
|
||||
<Address>0</Address>
|
||||
<ByteObject>0</ByteObject>
|
||||
<HtxType>0</HtxType>
|
||||
<ManyObjects>0</ManyObjects>
|
||||
<SizeOfObject>0</SizeOfObject>
|
||||
<BreakByAccess>0</BreakByAccess>
|
||||
<BreakIfRCount>0</BreakIfRCount>
|
||||
<Filename>..\Core\Src\protocan.c</Filename>
|
||||
<ExecCommand></ExecCommand>
|
||||
<Expression></Expression>
|
||||
</Bp>
|
||||
<Bp>
|
||||
<Number>7</Number>
|
||||
<Type>0</Type>
|
||||
<LineNumber>696</LineNumber>
|
||||
<EnabledFlag>1</EnabledFlag>
|
||||
<Address>0</Address>
|
||||
<ByteObject>0</ByteObject>
|
||||
<HtxType>0</HtxType>
|
||||
<ManyObjects>0</ManyObjects>
|
||||
<SizeOfObject>0</SizeOfObject>
|
||||
<BreakByAccess>0</BreakByAccess>
|
||||
<BreakIfRCount>0</BreakIfRCount>
|
||||
<Filename>..\Core\Src\protocan.c</Filename>
|
||||
<ExecCommand></ExecCommand>
|
||||
<Expression></Expression>
|
||||
</Bp>
|
||||
</Breakpoint>
|
||||
<WatchWindow1>
|
||||
<Ww>
|
||||
@@ -321,7 +417,31 @@
|
||||
<GroupNumber>2</GroupNumber>
|
||||
<FileNumber>2</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>1</tvExp>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\Core\Src\canerrorbox.c</PathWithFileName>
|
||||
<FilenameWithoutPath>canerrorbox.c</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>2</GroupNumber>
|
||||
<FileNumber>3</FileNumber>
|
||||
<FileType>5</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\Core\Inc\canerrorbox.h</PathWithFileName>
|
||||
<FilenameWithoutPath>canerrorbox.h</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>2</GroupNumber>
|
||||
<FileNumber>4</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>../Core/Src/main.c</PathWithFileName>
|
||||
@@ -331,7 +451,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>2</GroupNumber>
|
||||
<FileNumber>3</FileNumber>
|
||||
<FileNumber>5</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@@ -343,7 +463,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>2</GroupNumber>
|
||||
<FileNumber>4</FileNumber>
|
||||
<FileNumber>6</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@@ -355,7 +475,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>2</GroupNumber>
|
||||
<FileNumber>5</FileNumber>
|
||||
<FileNumber>7</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@@ -367,7 +487,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>2</GroupNumber>
|
||||
<FileNumber>6</FileNumber>
|
||||
<FileNumber>8</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@@ -379,7 +499,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>2</GroupNumber>
|
||||
<FileNumber>7</FileNumber>
|
||||
<FileNumber>9</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@@ -391,7 +511,7 @@
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>2</GroupNumber>
|
||||
<FileNumber>8</FileNumber>
|
||||
<FileNumber>10</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
@@ -401,30 +521,6 @@
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>2</GroupNumber>
|
||||
<FileNumber>9</FileNumber>
|
||||
<FileType>5</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\Core\Inc\requester.h</PathWithFileName>
|
||||
<FilenameWithoutPath>requester.h</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>2</GroupNumber>
|
||||
<FileNumber>10</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\Core\Src\requester.c</PathWithFileName>
|
||||
<FilenameWithoutPath>requester.c</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
<File>
|
||||
<GroupNumber>2</GroupNumber>
|
||||
<FileNumber>11</FileNumber>
|
||||
@@ -432,8 +528,8 @@
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\Core\Src\canerrorbox.c</PathWithFileName>
|
||||
<FilenameWithoutPath>canerrorbox.c</FilenameWithoutPath>
|
||||
<PathWithFileName>..\Core\Src\protocan.c</PathWithFileName>
|
||||
<FilenameWithoutPath>protocan.c</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
@@ -444,8 +540,8 @@
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>..\Core\Inc\canerrorbox.h</PathWithFileName>
|
||||
<FilenameWithoutPath>canerrorbox.h</FilenameWithoutPath>
|
||||
<PathWithFileName>..\Core\Inc\protocan.h</PathWithFileName>
|
||||
<FilenameWithoutPath>protocan.h</FilenameWithoutPath>
|
||||
<RteFlg>0</RteFlg>
|
||||
<bShared>0</bShared>
|
||||
</File>
|
||||
|
||||
@@ -395,6 +395,16 @@
|
||||
<Group>
|
||||
<GroupName>Application/User/Core</GroupName>
|
||||
<Files>
|
||||
<File>
|
||||
<FileName>canerrorbox.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\Core\Src\canerrorbox.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>canerrorbox.h</FileName>
|
||||
<FileType>5</FileType>
|
||||
<FilePath>..\Core\Inc\canerrorbox.h</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>main.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
@@ -635,24 +645,14 @@
|
||||
<FilePath>../Core/Src/stm32f1xx_hal_msp.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>requester.h</FileName>
|
||||
<FileType>5</FileType>
|
||||
<FilePath>..\Core\Inc\requester.h</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>requester.c</FileName>
|
||||
<FileName>protocan.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\Core\Src\requester.c</FilePath>
|
||||
<FilePath>..\Core\Src\protocan.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>canerrorbox.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\Core\Src\canerrorbox.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>canerrorbox.h</FileName>
|
||||
<FileName>protocan.h</FileName>
|
||||
<FileType>5</FileType>
|
||||
<FilePath>..\Core\Inc\canerrorbox.h</FilePath>
|
||||
<FilePath>..\Core\Inc\protocan.h</FilePath>
|
||||
</File>
|
||||
</Files>
|
||||
</Group>
|
||||
@@ -924,4 +924,13 @@
|
||||
<files/>
|
||||
</RTE>
|
||||
|
||||
<LayerInfo>
|
||||
<Layers>
|
||||
<Layer>
|
||||
<LayName>F103C8T6</LayName>
|
||||
<LayPrjMark>1</LayPrjMark>
|
||||
</Layer>
|
||||
</Layers>
|
||||
</LayerInfo>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user