Добавить пакеты SETTINGS для привязки датчиков

This commit is contained in:
2026-08-26 20:13:06 +03:00
parent ce6c4327a4
commit bb7c94f1b7
3 changed files with 295 additions and 16 deletions

View File

@@ -164,6 +164,10 @@ void PROTOCAN_LoopProcessRxMsgs(void)
{
ProtoCanMsgToGeneralAddressSpace(rxMsg[CurrentStep]);
}
else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_SETTINGS)
{
PROTOCAN_SettingsProcessing(rxMsg[CurrentStep]);
}
else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_COIL ||
rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_DISCRETE ||
rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_HOLDING ||
@@ -216,6 +220,10 @@ PROTOCAN_StatusTypeDef PROTOCAN_ProcessAllRxMsgs(void)
{
result = ProtoCanMsgToGeneralAddressSpace(rxMsg[CurrentStep]);
}
else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_SETTINGS)
{
result = PROTOCAN_SettingsProcessing(rxMsg[CurrentStep]);
}
else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_COIL ||
rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_DISCRETE ||
rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_HOLDING ||
@@ -269,6 +277,10 @@ PROTOCAN_StatusTypeDef PROTOCAN_ProcessSingleRxMsg(void)
{
result = ProtoCanMsgToGeneralAddressSpace(rxMsg[CurrentStep]);
}
else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_SETTINGS)
{
result = PROTOCAN_SettingsProcessing(rxMsg[CurrentStep]);
}
else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_COIL ||
rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_DISCRETE ||
rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_HOLDING ||
@@ -868,7 +880,140 @@ PROTOCAN_StatusTypeDef PROTOCAN_SEND_CORE(const ProtoCanId_t id, const struct Pr
return PROTOCAN_ERROR;
}
}
return PROTOCAN_OK;
return PROTOCAN_OK;
}
/**
* @brief Разбирает однокадровый запрос SETTINGS для текущего устройства.
*
* Body[15:8] содержит номер сборки, Body[7:0] — позицию. DLC=0 означает
* GET, DLC=8 с ненулевым ROM — WRITE/REPLACE, DLC=8 с нулями — CLEAR.
* Проверка физического датчика и сохранение EEPROM выполняются приложением в
* переопределённой функции ProtoCanMsgToSettings().
*/
PROTOCAN_StatusTypeDef PROTOCAN_SettingsProcessing(struct RXMsg _rxMsg)
{
ProtoCanSettingsMsg_t message;
uint8_t index;
uint8_t romIsZero = 1U;
if((_rxMsg.eID.BitAll & PROTOCAN_SETTINGS_HEADER_MASK)
!= PROTOCAN_SETTINGS_REQUEST_BASE_ID)
{
return PROTOCAN_ERROR;
}
message.AssemblySerial = (uint8_t)((_rxMsg.eID.Fields.MsgBody >> 8U) & 0xFFU);
message.Position = (uint8_t)(_rxMsg.eID.Fields.MsgBody & 0xFFU);
message.Result = PROTOCAN_SETTINGS_RESULT_OK;
for(index = 0U; index < PROTOCAN_SETTINGS_ROM_SIZE; index++)
{
message.Rom[index] = 0U;
}
if((_rxMsg.info.RTR != 0U)
|| ((_rxMsg.DLC != 0U) && (_rxMsg.DLC != PROTOCAN_SETTINGS_ROM_SIZE)))
{
message.Operation = PROTOCAN_SETTINGS_INVALID;
message.Result = PROTOCAN_SETTINGS_RESULT_INVALID_DLC;
return PROTOCAN_SEND_SETTINGS_ERROR(message.AssemblySerial, message.Position,
message.Result);
}
if(_rxMsg.DLC == 0U)
{
message.Operation = PROTOCAN_SETTINGS_GET;
return ProtoCanMsgToSettings(&message);
}
for(index = 0U; index < PROTOCAN_SETTINGS_ROM_SIZE; index++)
{
message.Rom[index] = _rxMsg.Data[index];
if(message.Rom[index] != 0U)
{
romIsZero = 0U;
}
}
message.Operation = (romIsZero != 0U) ? PROTOCAN_SETTINGS_CLEAR
: PROTOCAN_SETTINGS_WRITE;
return ProtoCanMsgToSettings(&message);
}
/**
* @brief Слабая точка подключения каталога датчиков приложения.
*/
__weak PROTOCAN_StatusTypeDef ProtoCanMsgToSettings(
const ProtoCanSettingsMsg_t *message)
{
(void)message;
return PROTOCAN_ERROR;
}
/** Отправляет один SETTINGS-кадр с Body из id и payload длиной 0..8. */
PROTOCAN_StatusTypeDef PROTOCAN_SEND_SETTINGS(
ProtoCanId_t id, const struct ProtoCanSettingsData data)
{
CAN_TxHeaderTypeDef TxHeader;
uint32_t TxMailBox = 0U;
uint8_t canData[PROTOCAN_SETTINGS_ROM_SIZE] = {0U};
uint8_t index;
if((id.Fields.MsgType != PROTOCAN_MSGTYPE_SETTINGS)
|| (data.DataCount > PROTOCAN_SETTINGS_ROM_SIZE)
|| ((data.DataCount != 0U) && (data.Data == 0)))
{
return PROTOCAN_ERROR;
}
for(index = 0U; index < data.DataCount; index++)
{
canData[index] = data.Data[index];
}
TxHeader.ExtId = id.BitAll;
TxHeader.IDE = CAN_ID_EXT;
TxHeader.RTR = CAN_RTR_DATA;
TxHeader.TransmitGlobalTime = DISABLE;
TxHeader.DLC = data.DataCount;
if(HAL_CAN_AddTxMessage(_HCAN, &TxHeader, canData, &TxMailBox) != HAL_OK)
{
return PROTOCAN_ERROR;
}
return PROTOCAN_OK;
}
/** Отправляет успешный ответ SETTINGS с текущим ROM целевой локации. */
PROTOCAN_StatusTypeDef PROTOCAN_SEND_SETTINGS_RESPONSE(uint8_t assemblySerial,
uint8_t position, const uint8_t *rom)
{
ProtoCanId_t id;
ProtoCanData_t data;
if(rom == 0)
{
return PROTOCAN_ERROR;
}
id.BitAll = PROTOCAN_SETTINGS_RESPONSE_BASE_ID
| ((uint32_t)assemblySerial << 8U) | position;
data.SettingsData.Data = rom;
data.SettingsData.DataCount = PROTOCAN_SETTINGS_ROM_SIZE;
return PROTOCAN_SEND_SETTINGS(id, data.SettingsData);
}
/** Отправляет однобайтовую ошибку SETTINGS с сохранением Body запроса. */
PROTOCAN_StatusTypeDef PROTOCAN_SEND_SETTINGS_ERROR(uint8_t assemblySerial,
uint8_t position, ProtoCanSettingsResultType result)
{
ProtoCanId_t id;
ProtoCanData_t data;
const uint8_t error = (uint8_t)result;
if(result == PROTOCAN_SETTINGS_RESULT_OK)
{
return PROTOCAN_ERROR;
}
id.BitAll = PROTOCAN_SETTINGS_RESPONSE_BASE_ID
| ((uint32_t)assemblySerial << 8U) | position;
data.SettingsData.Data = &error;
data.SettingsData.DataCount = 1U;
return PROTOCAN_SEND_SETTINGS(id, data.SettingsData);
}
/**
@@ -1291,8 +1436,8 @@ void TakeRxMsgToBuffer(ProtoCanId_t tmp_eID, uint32_t tmp_IDE, uint32_t tmp_RTR,
tmp_DLC = 8u;
}
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].info.EXT = (tmp_IDE == CAN_ID_EXT) ? 1U : 0U;
rxMsg[tmp_LastStep].info.RTR = (tmp_RTR == CAN_RTR_REMOTE) ? 1U : 0U;
rxMsg[tmp_LastStep].DLC = tmp_DLC;
for(uint32_t i = 0; i < tmp_DLC; i++)
{
@@ -1445,7 +1590,8 @@ void PROTOCAN_FILTERS()
#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);
/* Адресованный запрос приходит от ПМ, поэтому Route (бит 27) равен нулю. */
uint32_t filter1_id = (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)
@@ -1456,7 +1602,7 @@ void PROTOCAN_FILTERS()
uint32_t filter3_id = PROTOCAN_MSGTYPE_PULSE << 16;
uint32_t filter3_mask = BITS_16_19_MASK;
// Первый фильтр: проверяем 20-27 биты, где 27-й всегда 1
// Первый фильтр: Route=0 (от ПМ), DeviceType и DeviceID текущего устройства.
PROTOCAN_CONFIG_FILTER(0, filter1_id, filter1_mask);
// Второй фильтр: проверяем 16-19 биты, равны PROTOCAN_MSGTYPE_BROADCASTE
@@ -1510,8 +1656,12 @@ PROTOCAN_StatusTypeDef PROTOCAN_SEND(ProtoCanId_t id, ProtoCanData_t data)
return PROTOCAN_SEND_ERROR(id, data.ErrorData);
break;
}
case PROTOCAN_MSGTYPE_SETTINGS:
{
return PROTOCAN_SEND_SETTINGS(id, data.SettingsData);
}
default:
return PROTOCAN_ERROR;
}
return PROTOCAN_ERROR;
}
}