Transmit And Receive

该示例演示了 CAN 外设的收发数据功能。

CAN外接USB CAN FD分析仪,通过PC端收发标准数据帧,扩展数据帧,标准远程帧,扩展远程帧,FD标准数据帧,FD扩展数据帧等帧类型与CAN controller进行通信。

芯片端在CAN中断中接收PC下发的数据,并传输相同数据给PC端,PC端收到芯片回的数据。

环境需求

该示例支持以下开发套件:

开发套件

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

更多信息请参考快速入门

硬件连线

EVB外接TJA1051 CAN Receiver模块,连接P3_2和CTX,P3_4和CRX,连接EVB 3.3V和模块VCC,EVB VCC3.3和连接模块NC,连接EVB GND和模块GND和S。

TJA1051 CAN Receiver模块另一端通过USB CAN FD分析仪连接到PC,连接模块CANH和分析仪CANH,连接模块CANL和分析仪CANL。

CAN收发器介绍

本示例中采用TJA1051模块作为CAN收发器,用户可自行选择所用的CAN收发器。 TJA1051是一款高速CAN收发器,为CAN控制器提供差动发送和接收功能,传输速率高达1Mbit/s。

这里应该是CAN收发器模块的图片

CAN 收发器模块

这里应该是CAN收发器模块连接示意图的图片

CAN 收发器模块连接示意图

编译和下载

该示例的工程路径如下:

Project file: samples\peripheral\can\trx\proj\rtl87x2g\mdk

Project file: samples\peripheral\can\trx\proj\rtl87x2g\gcc

请按照以下步骤操作构建并运行该示例:

  1. 打开工程文件。

  2. 按照 快速入门编译APP Image 给出的步骤构建目标文件。

  3. 编译成功后,在路径 mdk\bingcc\bin 下会生成 app bin app_MP_xxx.bin 文件。

  4. 按照 快速入门MP Tool 给出的步骤将app bin烧录至EVB内。

  5. 按下复位按键,开始运行。

测试验证

  1. IC复位后,CAN FD Tool上会收到各个类型的帧。

  2. 使用CAN FD Tool给IC发送数据帧。

  3. 在Debug Analyzer工具上,打印接收到的帧数据。

这里应该是IC接收的帧数据log

IC接收的帧数据log

  1. IC将收到的数据帧发送回tool,在tool上可以看到发送和接收的数据帧。

代码介绍

该章节分为以下几个部分:

  1. 源码路径

  2. 初始化函数将在 初始化 章节介绍。

  3. 初始化后的功能实现将在 功能实现 章节介绍。

源码路径

  • 工程路径: sdk\samples\peripheral\can\trx\proj

  • 源码路径: sdk\samples\peripheral\can\trx\src

该工程的工程文件代码结构如下:

└── Project: trx
    └── 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_nvic.c
            └── rtl_can.c
        └── APP                      includes the ble_peripheral user application implementation
            ├── main_ns.c
            └── io_can.c

初始化

初始化流程包括了 can_board_initcan_driver_init


can_board_init 包含了对PAD和PINMUX的设置。

  1. 配置PAD:设置引脚、PINMUX模式、PowerOn、无内部上拉。

  2. 配置PINMUX:分配引脚分别为CAN_TX、CAN_RX功能。


can_driver_init 包含了对CAN外设的初始化。

  1. 使能PCC时钟。

  2. 关闭CAN的自动重传模式。

  3. 设置CAN总线同步位时间,将CAN总线速度设置为500kHz。

  4. 使能CAN FD,设置CAN FD可变速率段位同步时间,将CAN FD可变速率段速度设置为5MHz,设置采样补偿SSP为自动计算模式。

  5. 使能CAN,配置CAN中断。

  6. 等待CAN总线打开。

备注

注意:如果程序卡在等待CAN总线打开处,请检查CAN bus是否连接准确。

