From 0f1fa1e7818db41913aca3cdb30b53e714ab322b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D1=8F=D1=87=D0=B5=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A8?= =?UTF-8?q?=D1=82=D0=B5=D0=B9=D0=B1=D0=B5=D0=B7=D0=B0=D0=BD=D0=B4=D1=82?= Date: Wed, 8 Jul 2026 15:12:58 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D1=82=D1=80=D0=B8=20=D0=B2=D0=B0=D1=80=D0=B8?= =?UTF-8?q?=D0=B0=D0=BD=D1=82=D0=B0=20=D0=BF=D1=80=D0=B8=D1=91=D0=BC=D0=B0?= =?UTF-8?q?=20CAN=20(=D0=91=D0=B5=D1=81=D0=BA=D0=BE=D0=BD=D0=B5=D1=87?= =?UTF-8?q?=D0=BD=D1=8B=D0=B9,=20=D0=B2=D1=81=D0=B5=20=D1=81=D0=BE=D0=BE?= =?UTF-8?q?=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D1=8F,=20=D0=BE=D0=B4=D0=BD?= =?UTF-8?q?=D0=BE=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/Inc/protocan.h | 6 +- Core/Src/protocan.c | 219 +++++++++++++++++++++++++++++++++----------- 2 files changed, 171 insertions(+), 54 deletions(-) diff --git a/Core/Inc/protocan.h b/Core/Inc/protocan.h index 55a225c..99fa270 100644 --- a/Core/Inc/protocan.h +++ b/Core/Inc/protocan.h @@ -275,7 +275,9 @@ PROTOCAN_INIT_StatusTypeDef PROTOCAN_INIT(CAN_HandleTypeDef *tmp_hcan, TIM_HandleTypeDef *tmp_tim); void PROTOCAN_DEINIT(uint8_t stage); void PROTOCAN_FILTERS(void); -void PROTOCAN_LOOP(void); +void PROTOCAN_LoopProcessRxMsgs(void); +PROTOCAN_StatusTypeDef PROTOCAN_ProcessAllRxMsgs(void); +PROTOCAN_StatusTypeDef PROTOCAN_ProcessSingleRxMsg(void); PROTOCAN_StatusTypeDef PROTOCAN_SEND(ProtoCanId_t id, ProtoCanData_t data); void ProtoCanPulseCallback(TIM_HandleTypeDef *htim); @@ -305,7 +307,7 @@ PROTOCAN_StatusTypeDef ProtoCanMsgToAnalogTSens(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToGeneralAddressSpace(struct RXMsg _rxMsg); -PROTOCAN_StatusTypeDef CanRequestError(struct RXMsg _rxMsg); +PROTOCAN_StatusTypeDef PROTOCAN_RequestError(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef PROTOCAN_ModbusProcessing(struct RXMsg _rxMsg); PROTOCAN_StatusTypeDef ProtoCanMsgToModbusCoil(struct RXMsg _rxMsg); diff --git a/Core/Src/protocan.c b/Core/Src/protocan.c index 2d4f861..b5dcb5a 100644 --- a/Core/Src/protocan.c +++ b/Core/Src/protocan.c @@ -111,50 +111,165 @@ PROTOCAN_INIT_StatusTypeDef PROTOCAN_INIT(CAN_HandleTypeDef *tmp_hcan, RTC_Handl } /** -* @brief Функция с обработкой полученных запросов -* @details В бесконечном цикле функция ожидает приёма сообщения. После этого сообщение распределяется в зависимости от DataType. -* Обработка запроса аналоговых значений - PROTOCAN_AnalogProcessing(). -* Обработка широковещательных запросов - PROTOCAN_BroadcastProcessing(). -* Обработка запроса дискретных значений - PROTOCAN_DiscreticProcessing(). -* Обработка запроса к общему адресному пространству - PROTOCAN_GeneralAddressSpace_Answer(). -* Обработка Modbus - PROTOCAN_ModbusProcessing(). -*/ -void PROTOCAN_LOOP(void) + * @brief Бесконечный цикл обработки входящих CAN-сообщений. + * + * Эта функция постоянно проверяет наличие доступных сообщений в буфере CAN и + * вызывает соответствующие обработчики в зависимости от типа полученного сообщения. + * Обрабатываемые типы сообщений: + * - Аналоговые данные + * - Широковещательные сообщения + * - Дискретные данные + * - Общее адресное пространство + * - Модбас сообщения + * - Ошибки + * + * Обработка сообщений осуществляется внутри бесконечного цикла с использованием + * функции AvailableCanRxMsg() для определения наличия новых сообщений. + * + * В конце каждого обработанного сообщения индекс текущего элемента буфера инкрементируется + * с учетом размера буфера через операцию по модулю. + */ +void PROTOCAN_LoopProcessRxMsgs(void) { - while(1) + while(1) + { + if(AvailableCanRxMsg()) + { + if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_ANALOG) + { + PROTOCAN_AnalogProcessing(rxMsg[CurrentStep]); + } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_BROADCAST) + { + PROTOCAN_BroadcastProcessing(rxMsg[CurrentStep]); + } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_DISCRETE) + { + PROTOCAN_DiscreticProcessing(rxMsg[CurrentStep]); + } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_GENERAL_ADDRESS_SPACE) + { + ProtoCanMsgToGeneralAddressSpace(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 || + rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_INPUT) + { + PROTOCAN_ModbusProcessing(rxMsg[CurrentStep]); + } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_ERROR) + { + PROTOCAN_RequestError(rxMsg[CurrentStep]); + } + // Обновление индекса текущего сообщения с циклическим масштабированием + CurrentStep = (uint16_t)(CurrentStep + 1) % PROTOCAN_RX_BUFFER_SIZE; + } + } +} + +/** + * @brief Обрабатывает все доступные входящие CAN-сообщения. + * + * Эта функция последовательно обрабатывает все сообщения, доступные в буфере, + * вызывая соответствующие функции обработчики в зависимости от типа сообщения. + * После обработки каждого сообщения индекс текущего элемента буфера обновляется + * циклически. + * + * @return PROTOCAN_OK, если все сообщения были обработаны успешно. + * В противном случае возвращается код ошибки, полученный при обработке сообщения. + * + * Обработка происходит до тех пор, пока есть доступные сообщения, полученные функцией + * AvailableCanRxMsg(). + */ +PROTOCAN_StatusTypeDef PROTOCAN_ProcessAllRxMsgs(void) +{ + PROTOCAN_StatusTypeDef result = PROTOCAN_TIMEOUT; + while(AvailableCanRxMsg()) { - if(AvailableCanRxMsg()) + if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_ANALOG) { - if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_ANALOG) - { - PROTOCAN_AnalogProcessing(rxMsg[CurrentStep]); - } - else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_BROADCAST) - { - PROTOCAN_BroadcastProcessing(rxMsg[CurrentStep]); - } - else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_DISCRETE) - { - PROTOCAN_DiscreticProcessing(rxMsg[CurrentStep]); - } - else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_GENERAL_ADDRESS_SPACE) - { - ProtoCanMsgToGeneralAddressSpace(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 || - rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_INPUT) - { - PROTOCAN_ModbusProcessing(rxMsg[CurrentStep]); - } - else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_ERROR) - { - CanRequestError(rxMsg[CurrentStep]); - } - CurrentStep = (uint16_t)(CurrentStep + 1) % PROTOCAN_RX_BUFFER_SIZE; + result = PROTOCAN_AnalogProcessing(rxMsg[CurrentStep]); + } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_BROADCAST) + { + result = PROTOCAN_BroadcastProcessing(rxMsg[CurrentStep]); + } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_DISCRETE) + { + result = PROTOCAN_DiscreticProcessing(rxMsg[CurrentStep]); + } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_GENERAL_ADDRESS_SPACE) + { + result = ProtoCanMsgToGeneralAddressSpace(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 || + rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_INPUT) + { + result = PROTOCAN_ModbusProcessing(rxMsg[CurrentStep]); + } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_ERROR) + { + result = PROTOCAN_RequestError(rxMsg[CurrentStep]); + } + CurrentStep = (uint16_t)(CurrentStep + 1) % PROTOCAN_RX_BUFFER_SIZE; + if(result != PROTOCAN_OK) + { + return result; } } + return result; +} + +/** + * @brief Обрабатывает одно доступное CAN-сообщение. + * + * Эта функция проверяет наличие доступных сообщений в буфере и, если таковое есть, + * выполняет обработку текущего сообщения в зависимости от его типа. После обработки + * индекс текущего сообщения обновляется циклически. + * + * @return Прошедший статус обработки: + * - PROTOCAN_OK, если сообщение успешно обработано, + * - PROTOCAN_TIMEOUT, если сообщений не было, + * - или код ошибки, возвращенный функцией обработки. + */ +PROTOCAN_StatusTypeDef PROTOCAN_ProcessSingleRxMsg(void) +{ + PROTOCAN_StatusTypeDef result = PROTOCAN_TIMEOUT; + if(AvailableCanRxMsg()) + { + if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_ANALOG) + { + result = PROTOCAN_AnalogProcessing(rxMsg[CurrentStep]); + } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_BROADCAST) + { + result = PROTOCAN_BroadcastProcessing(rxMsg[CurrentStep]); + } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_DISCRETE) + { + result = PROTOCAN_DiscreticProcessing(rxMsg[CurrentStep]); + } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_GENERAL_ADDRESS_SPACE) + { + result = ProtoCanMsgToGeneralAddressSpace(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 || + rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_MODBUS_INPUT) + { + result = PROTOCAN_ModbusProcessing(rxMsg[CurrentStep]); + } + else if(rxMsg[CurrentStep].eID.Fields.MsgType == PROTOCAN_MSGTYPE_ERROR) + { + result = PROTOCAN_RequestError(rxMsg[CurrentStep]); + } + CurrentStep = (uint16_t)(CurrentStep + 1) % PROTOCAN_RX_BUFFER_SIZE; + } + return result; } /** @@ -568,10 +683,10 @@ __weak PROTOCAN_StatusTypeDef ProtoCanMsgToAnalogUSens(struct RXMsg _rxMsg) 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; + data[2] = '0' + msg.Fields.SensorID / 1000; + data[3] = '0' + msg.Fields.SensorID / 100 % 10; + data[4] = '0' + msg.Fields.SensorID / 10 % 10; + data[5] = '0' + msg.Fields.SensorID % 10; return (PROTOCAN_StatusTypeDef)HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox); } @@ -598,10 +713,10 @@ __weak PROTOCAN_StatusTypeDef ProtoCanMsgToAnalogISens(struct RXMsg _rxMsg) 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; + data[2] = '0' + msg.Fields.SensorID / 1000; + data[3] = '0' + msg.Fields.SensorID / 100 % 10; + data[4] = '0' + msg.Fields.SensorID / 10 % 10; + data[5] = '0' + msg.Fields.SensorID % 10; return (PROTOCAN_StatusTypeDef)HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox); } @@ -628,10 +743,10 @@ __weak PROTOCAN_StatusTypeDef ProtoCanMsgToAnalogTSens(struct RXMsg _rxMsg) 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; + data[2] = '0' + msg.Fields.SensorID / 1000; + data[3] = '0' + msg.Fields.SensorID / 100 % 10; + data[4] = '0' + msg.Fields.SensorID / 10 % 10; + data[5] = '0' + msg.Fields.SensorID % 10; return (PROTOCAN_StatusTypeDef)HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox); } @@ -1085,7 +1200,7 @@ PROTOCAN_StatusTypeDef PROTOCAN_SEND_MODBUS(const ProtoCanId_t id, const struct * @param _rxMsg Структура входящего сообщения RXMsg, данными которого формируется ответ-ошибка. * @return HAL_StatusTypeDef Статус выполнения команды CAN. */ -__weak PROTOCAN_StatusTypeDef CanRequestError(struct RXMsg _rxMsg) +__weak PROTOCAN_StatusTypeDef PROTOCAN_RequestError(struct RXMsg _rxMsg) { CAN_TxHeaderTypeDef TxHeader; uint32_t TxMailBox = 0;