恩智浦支持人员你好,
目前我正在开发恩智浦 KW45B41Z-EVK 板。我的目标是从 BLE 板上传输 CAN 帧。我曾尝试使用 SDK 示例,但它不能提供 CAN 的直接接口。
我无法传输 CAN 帧。仅供参考,我正在使用 Technica CAN 捕获模块。
期待您的及时帮助。
所以,我开发了一个自定义应用程序,以下是代码供你参考:
#include"fsl_debug_console.h"
#include"fsl_flexcan.h"
#include "board.h"
#include"app.h"
/*******************************************************************************
* 定义
******************************************************************************/
/* 修正 MISRA_C-2012 第 17.7 条规则。*/
#define LOG_INFO (void)PRINTF
#ifndef USE_CANFD
#define USE_CANFD (1)
#endif
#ifndef EXAMPLE_CAN_BIT_RATE
#define EXAMPLE_CAN_BIT_RATE (500000U)
#endif
#ifndef EXAMPLE_CAN_BIT_RATE_FD
#define EXAMPLE_CAN_BIT_RATE_FD (2000000U)
#endif
#define USE_PHY_TJA1152 (1)
#if (defined(USE_CANFD)&& USE_CANFD)
/*
* DWORD_IN_MB DLC BYTES_IN_MB 最大 MB 数
* 2 8 kFLEXCAN_8BperMB 32(1 个 RAM 块) 64(2 个 RAM 块) 96(3 个 RAM 块)
* 4 10 kFLEXCAN_16BperMB 21(1 个 RAM 块) 42(2 个 RAM 块) 63(3 个 RAM 块)
* 8 13 kFLEXCAN_32BperMB 12(1 个 RAM 块) 24(2 个 RAM 块) 36(3 个 RAM 块)
* 16 15 kFLEXCAN_64BperMB 7(1 个 RAM 块) 14(2 个 RAM 块) 21(3 个 RAM 块)
*
* 每个消息缓冲区中的 Dword,以字节为单位的数据长度,有效负载大小必须一致,
* 信息缓冲区的限制与每个有效载荷配置相对应:
*/
#define DWORD_IN_MB (16)
#define DLC (15)
#define BYTES_IN_MB kFLEXCAN_64BperMB
#else
#define DLC (8)
#endif
/*******************************************************************************
* 原型
******************************************************************************/
/*******************************************************************************
* 变量
******************************************************************************/
flexcan_handle_t flexcanHandle;
volatile bool txComplete = false;
flexcan_mb_transfer_t txXfer;
#if (defined(USE_CANFD)&& USE_CANFD)
flexcan_fd_frame_t frame;
#else
flexcan_frame_t frame;
#endif
static const uint32_t kFlexcanTxId = 0x123U;
#if (defined(USE_CANFD)&& USE_CANFD)
static const uint8_t kPayloadSize = 64U;
static const uint8_t kFrameLength = (uint8_t)DLC;
#else
static const uint8_t kPayloadSize = 8U;
static const uint8_t kFrameLength = (uint8_t)DLC;
#endif
/*******************************************************************************
* 代码
******************************************************************************/
/*!
* CAN 收发器简要配置功能
*/
static void FLEXCAN_PHY_Config(void)
{
/* 始终确保收发器待机引脚处于驱动状态。*/
GPIO_PortSet(EXAMPLE_STB_RGPIO, 1u<< EXAMPLE_STB_RGPIO_PIN);
#if (defined(USE_PHY_TJA1152)&& USE_PHY_TJA1152)
/* 初始化 TJA1152。*/
/* STB=H,配置 CAN 信息将通过 TXD 引脚从本地主机发送。*/
/* 必须传输带有标准标识符 0x555 的经典 CAN 报文
在 TJA1152 確認之前,本地主機控制器將 * 儲存在 TJA1152 中。
* 自动检测比特率。不要设置 frame.brs = 1U,以保持标称值
* CANFD 帧数据阶段的比特率。*/
frame.id = FLEXCAN_ID_STD(0x555);
frame.format = (uint8_t)kFLEXCAN_FrameFormatStandard;
frame.type = (uint8_t)kFLEXCAN_FrameTypeData;
frame.length = 0U;
txXfer.mbIdx = (uint8_t)TX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD)&& USE_CANFD)
txXfer.framefd =&frame;
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN,&flexcanHandle,&txXfer);
#else
txXfer.frame =&frame;
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN,&flexcanHandle,&txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
/* 配置欺骗保护。*/
/* 在传输白名单中添加 0x321 和 0x123。*/
frame.id = FLEXCAN_ID_EXT(0x18DA00F1);
frame.format = (uint8_t)kFLEXCAN_FrameFormatExtend;
frame.type = (uint8_t)kFLEXCAN_FrameTypeData;
frame.length = 6U;
#if (defined(USE_CANFD)&& USE_CANFD)
frame.dataWord[0]= CAN_WORD_DATA_BYTE_0(0x10) | CAN_WORD_DATA_BYTE_1(0x00) | CAN_WORD_DATA_BYTE_2(0x33) | CAN_WORD_DATA_1(0x00) | CAN_WORD_DATA_BYTE_2(0x33)
CAN_WORD_DATA_BYTE_3(0x21);
frame.dataWord[1]= CAN_WORD_DATA_BYTE_4(0x11) | CAN_WORD_DATA_BYTE_5(0x23);
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN,&flexcanHandle,&txXfer);
#else
frame.dataWord0 = CAN_WORD0_DATA_BYTE_0(0x10) | CAN_WORD0_DATA_BYTE_1(0x00) | CAN_WORD0_DATA_BYTE_2(0x33) | CAN_WORD0_DATA_BYTE_2(0x33) | CAN_WORD0_DATA_BYTE_2(0x33)
CAN_WORD0_DATA_BYTE_3(0x21);
frame.dataWord1 = CAN_WORD1_DATA_BYTE_4(0x11) | CAN_WORD1_DATA_BYTE_5(0x23);
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN,&flexcanHandle,&txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
/* 配置命令信息 ID。*/
/* 只接受本地重新配置。保持 CONFIG_ID 为默认值 0x18DA00F1。*/
frame.length = 5U;
#if (defined(USE_CANFD)&& USE_CANFD)
frame.dataWord[0]= CAN_WORD_DATA_BYTE_0(0x60) | CAN_WORD_DATA_BYTE_1(0x98) | CAN_WORD_DATA_BYTE_2(0xDA) | CAN_WORD_DATA_1(0x98) | CAN_WORD_DATA_BYTE_2(0xDA)
CAN_WORD_DATA_BYTE_3(0x00);
frame.dataWord[1]= CAN_WORD_DATA_BYTE_4(0xF1);
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN,&flexcanHandle,&txXfer);
#else
frame.dataWord0 = CAN_WORD0_DATA_BYTE_0(0x60) | CAN_WORD0_DATA_BYTE_1(0x98) | CAN_WORD0_DATA_BYTE_2(0xDA) | CAN_WORD0_DATA_BYTE_2(0xDA)
CAN_WORD0_DATA_BYTE_3(0x00);
frame.dataWord1 = CAN_WORD1_DATA_BYTE_4(0xF1);
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN,&flexcanHandle,&txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
/* 离开配置模式。*/
/* 仅配置到易失性存储器中。*/
frame.length = 8U;
#if (defined(USE_CANFD)&& USE_CANFD)
frame.dataWord[0]= CAN_WORD_DATA_BYTE_0(0x71) | CAN_WORD_DATA_BYTE_1(0x02) | CAN_WORD_DATA_BYTE_2(0x03) | CAN_WORD_DATA_2(0x03)
CAN_WORD_DATA_BYTE_3(0x04);
frame.dataWord[1]= CAN_WORD_DATA_BYTE_4(0x05) | CAN_WORD_DATA_BYTE_5(0x06) | CAN_WORD_DATA_BYTE_6(0x07) | CAN_WORD_DATA_BYTE_5(0x06) | CAN_WORD_DATA_BYTE_6(0x07)
CAN_WORD_DATA_BYTE_7(0x08);
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN,&flexcanHandle,&txXfer);
#else
frame.dataWord0 = CAN_WORD0_DATA_BYTE_0(0x71) | CAN_WORD0_DATA_BYTE_1(0x02) | CAN_WORD0_DATA_BYTE_2(0x03) | CAN_WORD0_DATA_BYTE_1(0x03) | CAN_WORD0_DATA_BYTE_2(0x03)
CAN_WORD0_DATA_BYTE_3(0x04);
frame.dataWord1 = CAN_WORD1_DATA_BYTE_4(0x05) | CAN_WORD1_DATA_BYTE_5(0x06) | CAN_WORD1_DATA_BYTE_6(0x07) | CAN_WORD1_DATA_6(0x07)
CAN_WORD1_DATA_BYTE_7(0x08);
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN,&flexcanHandle,&txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
LOG_INFO("Initialize TJA1152 successfully!\r\n\rn");
/* 初始化 TJA1152 结束。*/
#endif
/* 版本收发器待机状态以驱动 CANH/CANL。*/
GPIO_PortClear(EXAMPLE_STB_RGPIO, 1u<< EXAMPLE_STB_RGPIO_PIN);
}
/*!
* 简短的 FlexCAN 回电功能
*/
static FLEXCAN_CALLBACK(flexcan_callback)
{
LOG_INFO("status:%d\n", status);
开关
{
情况 kStatus_FLEXCAN_TxIdle:
如果 (TX_MESSAGE_BUFFER_NUM == result)
{
txComplete = true;
}
打破;
默认:
打破;
}
}
/*!
* @brief 主要功能
*/
int main(void)
{
flexcan_config_t flexcanConfig;
uint8_t txCounter = 0U;
/* 初始化板硬件。*/
BOARD_InitHardware();
LOG_INFO("********* FLEXCAN Continuous TX EXAMPLE *********\r\n");
LOG_INFO(" Message format:Standard (11 bit id)/r\n");
#if (defined(USE_CANFD)&& USE_CANFD)
LOG_INFO(" Frame type : CAN FD with BRS\r\n");
LOG_INFO(" Nominal/Data bit rates:%u /%u bps\r\n", EXAMPLE_CAN_BIT_RATE, EXAMPLE_CAN_BIT_RATE_FD);
LOG_INFO (" 有效负载长度:%u 字节\ r\n ", KPayloadSize);
#else
LOG_INFO(" Frame type : Classical CAN\r\n");
LOG_INFO(" Bit rate :%u bps\r\n", EXAMPLE_CAN_BIT_RATE);
LOG_INFO (" 有效负载长度:%u 字节\ r\n ", KPayloadSize);
#endif
LOG_INFO(" Message buffer%d used for Tx.\r\n", TX_MESSAGE_BUFFER_NUM);
LOG_INFO(" Interrupt Mode: Enabled\r\n");
LOG_INFO(" Operation Mode: Continuous transmit\r\n");
LOG_INFO("*********************************************\r\n\r\n");
LOG_INFO("Starting continuous CAN transmissions on ID 0x%3x\r\n\r\n", kFlexcanTxId);
/* 获取 FlexCAN 模块默认配置。*/
/*
* flexcanConfig.clkSrc = kFLEXCAN_ClkSrc0;
* flexcanConfig.bitRate = 1000000U;
* flexcanConfig.bitRateFD = 2000000U;
* flexcanConfig.maxMbNum = 16;
* flexcanConfig.enableLoopBack = false;
* flexcanConfig.enableSelfWakeup = false;
* flexcanConfig.enableIndividMask = false;
* flexcanConfig.disableSelfReception = false;
* flexcanConfig.enableListenOnlyMode = false;
* flexcanConfig.enableDoze = false;
*/
FLEXCAN_GetDefaultConfig(&flexcanConfig);
flexcanConfig.bitRate = EXAMPLE_CAN_BIT_RATE;
flexcanConfig.disableSelfReception = true;
#if (defined(USE_CANFD)&& USE_CANFD)
flexcanConfig.bitRateFD = EXAMPLE_CAN_BIT_RATE_FD;
#endif
#if defined(EXAMPLE_CAN_CLK_SOURCE)
flexcanConfig.clksrc=EXAMPLE_CAN_CLK_SOURCE;
#endif
/* 如果需要特殊的量子设置,请设置定时参数。*/
#if (defined(SET_CAN_QUANTUM)&& SET_CAN_QUANTUM)
flexcanConfig.timingConfig.phaseSeg1 = PSEG1;
flexcanConfig.timingConfig.phaseSeg2 = PSEG2;
flexcanConfig.timingConfig.propSeg = PROPSEG;
#if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)&& FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
flexcanConfig.timingConfig.fphaseSeg1 = FPSEG1;
flexcanConfig.timingConfig.fphaseSeg2 = FPSEG2;
flexcanConfig.timingConfig.fpropSeg = FPROPSEG;
#endif
#endif
#if (defined(USE_IMPROVED_TIMING_CONFIG)&& USE_IMPROVED_TIMING_CONFIG)
flexcan_timing_config_t timing_config;
memset(&timing_config, 0, sizeof(flexcan_timing_config_t));
#if (defined(USE_CANFD)&& USE_CANFD)
如果(FLEXCAN_FDCalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.bitRate、flexcanConfig.bitRateFD、
EXAMPLE_CAN_CLK_FREQ,&timing_config))
{
/* 更新改进后的定时配置*/
memcpy(&(flexcanConfig.timingConfig),&timing_config, sizeof(flexcan_timing_config_t));
}
不然
{
LOG_INFO("未找到改进的定时配置。只是使用了默认的 configuration\r\n\r\n" );
}
#else
如果(FLEXCAN_CalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.bitRate、EXAMPLE_CAN_CLK_FREQ,&timing_config))
{
/* 更新改进后的定时配置*/
memcpy(&(flexcanConfig.timingConfig),&timing_config, sizeof(flexcan_timing_config_t));
}
不然
{
LOG_INFO("未找到改进的定时配置。只是使用了默认的 configuration\r\n\r\n" );
}
#endif
#endif
#if (defined(USE_CANFD)&& USE_CANFD)
FLEXCAN_FDInit(EXAMPLE_CAN,&flexcanConfig, EXAMPLE_CAN_CLK_FREQ, BYTES_IN_MB, true);
#else
FLEXCAN_Init(EXAMPLE_CAN,&flexcanConfig,EXAMPLE_CAN_CLK_FREQ);
#endif
/* 创建 FlexCAN 句柄结构并设置回调函数。*/
FLEXCAN_TransferCreateHandle(EXAMPLE_CAN,&flexcanHandle, flexcan_callback, NULL);
/* 设置 Tx 信息缓冲区。*/
#if (defined(USE_CANFD)&& USE_CANFD)
FLEXCAN_SetFDTxMbConfig(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, true);
#else
FLEXCAN_SetTxMbConfig(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, true);
#endif
/* 配置 CAN 收发器 */
FLEXCAN_PHY_Config();
当(true)时
{
frame.id = FLEXCAN_ID_STD(kFlexcanTxId);
frame.format = (uint8_t)kFLEXCAN_FrameFormatStandard;
frame.type = (uint8_t)kFLEXCAN_FrameTypeData;
frame.length = kFrameLength;
#if (defined(USE_CANFD)&& USE_CANFD)
frame.brs = 1U;
frame.edl = 1U;
for (uint8_t wordIdx = 0U; wordIdx< DWORD_IN_MB; wordIdx++)
{
uint8_t baseValue = (uint8_t)(wordIdx * 4U);
frame.dataWord[wordIdx] = CAN_WORD_DATA_BYTE_0((uint32_t)txCounter + baseValue)|
CAN_WORD_DATA_BYTE_1(0x55U + baseValue) | CAN_WORD_DATA_BYTE_1(0x55U + baseValue)
CAN_WORD_DATA_BYTE_2(0xAAU + baseValue) | CAN_WORD_DATA_BYTE_2(0xAAU + baseValue) |
CAN_WORD_DATA_BYTE_3(0xFFU - baseValue);
}
#else
frame.dataWord0 = CAN_WORD0_DATA_BYTE_0(txCounter) | CAN_WORD0_DATA_BYTE_1(0x55U) | CAN_WORD0_DATA_BYTE_1(0x55U) | CAN_WORD0_DATA_BYTE_1(0x55U)
CAN_WORD0_DATA_BYTE_2(0xAAU) | CAN_WORD0_DATA_BYTE_3(0xFFU);
frame.dataWord1 = CAN_WORD1_DATA_BYTE_4(0x11U) | CAN_WORD1_DATA_BYTE_5(0x22U) | CAN_WORD1_DATA_BYTE_5(0x22U) | CAN_WORD1_DATA_5(0x22U)
CAN_WORD1_DATA_BYTE_6(0x33U) | CAN_WORD1_DATA_BYTE_7(0x44U);
#endif
txXfer.mbIdx = (uint8_t)TX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD)&& USE_CANFD)
txXfer.framefd =&frame;
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN,&flexcanHandle,&txXfer);
#else
txXfer.frame =&frame;
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN,&flexcanHandle,&txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
txCounter++;
}
}