93 lines
3.6 KiB
C
93 lines
3.6 KiB
C
#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;
|
||
}
|