Функция отправки сообщений

Пока только PROTOCAN_MSGTYPE_GENERAL_ADDRESS_SPACE
This commit is contained in:
2026-06-01 15:20:13 +03:00
parent 757d608ad4
commit 4da9640c3f
2 changed files with 104 additions and 0 deletions

View File

@@ -255,6 +255,7 @@ PROTOCAN_INIT_StatusTypeDef PROTOCAN_INIT(CAN_HandleTypeDef *tmp_hcan,
void PROTOCAN_DEINIT(uint8_t stage);
void PROTOCAN_FILTERS(void);
void PROTOCAN_LOOP(void);
PROTOCAN_StatusTypeDef PROTOCAN_SEND(ProtoCanId_t id, ProtoCanData_t data);
void ProtoCanPulseCallback(TIM_HandleTypeDef *htim);
void ProtoCanRxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan);

View File

@@ -111,6 +111,19 @@ PROTOCAN_INIT_StatusTypeDef PROTOCAN_INIT(CAN_HandleTypeDef *tmp_hcan, RTC_Handl
*/
void PROTOCAN_LOOP(void)
{
ProtoCanId_t testId;
testId.BitAll = 0;
testId.Fields.Priority = PROTOCAN_PRIORITY_STANDARD;
testId.Fields.Route = PROTOCAN_ROUTE_FROM_DEVICE;
testId.Fields.DeviceType = CURRENT_TYPE_DEVICE;
testId.Fields.DeviceID = CURRENT_ID_DEVICE;
testId.Fields.MsgType = PROTOCAN_MSGTYPE_GENERAL_ADDRESS_SPACE;
ProtoCanData_t testData;
uint16_t massiv[] = {0xABCD, 0x1234, 0xAFBF, 0x5678, 0x9AF1};
testData.GeneralAddressSpaceData.Data = massiv;
testData.GeneralAddressSpaceData.RegCount = 5;
testData.GeneralAddressSpaceData.RegStartAdr = 0xFA;
while(1)
{
if(AvailableCanRxMsg())
@@ -144,6 +157,7 @@ void PROTOCAN_LOOP(void)
}
CurrentStep = (uint16_t)(CurrentStep + 1) % PROTOCAN_RX_BUFFER_SIZE;
}
PROTOCAN_SEND(testId, testData);
}
}
@@ -659,6 +673,60 @@ __weak PROTOCAN_StatusTypeDef ProtoCanMsgToGeneralAddressSpace(struct RXMsg _rxM
return (PROTOCAN_StatusTypeDef)HAL_CAN_AddTxMessage(_HCAN, &TxHeader, data, &TxMailBox);
}
/**
* @brief Отправляет произвольный диапазон регистров в пакетах по, максимум, 4 регистра за раз через CAN.
*
* Функция разбивает передаваемый массив регистров на пакеты по 4 или меньше и отправляет их по отдельности.
* Для каждого пакета формируется уникальный MsgBody, равный адресу первого регистра в пакете.
*
* @param priority Приоритет сообщения CAN. ProtoCan_Priority_TypeDef
* @param regStartAdr Адрес первого регистра из всего массива.
* @param data Указатель на массив регистров для отправки.
* @param regCount Общее количество регистров для отправки.
*
* @return Возвращает статус отправки: HAL_OK при успехе, или код ошибки HAL_StatusTypeDef при сбое.
*/
PROTOCAN_StatusTypeDef PROTOCAN_SEND_GENERAL_ADDRESS_SPACE(ProtoCanId_t id, uint16_t regStartAdr, uint16_t *data, uint8_t regCount)
{
CAN_TxHeaderTypeDef TxHeader;
uint32_t TxMailBox = 0;
uint8_t canData[8];
TxHeader.IDE = CAN_ID_EXT;
TxHeader.TransmitGlobalTime = DISABLE;
TxHeader.RTR = CAN_RTR_DATA;
ProtoCanId_t tmp_eID;
tmp_eID.BitAll = id.BitAll;
uint8_t regsRemaining = regCount;
uint8_t currentIndex = 0;
while(regsRemaining > 0)
{
uint8_t regsInPacket = (regsRemaining > 4) ? 4 : regsRemaining;
tmp_eID.Fields.MsgBody = regStartAdr + currentIndex;
TxHeader.ExtId = tmp_eID.BitAll;
TxHeader.DLC = regsInPacket*2;
for(int i = 0; i < regsInPacket; i++)
{
canData[(i*2)+1] = LowByteOfWord(data[currentIndex+i]);
canData[(i*2)] = HighByteOfWord(data[currentIndex+i]);
}
HAL_StatusTypeDef status = HAL_CAN_AddTxMessage(_HCAN, &TxHeader, canData, &TxMailBox);
if(status != HAL_OK)
{
return (PROTOCAN_StatusTypeDef)status;
}
regsRemaining -= regsInPacket;
currentIndex += regsInPacket;
}
return (PROTOCAN_StatusTypeDef)HAL_OK;
}
/**
@@ -1044,3 +1112,38 @@ void PROTOCAN_FILTERS()
// Третий фильтр: проверяем 16-19 биты, равны PROTOCAN_MSGTYPE_PULSE
PROTOCAN_CONFIG_FILTER(2, filter3_id, filter3_mask);
}
/**
* @brief Отправляет CAN-сообщение в зависимости от типа сообщения.
*
* Эта функция анализирует тип сообщения в идентификаторе и вызывает
* соответствующую функцию отправки. В текущей реализации поддерживается только
* тип PROTOCAN_MSGTYPE_GENERAL_ADDRESS_SPACE.
*
* @param id Идентификатор CAN-сообщения, содержащий информацию о типе.
* @param data Структура с данными, которые необходимо отправить. Зависит от типа сообщения.
*
* @return Статус выполнения операции:
* - PROTOCAN_OK при успешной отправке,
* - PROTOCAN_ERROR, если тип сообщения не поддерживается или произошла ошибка.
*/
PROTOCAN_StatusTypeDef PROTOCAN_SEND(ProtoCanId_t id, ProtoCanData_t data)
{
switch (id.Fields.MsgType)
{
case PROTOCAN_MSGTYPE_GENERAL_ADDRESS_SPACE:
{
/* Если есть регистры для отправки, указатель data должен быть валиден. */
if((data.GeneralAddressSpaceData.RegCount > 0U) && data.GeneralAddressSpaceData.Data == 0)
{
return PROTOCAN_ERROR;
}
return PROTOCAN_SEND_GENERAL_ADDRESS_SPACE(id, data.GeneralAddressSpaceData.RegStartAdr,
data.GeneralAddressSpaceData.Data,
data.GeneralAddressSpaceData.RegCount);
}
default:
return PROTOCAN_ERROR;
}
return PROTOCAN_ERROR;
}