#include "sn65hvd230_g0.h" /** * @brief Инициализация структуры и привязка к FDCAN в STM32G0 */ HAL_StatusTypeDef SN65HVD230_Init(SN65HVD230_t *node, FDCAN_HandleTypeDef *hfdcan_handle) { if (node == NULL || hfdcan_handle == NULL) { return HAL_ERROR; } node->hfdcan = hfdcan_handle; return HAL_OK; } /** * @brief Запуск периферийного модуля FDCAN */ HAL_StatusTypeDef SN65HVD230_Start(SN65HVD230_t *node) { if (node == NULL || node->hfdcan == NULL) return HAL_ERROR; // Активируем прерывание по заполнению FIFO 0 (потребуется, если включите IT-режим в CubeMX) HAL_FDCAN_ActivateNotification(node->hfdcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0); return HAL_FDCAN_Start(node->hfdcan); } /** * @brief Остановка модуля FDCAN */ HAL_StatusTypeDef SN65HVD230_Stop(SN65HVD230_t *node) { if (node == NULL || node->hfdcan == NULL) return HAL_ERROR; return HAL_FDCAN_Stop(node->hfdcan); } /** * @brief Отправка пакета данных в шину (Классический CAN-кадр через FDCAN) */ HAL_StatusTypeDef SN65HVD230_Transmit(SN65HVD230_t *node, CAN_Message_t *msg, uint32_t timeout_ms) { if (node == NULL || node->hfdcan == NULL || msg == NULL) return HAL_ERROR; uint32_t tickstart = HAL_GetTick(); FDCAN_TxHeaderTypeDef TxHeader; // Конфигурация заголовка кадра в стиле G0 FDCAN TxHeader.Identifier = msg->Identifier; TxHeader.IdType = msg->IdType; TxHeader.TxFrameType = msg->TxFrameType; TxHeader.DataLength = msg->DataLength; // Константы типа FDCAN_DLC_BYTES_8 TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; TxHeader.BitRateSwitch = FDCAN_BRS_OFF; // Выключаем ускорение данных (для классического CAN) TxHeader.FDFormat = FDCAN_CLASSIC_CAN; // Работаем в режиме совместимости с обычным CAN TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS; TxHeader.MessageMarker = 0; // Ожидаем, пока в TX FIFO освободится хотя бы одна ячейка while (HAL_FDCAN_GetTxFifoFreeLevel(node->hfdcan) == 0) { if ((HAL_GetTick() - tickstart) > timeout_ms) { return HAL_TIMEOUT; } } // Помещаем сообщение в очередь отправки FDCAN return HAL_FDCAN_AddMessageToTxFifoQ(node->hfdcan, &TxHeader, msg->Data); } /** * @brief Опрашивающий (блокирующий) прием кадра из FIFO 0 */ HAL_StatusTypeDef SN65HVD230_Receive(SN65HVD230_t *node, CAN_Message_t *msg, uint32_t timeout_ms) { if (node == NULL || node->hfdcan == NULL || msg == NULL) return HAL_ERROR; uint32_t tickstart = HAL_GetTick(); FDCAN_RxHeaderTypeDef RxHeader; // Ожидаем появления нового сообщения в FIFO 0 while (HAL_FDCAN_GetRxFifoFillLevel(node->hfdcan, FDCAN_RX_FIFO0) == 0) { if ((HAL_GetTick() - tickstart) > timeout_ms) { return HAL_TIMEOUT; } } // Вычитываем данные из FIFO 0 if (HAL_FDCAN_GetRxMessage(node->hfdcan, FDCAN_RX_FIFO0, &RxHeader, msg->Data) == HAL_OK) { msg->Identifier = RxHeader.Identifier; msg->IdType = RxHeader.IdType; msg->TxFrameType = RxHeader.RxFrameType; msg->DataLength = RxHeader.DataLength; return HAL_OK; } return HAL_ERROR; }