RCC_PeriphClockCmd(APBPeriph_CAN, APBPeriph_CAN_CLOCK, ENABLE);

init_struct.CAN_AutoReTxEn = DISABLE;
init_struct.CAN_BitTiming.b.can_brp = 3;
...
init_struct.CAN_FdEn = ENABLE;
/* Here config to 5mhz. */
init_struct.CAN_FdBitTiming.b.can_fd_brp = 0;
...
CAN_Init(&init_struct);
CAN_Cmd(ENABLE);
/* CAN interrupts enable */
CAN_INTConfig((CAN_BUS_OFF_INT | CAN_WAKE_UP_INT | CAN_ERROR_INT |
               CAN_RX_INT | CAN_TX_INT), ENABLE);
...
/* polling CAN bus on status */
while (CAN_GetBusState() != CAN_BUS_STATE_ON)
...

功能实现

  1. 执行 can_basic_tx ,依次发送标准数据帧,扩展数据帧,标准远程帧,扩展远程帧,FD标准数据帧,FD扩展数据帧。

    1. 使用设置的发送帧类型将邮箱配置为发送模式。

    2. 使能邮箱发送中断,等待RAM状态空闲。

CANError_TypeDef tx_error;
CANTxFrame_TypeDef tx_frame_type;

tx_frame_type.msg_buf_id = buf_id;
...
switch (frame_type)
...

CAN_MBTxINTConfig(tx_frame_type.msg_buf_id, ENABLE);
tx_error = CAN_SetMsgBufTxMode(&tx_frame_type, tx_data, data_len);

while (CAN_GetRamState() != CAN_RAM_STATE_IDLE)
...

备注

注意:如果使用同一个邮箱号连续发送多个帧,请务必保证前一帧发送完成后再发送下一帧。

  1. 发送完毕后执行 can_basic_rx ,等待PC端发送帧进入接收中断。

    1. 如果使能了FIFO模式则使用邮箱12进行接收。

    2. 屏蔽接收帧rtr,ide,id过滤,即接收所有帧。

    3. 失能Rx DMA,失能自动回复。

    4. 使用设置的接收帧类型将邮箱配置为接收模式。

    5. 使能邮箱接收中断,等待RAM状态闲。

  CANError_TypeDef rx_error;
  CANRxFrame_TypeDef rx_frame_type;
#if CAN_RX_FIFO_EN
  rx_frame_type.msg_buf_id = CAN_MESSAGE_FIFO_START_ID;
#else
  rx_frame_type.msg_buf_id = 0;
#endif

  rx_frame_type.extend_frame_id = 0;
  ...
  rx_error = CAN_SetMsgBufRxMode(&rx_frame_type);

  CAN_MBRxINTConfig(rx_frame_type.msg_buf_id, ENABLE);

  while (CAN_GetRamState() != CAN_RAM_STATE_IDLE)
  ...
  1. 当发送完成或接收完成或出现错误时,进入中断处理函数 CAN_Handler

    1. 依次从产生接收完成中断的邮箱中读取与打印接收到的帧数据。

    2. 执行 can_basic_tx 将接收到的帧类型与帧数据发送回去。

    3. 执行 can_basic_rx 等待下一次中断。

...
CAN_ClearMBnRxDoneFlag(index);
CANError_TypeDef get_error;
CANMsgBufInfo_TypeDef mb_info;
get_error = CAN_GetMsgBufInfo(index, &mb_info);
...
CAN_GetRamData(mb_info.data_length, rx_data);
CANDataFrameSel_TypeDef frame_type = CAN_CheckFrameType(mb_info.rtr_bit, mb_info.ide_bit,
                                                        mb_info.edl_bit);
...
/* Send back frame here. */
can_basic_tx(0, frame_type, mb_info.standard_frame_id, \
              mb_info.extend_frame_id, rx_data, mb_info.data_length);

/* Start rx next time. */
can_basic_rx();
...