LoopBack
该示例使用使用 CAN 的回环测试模式发送和接收帧数据。 使用CAN发送邮箱分别发送标准数据帧、扩展数据帧、标准远程帧、扩展远程帧、FD标准数据帧、FD扩展数据帧类型。 在Debug Analyzer工具上打印CAN邮箱接收到的帧数据。
环境需求
该示例支持以下开发套件:
Hardware Platforms |
Board Name |
---|---|
RTL87x2G HDK |
RTL87x2G EVB |
更多信息请参考快速入门。
硬件连线
EVB上,连接P3_2和P3_4。
编译和下载
该示例的工程路径如下:
Project file: samples\peripheral\can\loopback\proj\rtl87x2g\mdk
Project file: samples\peripheral\can\loopback\proj\rtl87x2g\gcc
请按照以下步骤操作构建并运行该示例:
打开工程文件。
按照 快速入门 中 编译APP Image 给出的步骤构建目标文件。
编译成功后,在路径
mdk\bin
或gcc\bin
下会生成 app binapp_MP_xxx.bin
文件。按下复位按键,开始运行。
测试验证
执行CAN初始化,初始化前后分别读取总线状态。
[CAN] BUS state: 0, waiting... [CAN] BUS ON 1
发送邮箱分别发送标准数据帧、扩展数据帧、标准远程帧、扩展远程帧、FD标准数据帧、FD扩展数据帧,接收邮箱收到数据后打印数据帧信息log。
[CAN] rx frame_type x [CAN] rx frame_id = xxx , ext_frame_id = xxx [CAN] rx_data [0] xxx ... [CAN] BUS RX done ...

CAN log
代码介绍
该章节分为以下几个部分:
源码路径
工程路径:
sdk\samples\peripheral\can\loopback\proj
源码路径:
sdk\samples\peripheral\can\loopback\src
该工程的工程文件代码结构如下:
└── Project: loopback
└── secure_only_app
└── Device includes startup code
├── startup_rtl.c
└── system_rtl.c
├── CMSIS includes CMSIS header files
├── CMSE Library Non-secure callable lib
├── Lib includes all binary symbol files that user application is built on
└── rtl87x2g_io.lib
├── Peripheral includes all peripheral drivers and module code used by the application
├── rtl_rcc.c
├── rtl_pinmux.c
└── rtl_can.c
└── APP includes the ble_peripheral user application implementation
├── main_ns.c
└── io_can.c
初始化
初始化流程包括了 can_driver_init
。
can_driver_init
包含了对CAN外设的初始化。
使能PCC时钟源。
关闭CAN的自动重传模式。
设置CAN总线同步位时间,将CAN总线速度设置为500kHz。
使能CAN FD,设置CAN FD可变速率段位同步时间,将CAN FD可变速率段速度设置为5MHz,设置采样补偿SSP为自动计算模式。
设置CAN为回环测试模式。
使能CAN,等待CAN总线打开。
备注
注意:如果程序卡在等待CAN总线打开处,请检查CAN bus是否连接准确。
RCC_PeriphClockCmd(APBPeriph_CAN, APBPeriph_CAN_CLOCK, ENABLE);
...
init_struct.CAN_AutoReTxEn = DISABLE;
/* can speed = 40mhz / ((brp + 1)*(1 + tseg1 + 1 + tseg2 + 1)) */
/* Here config to 500khz. */
init_struct.CAN_BitTiming.b.can_brp = 3;
...
init_struct.CAN_FdEn = ENABLE;
init_struct.CAN_FdBitTiming.b.can_fd_brp = 0;
...
init_struct.CAN_TestModeSel = CAN_TEST_MODE_LOOP_BACK;
...
CAN_Cmd(ENABLE);
while (CAN_GetBusState() != CAN_BUS_STATE_ON)
...
功能实现
依次以回环方式发送标准数据帧,扩展数据帧,标准远程帧,扩展远程帧,FD标准数据帧,FD扩展数据帧。
备注
注意:如果使用同一个邮箱号连续发送多个帧,请务必保证前一帧发送完成后再发送下一帧。
执行loopback函数,以回环方式发送和接收指定类型的帧。
设置接收邮箱的接收帧类型。使用邮箱15进行接收,屏蔽接收帧rtr,ide,id过滤,即接收所有帧,失能Rx DMA,失能自动回复,使用设置的接收帧类型将邮箱配置为接收模式,等待RAM状态空闲。
设置发送邮箱的发送帧类型。使用传入参数邮箱id,帧类型,标准帧id,扩展帧id,设置帧,失能自动回复,使用设置的发送帧类型将邮箱配置为发送模式,等待RAM状态空闲。
等待发送与接收完成。
读取接收邮箱信息,通过接收邮箱信息读取RAM中接收到的帧数据并打印。
CANError_TypeDef rx_error;
CANRxFrame_TypeDef rx_frame_type;
rx_frame_type.msg_buf_id = 15;
/* Set 0 to filter related bit, and set 1 to mask related filter. */
rx_frame_type.frame_rtr_mask = SET;
rx_frame_type.frame_ide_mask = SET;
rx_frame_type.frame_id_mask = CAN_FRAME_ID_MASK_MAX_VALUE;
rx_frame_type.rx_dma_en = RESET;
rx_frame_type.auto_reply_bit = RESET;
rx_error = CAN_SetMsgBufRxMode(&rx_frame_type);
while (CAN_GetRamState() != CAN_RAM_STATE_IDLE)
...
/* Set tx message buffer. */
CANError_TypeDef tx_error = CAN_NO_ERR;
CANTxFrame_TypeDef tx_frame_type;
tx_frame_type.msg_buf_id = buf_id;
tx_frame_type.frame_type = frame_type;
tx_frame_type.standard_frame_id = frame_id;
tx_frame_type.extend_frame_id = 0;
tx_frame_type.frame_brs_bit = CAN_BRS_NO_SWITCH_BIT_TIMING;
tx_frame_type.auto_reply_bit = DISABLE;
tx_error = CAN_SetMsgBufTxMode(&tx_frame_type, tx_data, data_len);
while (CAN_GetRamState() != CAN_RAM_STATE_IDLE)
...
/* Polling tx done. */
while (SET != CAN_GetMBnTxDoneFlag(tx_frame_type.msg_buf_id))
...
/* Polling rx done. */
while (SET != CAN_GetMBnRxDoneFlag(rx_frame_type.msg_buf_id))
...
/* Receive rx data. */
...
get_error = CAN_GetMsgBufInfo(rx_frame_type.msg_buf_id, &mb_info);
...
CAN_GetRamData(mb_info.data_length, rx_data);
CANDataFrameSel_TypeDef get_frame_type = CAN_CheckFrameType(mb_info.rtr_bit, mb_info.ide_bit, mb_info.edl_bit);
...