|
FDCAN 代码
/*******************************************************************
* 功能: CAN通信相关
* 创建者:
* 创建时间: 2021-5-16
* 版本: V0.1
* 修改时间:
* 修改人:
* 版权所有:
********************************************************************/
#include <stdio.h>
#include "gpio.h"
#include "fdcan.h"
#include "appTask.h"
FDCAN_HandleTypeDef hfdcan1;
osMessageQId CanRxQueueHandle;
FDCAN_RxHeaderTypeDef FDCAN1_RxHeader,FDCAN2_RxHeader;
/*******************************************************************
时钟源 PLL2Q 80MHz
仲裁段(CANID)波特率:
NominalPrescaler......
数据段(CAN DATA)波特率:
DataPrescaler......
BitRateSwitch:是否允许波特率切换。fdcan仲裁段和数据段可以有不同的波特率。
波特率 = (clk/Prescaler) / (1+TimeSeg1+TimeSeg2) = (80M/4) / (1+31+8) = 0.5MHz
********************************************************************/
FDCAN_TxHeaderTypeDef FDCAN1_TxHeader=
{
.IdType = FDCAN_EXTENDED_ID,
.TxFrameType = FDCAN_DATA_FRAME,
.ErrorStateIndicator = FDCAN_ESI_ACTIVE,
.BitRateSwitch = FDCAN_BRS_OFF,
.FDFormat = FDCAN_CLASSIC_CAN,
.TxEventFifoControl = FDCAN_NO_TX_EVENTS,
.MessageMarker = 0
};
FDCAN_TxHeaderTypeDef FDCAN2_TxHeader=
{
.IdType = FDCAN_EXTENDED_ID,
.TxFrameType = FDCAN_DATA_FRAME,
.ErrorStateIndicator = FDCAN_ESI_ACTIVE,
.BitRateSwitch = FDCAN_BRS_OFF,
.FDFormat = FDCAN_CLASSIC_CAN,
.TxEventFifoControl = FDCAN_NO_TX_EVENTS,
.MessageMarker = 0
};
/*******************************************************************
* 功能: CAN过滤设置
* 输入:
* 输出:
* 备注: CAN_FxR1[31:24] CAN_FxR1[23:16] CAN_FxR1[15:8] CAN_FxR1[7:0]
CAN_FxR2[31:24] CAN_FxR2[23:16] CAN_FxR2[15:8] CAN_FxR2[7:0]
STID[10:3] STID[2:0] EXID[17:13] EXID[12:5] EXID[4:0] IDE RTR 0
CAN ID是MSB,扩展帧29bit占据uint32的高位,最低三位不用
********************************************************************/
static void CAN_FilterConfig(void)
{
FDCAN_FilterTypeDef filterConfig;
uint32_t i, NodeID[2], filterID[2];
#define CAN_STD_ID_START_BIT 21 //标准id的起始位
#define CAN_EXT_ID_START_BIT 3 //拓展id的起始位
NodeID[0] = 0; //广播ID
NodeID[1] = 15; //GetBoardNodeId();//板卡自身相关ID
for (i=0; i<2; i++)
{
NodeID[i] = (NodeID[i]<<24) | FromMainBoard; //根据CAN协议定义,NodeId位于29bit的24~28位
filterConfig.IdType = FDCAN_EXTENDED_ID;
filterConfig.FilterIndex = i;
filterConfig.FilterType = FDCAN_FILTER_MASK;
filterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
filterConfig.FilterID1 = NodeID[i]; //掩码模式:匹配ID设置
filterConfig.FilterID2 = (0x1F << 24) ; //掩码模式:设置掩码,要过滤的NodeID占5位,CANID高5位是板卡地址位
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &filterConfig) != HAL_OK)
Error_Handler();
if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1,FDCAN_REJECT,FDCAN_REJECT,FDCAN_REJECT_REMOTE,FDCAN_REJECT_REMOTE) != HAL_OK)
Error_Handler();
}
}
/*******************************************************************
* 功能:
* 输入:
* 输出:
* 备注:
********************************************************************/
void MX_FDCAN1_Init(void)
{
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = ENABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.NominalPrescaler = 4;
hfdcan1.Init.NominalSyncJumpWidth = 8;
hfdcan1.Init.NominalTimeSeg1 = 31;
hfdcan1.Init.NominalTimeSeg2 = 8;
hfdcan1.Init.DataPrescaler = 4;
hfdcan1.Init.DataSyncJumpWidth = 8;
hfdcan1.Init.DataTimeSeg1 = 31;
hfdcan1.Init.DataTimeSeg2 = 8;
hfdcan1.Init.MessageRAMOffset = 0;
hfdcan1.Init.StdFiltersNbr = 0;
hfdcan1.Init.ExtFiltersNbr = 2;
hfdcan1.Init.RxFifo0ElmtsNbr = 64;
hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxFifo1ElmtsNbr = 0;
hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxBuffersNbr = 0;
hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.TxEventsNbr = 0;
hfdcan1.Init.TxBuffersNbr = 0;
hfdcan1.Init.TxFifoQueueElmtsNbr = 1;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
CAN_FilterConfig();
if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
Error_Handler();
HAL_FDCAN_ActivateNotification(&hfdcan1,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
}
/*******************************************************************
* 功能:
* 输入:
* 输出:
* 备注:
********************************************************************/
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* fdcanHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(fdcanHandle->Instance==FDCAN1)
{
/* USER CODE BEGIN FDCAN1_MspInit 0 */
/* USER CODE END FDCAN1_MspInit 0 */
/* FDCAN1 clock enable */
__HAL_RCC_FDCAN_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
/**FDCAN1 GPIO Configuration
PH13 ------> FDCAN1_TX
PH14 ------> FDCAN1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
/* FDCAN1 interrupt Init */
HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
/* USER CODE BEGIN FDCAN1_MspInit 1 */
/* USER CODE END FDCAN1_MspInit 1 */
}
}
/*******************************************************************
* 功能:
* 输入:
* 输出:
* 备注:
********************************************************************/
void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* fdcanHandle)
{
if(fdcanHandle->Instance==FDCAN1)
{
/* USER CODE BEGIN FDCAN1_MspDeInit 0 */
/* USER CODE END FDCAN1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_FDCAN_CLK_DISABLE();
/**FDCAN1 GPIO Configuration
PH13 ------> FDCAN1_TX
PH14 ------> FDCAN1_RX
*/
HAL_GPIO_DeInit(GPIOH, GPIO_PIN_13|GPIO_PIN_14);
/* FDCAN1 interrupt Deinit */
HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn);
/* USER CODE BEGIN FDCAN1_MspDeInit 1 */
/* USER CODE END FDCAN1_MspDeInit 1 */
}
}
/*******************************************************************
* 功能: CAN发送
* 输入:
* 输出:
* 备注:
********************************************************************/
int32_t Can1Send(CAN_FRAME cF)
{
int32_t ret=HAL_ERROR,lockCnt=0;
static uint32_t mySpinLock=0;
while(1)
{
if (mySpinLock == 0) //增加自旋锁机制,以规避发送时可能的竞争
{
mySpinLock = 1;
FDCAN1_TxHeader.Identifier = cF.Id;
FDCAN1_TxHeader.DataLength = cF.Len << 16;
for (int i=0; i<3; i++)
{
ret = HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1,&FDCAN1_TxHeader,cF.Data);
if (ret == HAL_OK)
break;
HAL_Delay(1);
}
mySpinLock = 0;
BJ_printf("CAN Tx: 0x%08X\t",cF.Id);
for (int i=0; i<cF.Len; i++)
BJ_printf("%02X ",cF.Data[i]);
BJ_printf("\n");
if(ret != HAL_OK)
printf("Can Tx Fail! ECode=%d\n",hfdcan1.ErrorCode);
break;
}
else
{
if (lockCnt++ < 5)
HAL_Delay(1);
else
{
ret = HAL_ERROR;
break;
}
printf("canLock:%d\n",lockCnt);
}
}
return ret;
}
/*******************************************************************
* 功能: CAN接收(查询方式)
* 输入:
* 输出:
* 备注:
********************************************************************/
uint8_t FDCAN1_Receive_Msg(uint8_t *buf)
{
if(HAL_FDCAN_GetRxMessage(&hfdcan1,FDCAN_RX_FIFO0,&FDCAN1_RxHeader,buf)!=HAL_OK)
return 0;
return FDCAN1_RxHeader.DataLength>>16;
}
/*******************************************************************
* 功能: CAN接收中断处理函数
* 输入:
* 输出:
* 备注:
********************************************************************/
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
BaseType_t tWoken;
BaseType_t err;
CAN_FRAME cf={0};
FDCAN_RxHeaderTypeDef RxHeader;
if((RxFifo0ITs&FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
{
HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, cf.Data);
cf.Id = RxHeader.Identifier;
cf.Len = RxHeader.DataLength >> 16;
err = xQueueSendFromISR(CanRxQueueHandle, (uint8_t *)&cf, &tWoken); //缓存之
if(err == errQUEUE_FULL)
printf("Error! CAN Queue Full!\n");
HAL_FDCAN_ActivateNotification(hfdcan,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
}
}
|
|