Files
F103C8T6/Core/Src/requester.c

842 lines
24 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.
#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);
}