|
STM32H743can配置成经典CAN,正常模式发送数据,TX引脚无信号,外部回环模式发送数据,TX引脚有信号。代码如下:
#include "bsp_debug.h"
#include "bsp_can.h"
/******************************************************************************/
#define FDCAN1_RX_PIN GPIO_PIN_8
#define FDCAN1_RX_GPIO_PORT GPIOB
#define FDCAN1_RX_AF GPIO_AF9_FDCAN1
#define FDCAN1_RX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define FDCAN1_TX_PIN GPIO_PIN_9
#define FDCAN1_TX_GPIO_PORT GPIOB
#define FDCAN1_TX_AF GPIO_AF9_FDCAN1
#define FDCAN1_TX_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
/******************************* 全局变量声明 *********************************/
/******************************* 内部变量声明 *********************************/
static FDCAN_HandleTypeDef s_Fdcan1Handler;
static FDCAN_TxHeaderTypeDef FDCAN1_TxHeader;
static FDCAN_RxHeaderTypeDef FDCAN1_RxHeader;
static uint8_t FDCAN1_TxData[8]={1,2,3,4,5,6,7,189};
static uint8_t FDCAN1_RxData[16];
/******************************* 内部函数声明 *********************************/
static void FDCAN1_Mode_Init(void);
/******************************************************************************/
/**
* @brief FDCAN1底层驱动,时钟使能,HAL_FDCAN_Init()调用
* @param None
* @retval None
*/
void Can1Config(void)
{
FDCAN1_Mode_Init();
HAL_FDCAN_Start(&s_Fdcan1Handler);
}
HAL_StatusTypeDef FdcanSend(void)
{
HAL_StatusTypeDef res = HAL_ERROR;
FDCAN1_TxHeader.Identifier = 0x222; // 32位ID
FDCAN1_TxHeader.IdType = FDCAN_STANDARD_ID; // 标准ID
FDCAN1_TxHeader.TxFrameType = FDCAN_DATA_FRAME; // 帧类型
FDCAN1_TxHeader.DataLength = FDCAN_DLC_BYTES_8; // 数据长度
FDCAN1_TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
FDCAN1_TxHeader.BitRateSwitch = FDCAN_BRS_OFF; // 关闭速率切换
FDCAN1_TxHeader.FDFormat = FDCAN_CLASSIC_CAN; // 传统的CAN模式
FDCAN1_TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS; // 无发送事件
FDCAN1_TxHeader.MessageMarker = 0;
res = HAL_FDCAN_AddMessageToTxFifoQ(&s_Fdcan1Handler, &FDCAN1_TxHeader, FDCAN1_TxData);
return res;
}
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
if (hfdcan == &s_Fdcan1Handler)
{
if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_WATERMARK) != RESET)
{
/* 从 RX FIFO0 读取数据 */
HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &FDCAN1_RxHeader, FDCAN1_RxData);
/* 激活 Rx FIFO0 watermark notification */
HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
if (FDCAN1_RxHeader.Identifier == 0x111 && FDCAN1_RxHeader.IdType == FDCAN_STANDARD_ID)
{
// DEBUG_PRINTF("Rx FIFO0: %d %d %d %d %d %d %d %d\r\n",
// FDCAN1_RxData[0],FDCAN1_RxData[1],FDCAN1_RxData[2],FDCAN1_RxData[3],
// FDCAN1_RxData[4],FDCAN1_RxData[5],FDCAN1_RxData[6],FDCAN1_RxData[7]);
}
}
}
}
/**
* @brief 获取FDCAN1句柄
* @param FdcanHandler fdcan句柄的指针
* @retval None
*/
void GetFdcan1Handler(FDCAN_HandleTypeDef **FdcanHandler)
{
*FdcanHandler = &s_Fdcan1Handler;
}
/**
* @brief DCAN1底层驱动,引脚配置,时钟使能,HAL_FDCAN_Init()调用
* @note FDCAN1 时钟配置
* 选择PPL2为时钟源
* FDCAN1时钟频率 = HSE /PLL2M * PLL2N / PLL2Q
* HSE = 8MHz
* 20MHz = 8 / 1 * 20 / 8
* @param hfdcan: FDCAN1句柄
* @retval None
*/
void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef *hfdcan)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
switch ((uint32_t)(hfdcan->Instance))
{
case (uint32_t)FDCAN1:
/* 使能时钟 */
__HAL_RCC_FDCAN_CLK_ENABLE();
FDCAN1_TX_GPIO_CLK_ENABLE();
FDCAN1_RX_GPIO_CLK_ENABLE();
/* 选择PLL2Q作为FDCANx时钟 */
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_FDCAN; /* 为FDCAN配置时钟 */
PeriphClkInitStruct.FdcanClockSelection = RCC_FDCANCLKSOURCE_PLL2; /* 选择PLL2Q作为FDCANx时钟 */
PeriphClkInitStruct.PLL2.PLL2M = 1;
PeriphClkInitStruct.PLL2.PLL2N = 20;
PeriphClkInitStruct.PLL2.PLL2P = 2;
PeriphClkInitStruct.PLL2.PLL2Q = 8;
PeriphClkInitStruct.PLL2.PLL2R = 2;
PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_2; /* 时钟频率输入范围 */
PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE; /* 时钟频率输出范围*/
PeriphClkInitStruct.PLL2.PLL2FRACN = 0; /* 指定乘法因子的小数部分 */
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
}
GPIO_InitStruct.Pin = FDCAN1_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = FDCAN1_TX_AF;
HAL_GPIO_Init(FDCAN1_TX_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = FDCAN1_RX_PIN;
GPIO_InitStruct.Alternate = FDCAN1_RX_AF;
HAL_GPIO_Init(FDCAN1_RX_GPIO_PORT, &GPIO_InitStruct);
HAL_NVIC_SetPriority(FDCAN1_IT0_IRQn, 3, 0);
HAL_NVIC_SetPriority(FDCAN1_IT1_IRQn, 3, 0);
HAL_NVIC_SetPriority(FDCAN_CAL_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
HAL_NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
HAL_NVIC_EnableIRQ(FDCAN_CAL_IRQn);
break;
default:
break;
}
}
/**
* @brief FDCAN配置复位,此函数会被HAL_FDCAN_DeInit调用
* @param hfdcan: FDCAN句柄
* @retval None
*/
void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef *hfdcan)
{
switch ((uint32_t)(hfdcan->Instance))
{
case (uint32_t)FDCAN1:
__HAL_RCC_FDCAN_FORCE_RESET(); /* 复位FDCAN1 */
__HAL_RCC_FDCAN_RELEASE_RESET(); /* 解除复位FDCAN1 */
HAL_GPIO_DeInit(FDCAN1_TX_GPIO_PORT, FDCAN1_TX_PIN);
HAL_GPIO_DeInit(FDCAN1_RX_GPIO_PORT, FDCAN1_RX_PIN);
HAL_NVIC_DisableIRQ(FDCAN1_IT0_IRQn);
HAL_NVIC_DisableIRQ(FDCAN1_IT1_IRQn);
HAL_NVIC_DisableIRQ(FDCAN_CAL_IRQn);
break;
case (uint32_t)FDCAN2:
break;
default:
break;
}
}
/**
* @brief FDCAN1中断0服务函数
* @param None
* @retval None
*/
void FDCAN1_IT0_IRQHandler(void)
{
HAL_FDCAN_IRQHandler(&s_Fdcan1Handler);
}
/**
* @brief FDCAN1中断1服务函数
* @param None
* @retval None
*/
void FDCAN1_IT1_IRQHandler(void)
{
HAL_FDCAN_IRQHandler(&s_Fdcan1Handler);
}
/**
* @brief FDCAN1校准中断服务函数
* @param None
* @retval None
*/
void FDCAN_CAL_IRQHandler(void)
{
HAL_FDCAN_IRQHandler(&s_Fdcan1Handler);
}
/***************************** 内部功能函数 -- start **************************/
/**
* @brief FDCAN模式初始化配置
* @param None
* @retval None
*/
static void FDCAN1_Mode_Init(void)
{
/* 位时间特性配置
Bit time parameter | Nominal | Data
---------------------------|--------------|----------------
fdcan_ker_ck | 20 MHz | 20 MHz
Time_quantum (tq) | 50 ns | 50 ns
Synchronization_segment | 1 tq | 1 tq
Propagation_segment | 23 tq | 1 tq
Phase_segment_1 | 8 tq | 4 tq
Phase_segment_2 | 8 tq | 4 tq
Synchronization_Jump_width | 8 tq | 4 tq
Bit_length | 40 tq = 2us | 10 tq = 0.5us
Bit_rate | 0.5 MBit/s | 2 MBit/s
*/
/************************ 初始化FDCAN1 ************************/
HAL_FDCAN_DeInit(&s_Fdcan1Handler); /* 先清除以前的设置 */
/************************ 基础配置 ************************/
s_Fdcan1Handler.Instance = FDCAN1; /* 设置FDCAN1 */
s_Fdcan1Handler.Init.FrameFormat = FDCAN_FRAME_CLASSIC; /* 经典模式 */
s_Fdcan1Handler.Init.Mode = FDCAN_MODE_NORMAL; /* 正常模式 */
s_Fdcan1Handler.Init.AutoRetransmission = ENABLE; /* 自动重传 */
s_Fdcan1Handler.Init.TransmitPause = DISABLE; /* 禁止暂停传输 */
s_Fdcan1Handler.Init.ProtocolException = ENABLE; /* 启用协议异常处理 */
/************************ 波特率设置 ************************/
/*
配置仲裁阶段波特率
CAN时钟20MHz时,仲裁阶段的波特率就是
CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / 2 / (1+5+ 4) = 1Mbps
其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg2
*/
s_Fdcan1Handler.Init.NominalPrescaler = 0x02; /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck) */
s_Fdcan1Handler.Init.NominalSyncJumpWidth = 0x04; /* 用于动态调节 Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */
s_Fdcan1Handler.Init.NominalTimeSeg1 = 0x05; /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */
s_Fdcan1Handler.Init.NominalTimeSeg2 = 0x04; /* 对应位时间特性图的 Phase_Seg2 */
/************************ RAM管理器配置 ************************/
s_Fdcan1Handler.Init.MessageRAMOffset = 0; /* 信息RAM偏移 */
s_Fdcan1Handler.Init.StdFiltersNbr = 4; /* 标准信息ID滤波器数量 */
s_Fdcan1Handler.Init.ExtFiltersNbr = 4; /* 扩展信息ID滤波器数量 */
s_Fdcan1Handler.Init.RxFifo0ElmtsNbr = 64; /* 接收FIFO0元素数量 */
s_Fdcan1Handler.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; /* 接收FIFO0元素大小:8字节 */
s_Fdcan1Handler.Init.RxFifo1ElmtsNbr = 16; /* 接收FIFO1元素数量 */
s_Fdcan1Handler.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; /* 接收FIFO1元素大小:8字节 */
s_Fdcan1Handler.Init.RxBuffersNbr = 16; /* 接收缓冲数量*/
s_Fdcan1Handler.Init.RxBufferSize = FDCAN_DATA_BYTES_8; /* 接收缓冲元素大小:8字节 */
s_Fdcan1Handler.Init.TxEventsNbr = 16; /* 发送事件数量 */
s_Fdcan1Handler.Init.TxBuffersNbr = 8; /* 发送缓冲数量 */
s_Fdcan1Handler.Init.TxFifoQueueElmtsNbr = 32; /* 发送FIFO序列元素数量 */
s_Fdcan1Handler.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* 发送FIFO序列模式 */
s_Fdcan1Handler.Init.TxElmtSize = FDCAN_DATA_BYTES_8; /* 发送大小:8字节 */
if (HAL_FDCAN_Init(&s_Fdcan1Handler) != HAL_OK) /* 初始化FDCAN1*/
{
}
}
/**************************** 内部功能函数 -- end *****************************/
|
|