TL-LED 发表于 2025-1-8 12:19

【FRDM-MCXN947】CAN0收发测试

<p><span style="font-size:16px;">测试开发板上的CAN0通信,实现数据收发。</span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><strong>一、硬件部分</strong></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">开发板上的CAN通信部分电路图</span></p>

<p><span style="font-size:16px;"></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><strong>二、配置端口和时钟</strong></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">2.1、CAN0端口配置</span></p>

<p><span style="font-size:16px;"></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">2.2、配置CAN0时钟</span></p>

<p><span style="font-size:16px;"></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><strong>三、程序部分</strong></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">3.1、can.c</span></p>

<pre>
<code>#include "main.h"


#if (defined(USE_CANFD) &amp;&amp; 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) &amp;&amp; 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) &amp;&amp; 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 &lt;&lt; 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) &amp;&amp; USE_CANFD)
    txXfer.framefd = &amp;frame;
    (void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &amp;flexcanHandle, &amp;txXfer);
#else
    txXfer.frame = &amp;frame;
    (void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &amp;flexcanHandle, &amp;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) &amp;&amp; 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, &amp;flexcanHandle, &amp;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, &amp;flexcanHandle, &amp;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) &amp;&amp; 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, &amp;flexcanHandle, &amp;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, &amp;flexcanHandle, &amp;txXfer);
#endif
    while (!txComplete)
    {
    };
    txComplete = false;

    /* Leaving configuration mode. */
    /* Configuration into volatile memory only. */
    frame.length = 8U;

#if (defined(USE_CANFD) &amp;&amp; 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, &amp;flexcanHandle, &amp;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, &amp;flexcanHandle, &amp;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 &lt;&lt; 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) &amp;&amp; USE_CANFD)
                rxXfer.framefd = &amp;frame;
                (void)FLEXCAN_TransferFDReceiveNonBlocking(EXAMPLE_CAN, &amp;flexcanHandle, &amp;rxXfer);
#else
                rxXfer.frame = &amp;frame;
                (void)FLEXCAN_TransferReceiveNonBlocking(EXAMPLE_CAN, &amp;flexcanHandle, &amp;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 &gt;&gt; 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) &amp;&amp; USE_CANFD)
                frame.brs = 1U;
                frame.edl = 1U;
#endif
                txXfer.mbIdx = (uint8_t)TX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) &amp;&amp; USE_CANFD)
                txXfer.framefd = &amp;frame;
                (void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &amp;flexcanHandle, &amp;txXfer);
#else
                txXfer.frame = &amp;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, &amp;flexcanHandle, &amp;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(&amp;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) &amp;&amp; SET_CAN_QUANTUM)
    flexcanConfig.timingConfig.phaseSeg1 = PSEG1;
    flexcanConfig.timingConfig.phaseSeg2 = PSEG2;
    flexcanConfig.timingConfig.propSeg   = PROPSEG;
#if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) &amp;&amp; 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) &amp;&amp; USE_IMPROVED_TIMING_CONFIG)
    flexcan_timing_config_t timing_config;
    memset(&amp;timing_config, 0, sizeof(flexcan_timing_config_t));
#if (defined(USE_CANFD) &amp;&amp; USE_CANFD)
    if (FLEXCAN_FDCalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.bitRate, flexcanConfig.bitRateFD,
                                                EXAMPLE_CAN_CLK_FREQ, &amp;timing_config))
    {
      /* Update the improved timing configuration*/
      memcpy(&amp;(flexcanConfig.timingConfig), &amp;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, &amp;timing_config))
    {
      /* Update the improved timing configuration*/
      memcpy(&amp;(flexcanConfig.timingConfig), &amp;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) &amp;&amp; USE_CANFD)
    FLEXCAN_FDInit(EXAMPLE_CAN, &amp;flexcanConfig, EXAMPLE_CAN_CLK_FREQ, BYTES_IN_MB, true);
#else
    FLEXCAN_Init(EXAMPLE_CAN, &amp;flexcanConfig, EXAMPLE_CAN_CLK_FREQ);
#endif

    /* Create FlexCAN handle structure and set call back function. */
    FLEXCAN_TransferCreateHandle(EXAMPLE_CAN, &amp;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) &amp;&amp; USE_CANFD)
    FLEXCAN_SetFDRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &amp;mbConfig, true);
#else
    FLEXCAN_SetRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &amp;mbConfig, true);
#endif

/* Setup Tx Message Buffer. */
#if (defined(USE_CANFD) &amp;&amp; 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>&nbsp;</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>&nbsp;</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>&nbsp;</p>

<p><span style="font-size:16px;"><strong>四、运行结果</strong></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">4.1、CAN0收发数据</span></p>

<p><span style="font-size:16px;"></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">4.2、串口打印接收的数据</span></p>

<p><span style="font-size:16px;"></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><strong>五、附件</strong></span></p>

<p>&nbsp;</p>

<div><span style="font-size:16px;">测试源代码:</span></div>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

Jacktang 发表于 2025-1-9 07:49

<p>测试任务过程说的很规范详细,很赞</p>
页: [1]
查看完整版本: 【FRDM-MCXN947】CAN0收发测试