【FRDM-MCXN947】CAN0收发测试
<p><span style="font-size:16px;">测试开发板上的CAN0通信,实现数据收发。</span></p><p> </p>
<p><span style="font-size:16px;"><strong>一、硬件部分</strong></span></p>
<p> </p>
<p><span style="font-size:16px;">开发板上的CAN通信部分电路图</span></p>
<p><span style="font-size:16px;"></span></p>
<p> </p>
<p><span style="font-size:16px;"><strong>二、配置端口和时钟</strong></span></p>
<p> </p>
<p><span style="font-size:16px;">2.1、CAN0端口配置</span></p>
<p><span style="font-size:16px;"></span></p>
<p> </p>
<p><span style="font-size:16px;">2.2、配置CAN0时钟</span></p>
<p><span style="font-size:16px;"></span></p>
<p> </p>
<p><span style="font-size:16px;"><strong>三、程序部分</strong></span></p>
<p> </p>
<p><span style="font-size:16px;">3.1、can.c</span></p>
<pre>
<code>#include "main.h"
#if (defined(USE_CANFD) && USE_CANFD)
/*
* DWORD_IN_MB DLC BYTES_IN_MB Maximum MBs
* 2 8 kFLEXCAN_8BperMB 64
* 4 10 kFLEXCAN_16BperMB 42
* 8 13 kFLEXCAN_32BperMB 25
* 16 15 kFLEXCAN_64BperMB 14
*
* Dword in each message buffer, Length of data in bytes, Payload size must align,
* and the Message Buffers are limited corresponding to each payload configuration:
*/
#define DLC (15)
#define BYTES_IN_MB kFLEXCAN_64BperMB
#else
#define DLC (8)
#endif
flexcan_handle_t flexcanHandle;
volatile bool txComplete = false;
volatile bool rxComplete = false;
volatile bool wakenUp = false;
flexcan_mb_transfer_t txXfer, rxXfer;
#if (defined(USE_CANFD) && USE_CANFD)
flexcan_fd_frame_t frame;
#else
flexcan_frame_t frame;
#endif
uint32_t txIdentifier;
uint32_t rxIdentifier;
static void FLEXCAN_PHY_Config(void)
{
#if (defined(USE_PHY_TJA1152) && USE_PHY_TJA1152)
/* Initialize TJA1152. */
/* STB=H, configuration CAN messages are expected from the local host via TXD pin. */
RGPIO_PortSet(EXAMPLE_STB_RGPIO, 1u << EXAMPLE_STB_RGPIO_PIN);
/* Classical CAN messages with standard identifier 0x555 must be transmitted
* by the local host controller until acknowledged by the TJA1152 for
* automatic bit rate detection. Do not set frame.brs = 1U to keep nominal
* bit rate in CANFD frame data phase. */
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;
/* Configuration of spoofing protection. */
/* Add 0x321 and 0x123 to Transmission Whitelist. */
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 = CAN_WORD_DATA_BYTE_0(0x10) | CAN_WORD_DATA_BYTE_1(0x00) | CAN_WORD_DATA_BYTE_2(0x33) |
CAN_WORD_DATA_BYTE_3(0x21);
frame.dataWord = 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_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;
/* Configuration of command message ID. */
/* Reconfiguration is only accepted locally. Keep CONFIG_ID as default value 0x18DA00F1. */
frame.length = 5U;
#if (defined(USE_CANFD) && USE_CANFD)
frame.dataWord = CAN_WORD_DATA_BYTE_0(0x60) | CAN_WORD_DATA_BYTE_1(0x98) | CAN_WORD_DATA_BYTE_2(0xDA) |
CAN_WORD_DATA_BYTE_3(0x00);
frame.dataWord = 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_3(0x00);
frame.dataWord1 = CAN_WORD1_DATA_BYTE_4(0xF1);
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
/* Leaving configuration mode. */
/* Configuration into volatile memory only. */
frame.length = 8U;
#if (defined(USE_CANFD) && USE_CANFD)
frame.dataWord = CAN_WORD_DATA_BYTE_0(0x71) | CAN_WORD_DATA_BYTE_1(0x02) | CAN_WORD_DATA_BYTE_2(0x03) |
CAN_WORD_DATA_BYTE_3(0x04);
frame.dataWord = CAN_WORD_DATA_BYTE_4(0x05) | 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_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_BYTE_7(0x08);
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
LOG_INFO("Initialize TJA1152 successfully!\r\n\r\n");
/* STB=L, TJA1152 switch from secure standby mode to normal mode. */
RGPIO_PortClear(EXAMPLE_STB_RGPIO, 1u << EXAMPLE_STB_RGPIO_PIN);
/* Initialize TJA1152 end. */
#endif
}
/*!
* @brief FlexCAN Call Back function
*/
static FLEXCAN_CALLBACK(flexcan_callback)
{
switch (status)
{
case kStatus_FLEXCAN_RxIdle:
if (RX_MESSAGE_BUFFER_NUM == result)
{
rxComplete = true;
}
break;
case kStatus_FLEXCAN_TxIdle:
if (TX_MESSAGE_BUFFER_NUM == result)
{
txComplete = true;
}
break;
case kStatus_FLEXCAN_WakeUp:
wakenUp = true;
break;
default:
break;
}
}
uint8_t can_rx_hdl(uint8_t *rxbuf)
{
uint8_t can_tx_buf;
/* Start receive data through Rx Message Buffer. */
rxXfer.mbIdx = (uint8_t)RX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
rxXfer.framefd = &frame;
(void)FLEXCAN_TransferFDReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#else
rxXfer.frame = &frame;
(void)FLEXCAN_TransferReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#endif
if(rxComplete==true)
{
rxComplete=false;
LOG_INFO(" Rx MB ID: 0x%3x, Rx MB data: %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x \r\n", frame.id >> CAN_ID_STD_SHIFT,frame.dataByte0,frame.dataByte1,frame.dataByte2,frame.dataByte3,
frame.dataByte4,frame.dataByte5,frame.dataByte6,frame.dataByte7);
rxbuf = frame.dataByte0;
rxbuf = frame.dataByte1;
rxbuf = frame.dataByte2;
rxbuf = frame.dataByte3;
rxbuf = frame.dataByte4;
rxbuf = frame.dataByte5;
rxbuf = frame.dataByte6;
rxbuf = frame.dataByte7;
return 1;
}
return 0;
}
void can_std_tx(uint32_t id, uint8_t *txbuf)
{
frame.id = FLEXCAN_ID_STD(id);
frame.format = (uint8_t)kFLEXCAN_FrameFormatStandard;
frame.type = (uint8_t)kFLEXCAN_FrameTypeData;
frame.length = (uint8_t)DLC;
#if (defined(USE_CANFD) && USE_CANFD)
frame.brs = 1U;
frame.edl = 1U;
#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;
frame.dataByte0 = txbuf;
frame.dataByte1 = txbuf;
frame.dataByte2 = txbuf;
frame.dataByte3 = txbuf;
frame.dataByte4 = txbuf;
frame.dataByte5 = txbuf;
frame.dataByte6 = txbuf;
frame.dataByte7 = txbuf;
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
}
void init_can(void)
{
flexcan_config_t flexcanConfig;
flexcan_rx_mb_config_t mbConfig;
uint8_t node_type;
rxIdentifier = 0x506;
FLEXCAN_GetDefaultConfig(&flexcanConfig);
flexcanConfig.bitRate = 500000U;
#if defined(EXAMPLE_CAN_CLK_SOURCE)
flexcanConfig.clkSrc = EXAMPLE_CAN_CLK_SOURCE;
#endif
#if defined(EXAMPLE_CAN_BIT_RATE)
flexcanConfig.bitRate = EXAMPLE_CAN_BIT_RATE;
#endif
/* If special quantum setting is needed, set the timing parameters. */
#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)
if (FLEXCAN_FDCalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.bitRate, flexcanConfig.bitRateFD,
EXAMPLE_CAN_CLK_FREQ, &timing_config))
{
/* Update the improved timing configuration*/
memcpy(&(flexcanConfig.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
}
else
{
LOG_INFO("No found Improved Timing Configuration. Just used default configuration\r\n\r\n");
}
#else
if (FLEXCAN_CalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.bitRate, EXAMPLE_CAN_CLK_FREQ, &timing_config))
{
/* Update the improved timing configuration*/
memcpy(&(flexcanConfig.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
}
else
{
LOG_INFO("No found Improved Timing Configuration. Just used default 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
/* Create FlexCAN handle structure and set call back function. */
FLEXCAN_TransferCreateHandle(EXAMPLE_CAN, &flexcanHandle, flexcan_callback, NULL);
/* Set Rx Masking mechanism. */
FLEXCAN_SetRxMbGlobalMask(EXAMPLE_CAN, FLEXCAN_RX_MB_STD_MASK(rxIdentifier, 0, 0));
/* Setup Rx Message Buffer. */
mbConfig.format = kFLEXCAN_FrameFormatStandard;
mbConfig.type = kFLEXCAN_FrameTypeData;
mbConfig.id = FLEXCAN_ID_STD(rxIdentifier);
#if (defined(USE_CANFD) && USE_CANFD)
FLEXCAN_SetFDRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);
#else
FLEXCAN_SetRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);
#endif
/* Setup Tx Message Buffer. */
#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
/* Configure CAN transceiver */
FLEXCAN_PHY_Config();
}</code></pre>
<p> </p>
<p><span style="font-size:16px;">3.2、can.h</span></p>
<pre>
<code>#ifndef __CAN_H
#define __CAN_H
#define USE_CANFD (0)
#define EXAMPLE_CAN CAN0
#define RX_MESSAGE_BUFFER_NUM (0)
#define TX_MESSAGE_BUFFER_NUM (1)
#define EXAMPLE_CAN_CLK_FREQ CLOCK_GetFlexcanClkFreq(0U)
#define USE_IMPROVED_TIMING_CONFIG (1)
#define LOG_INFO (void)PRINTF
void init_can(void);
void can_std_tx(uint32_t id, uint8_t *txbuf);
uint8_t can_rx_hdl(uint8_t *rxbuf);
#endif
</code></pre>
<p> </p>
<p><span style="font-size:16px;">3.3、main.c</span></p>
<pre>
<code>#include "main.h"
int main(void)
{
uint8_t can_tx_buf;
uint8_t can_rx_buf;
uint8_t i;
CLOCK_EnableClock(kCLOCK_Gpio0);
BOARD_InitDEBUG_UARTPins();
BOARD_PowerMode_OD();
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
SysTick_Init();
init_led();
init_can();
while (1)
{
if(can_rx_hdl(can_rx_buf))
{
can_std_tx((uint32_t)0x510,can_rx_buf);
}
}
}
</code></pre>
<p> </p>
<p><span style="font-size:16px;"><strong>四、运行结果</strong></span></p>
<p> </p>
<p><span style="font-size:16px;">4.1、CAN0收发数据</span></p>
<p><span style="font-size:16px;"></span></p>
<p> </p>
<p><span style="font-size:16px;">4.2、串口打印接收的数据</span></p>
<p><span style="font-size:16px;"></span></p>
<p> </p>
<p><span style="font-size:16px;"><strong>五、附件</strong></span></p>
<p> </p>
<div><span style="font-size:16px;">测试源代码:</span></div>
<p> </p>
<p> </p>
<p> </p>
<p>测试任务过程说的很规范详细,很赞</p>
页:
[1]