前景提要
CANFD基础知识可参考前篇:
Jetson Xavier/XavierNX/TX2 CANFD 配置使用
STM32 CANFD 基础知识
本篇用起来, 连接关系如下:
CAN收发器均选用支持2M及以上CANFD的收发器, LPUART到PC用STLINK连接.
STM32工程搭建
STM32CubeMX配置步骤如下:
MCU选择: 打开 STM32CubeMX, 点击 ACCESS TO MCU SELECTOR, 选择 STM32G474VETx
调试端口配置为SWD: Pinout & Configuration -> System Core -> SYS -> Debug 选择 Serial Wire
Pinout & Configuration -> System Core -> RCC -> HSE 选择 Crystal/Ceramic Resonator
Clock Configuration(我板子上用的外部12M晶振, 主频配置成160MHz, FDCAN的时钟来自PCLK1=160MHz):
开启100us定时器中断: Pinout & Configuration -> Timers -> TIM6 -> 勾选Activated, Prescaler设置为160-1, Counter Period设置为100-1 -> 勾选TIM6中断:
LPUART1配置: Pinout & Configuration -> Connectivity -> LPUART1 -> Mode选择异步Asynchronous, 关闭 Overrun 和 DMA on RX Error, 波特率配置为2M-8-N-1:
FDCAN1配置: Pinout & Configuration -> Connectivity -> FDCAN1, Mode选择FD, Frame Format设置FD mode with BirRate Switshing启用位速率变换, Auto Retransmission设置为Enable开启自动重传, Trasmit Pause设置为Enable开启传输暂停, 速率和采样点设置参考上一篇 STM32 CANFD 基础知识的位时间和采样点小节, Nominal仲裁段设置500Kbit/s(160M/NPre/(1+NTSeg1+NTSeg2) = 160M/4/(1+63+16) = 500Kbit/s), 采样点0.8((1+NTSeg1)/(1+NTSeg1+NTSeg2)=64/80=0.8); Data数据段设置为2Mbit/s((160M/DPre/(1+DTSeg1+DTSeg2) = 160M/4/(1+63+16) = 500Kbit/s)), 采样点0.75((1+DTSeg1)/(1+DTSeg1+DTSeg2)=15/20=0.75), Std Filter Nbr标准帧过滤器数量直接设为最大28, Ext Filters Nbr扩展帧滤波器数量直接设为最大8(虽然后面并没有全用上), 勾选FDCAN1 interrupt 0中断, 引脚也从默认调整到板子上用的引脚PD0/PD1:
FDCAN2, FDCAN3的设置同FDCAN1, 注意引脚要从默认改为板子上用的, 最终引脚位置为:
Project Manager -> Project -> Browse 选择工程位置(Project Location), 填入工程名(Project Name), Toolchain/IDE 选择 MDK-ARM, 把Minimum Heap Size改为0x1000, Minimum Stack Size改为0x1000. 或者更大一点.
Project Manager -> Code Generator -> 勾选Copy only the necessary library files, 还有Generate peripheral initialization as a pair of .c/.h files per periphral
点击右上角 GENERATE CODE 按钮生成代码, 点击Open Project按钮打开工程.
Keil配置, Keil 点击魔术棒或者Project -> Options for Target ..., 默认配置Debug为ST-link Debugger, 点击Setting:
Flash Download选项卡 -> 勾选Reset and Run, 这样下载后可以自动复位运行.
Pack选项卡, 去掉默认的Enable勾选
到此配置结束. 下面是手动添加的代码详解
串口配置
为 LPUART1 添加printf支持:
- #include <stdio.h>
- #ifdef __GNUC__
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
- #else
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
- #endif /* __GNUC__ */
- PUTCHAR_PROTOTYPE
- {
- HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);
- return ch;
- }
复制代码
100us定时器
因为用最大64字节测试的, 实测只发送的情况下, 1s传输最多2490+约2500帧, 再多就丢帧了, 也就是400us/帧, 保守一点, 这里设置500us传一帧, 如果没传出去, 100us后有一次重传的机会, 这就是100us定时器的由来.
- /* USER CODE BEGIN 2 */
- HAL_TIM_Base_Start_IT(&htim6); //Starts the TIM Base generation in interrupt mode.
- /* USER CODE END 2 */
- uint8_t tim6_flag = 0;
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
- {
- if(htim->Instance == TIM6) {
- tim6_flag = 1;
- }
- }
复制代码
FDCAN配置
主要是标准帧滤波器, 扩展帧滤波器设置, 开启新消息接收中断, 开启Bus-Off中断, 设置发送传输延时补偿等.
- FDCAN_FilterTypeDef sFilterConfig1;
- void fdcan1_config(void)
- {
- sFilterConfig1.IdType = FDCAN_STANDARD_ID;
- sFilterConfig1.FilterIndex = 0;
- sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;
- sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
- sFilterConfig1.FilterID1 = 0x00;
- sFilterConfig1.FilterID2 = 0x7FF;
- if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)
- {
- Error_Handler();
- }
- sFilterConfig1.IdType = FDCAN_EXTENDED_ID;
- sFilterConfig1.FilterIndex = 0;
- sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;
- sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
- sFilterConfig1.FilterID1 = 0x00;
- sFilterConfig1.FilterID2 = 0x1FFFFFFF;
- if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)
- {
- Error_Handler();
- }
- /* Configure global filter on both FDCAN instances:
- Filter all remote frames with STD and EXT ID
- Reject non matching frames with STD ID and EXT ID */
- if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
- {
- Error_Handler();
- }
- /* Activate Rx FIFO 0 new message notification on both FDCAN instances */
- if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_BUS_OFF, 0) != HAL_OK)
- {
- Error_Handler();
- }
- /* Configure and enable Tx Delay Compensation, required for BRS mode.
- TdcOffset default recommended value: DataTimeSeg1 * DataPrescaler
- TdcFilter default recommended value: 0 */
- HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1, hfdcan1.Init.DataPrescaler * hfdcan1.Init.DataTimeSeg1, 0);
- HAL_FDCAN_EnableTxDelayCompensation(&hfdcan1);
- HAL_FDCAN_Start(&hfdcan1);
- }
复制代码
这里设置了用一个标准帧滤波器设置了标准帧的全接收, 也可以用掩码的方式设置全接收:
- sFilterConfig1.FilterType = FDCAN_FILTER_MASK;
- sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
- sFilterConfig1.FilterID1 = 0;
- sFilterConfig1.FilterID2 = 0;
复制代码 用一个扩展帧滤波器设置了扩展帧的全接收, 消息扔到RXFIFO0中, 设置了RXFIFO0的新消息来的中断, 也可以扔到RXFIFO1中.
有别于STM32H7, STM32G474在STM32CubeMX软件中能设置的最大标准帧滤波器是28个, 扩展帧滤波器是8个, 这里程序中只各用了一个(index = 0), 如果想用更多, 不知可否手动更改stm32g4xx_hal_fdcan.c中213行这个值, 如把扩展帧滤波器数量从8改为28, 有兴趣试试:
- #define SRAMCAN_FLE_NBR ( 8U) /* Max. Filter List Extended Number */
复制代码
FDCAN2, FDCAN3的配置和FDCAN1类似.
Bus-Off处理
如果CANH, CANL短接, 或者和其它节点的传输速率/采样点不一致, 会引发Bus-Off, 上面开启了Bus-Off中断, 发生Bus-Off时, 直接在中断中初始化FDCAN外设:
- void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs)
- {
- //__HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_BUS_OFF);
- if(hfdcan->Instance == FDCAN1) {
- MX_FDCAN1_Init();
- fdcan1_config();
- } else if(hfdcan->Instance == FDCAN2) {
- MX_FDCAN2_Init();
- fdcan2_config();
- } else if(hfdcan->Instance == FDCAN3) {
- MX_FDCAN3_Init();
- fdcan3_config();
- } else {
- }
- }
复制代码
新消息接收处理
直接把接收的消息通过2M波特率的串口打印出来.
- FDCAN_RxHeaderTypeDef RxHeader1;
- FDCAN_RxHeaderTypeDef RxHeader2;
- FDCAN_RxHeaderTypeDef RxHeader3;
- //RxHeader1.DataLength => can_dlc
- //0x00000 => 0
- //0x10000 => 1
- //0x20000 => 2
- //0x30000 => 3
- //0x40000 => 4
- //0x50000 => 5
- //0x60000 => 6
- //0x70000 => 7
- //0x80000 => 8
- //0x90000 => 12
- //0xA0000 => 16
- //0xB0000 => 20
- //0xC0000 => 24
- //0xD0000 => 32
- //0xE0000 => 48
- //0xF0000 => 64
- uint8_t dlc2len[]={0,1,2,3,4,5,6,7,8,12,16,20,24,32,48,64};
- uint8_t can_dlc2len(uint32_t RxHeader_DataLength)
- {
- return dlc2len[RxHeader_DataLength>>16];
- }
- uint8_t cnt = 0;
- uint8_t brs[] = {'-', 'B'};
- uint8_t esi[] = {'-', 'E'};
- void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
- {
- if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != 0) {
- //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);
- //RxHeader2.Identifier++;
- //fdcan2_transmit(RxHeader2.Identifier, RxData2);
- //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
- //memset(&RxHeader1, 0, sizeof(FDCAN_RxHeaderTypeDef));
- HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
- if (hfdcan->Instance == FDCAN1) {
- printf("fdcan1, ");
- } else if (hfdcan->Instance == FDCAN2) {
- printf("fdcan2, ");
- } else if (hfdcan->Instance == FDCAN3) {
- printf("fdcan3, ");
- }
- printf("0x%8X, %02d, %c, %c:",RxHeader1.Identifier,
- can_dlc2len(RxHeader1.DataLength),
- brs[RxHeader1.BitRateSwitch>>20 & 0x1],
- esi[RxHeader1.ErrorStateIndicator>>31 & 0x1]);
- for(cnt = 0; cnt < can_dlc2len(RxHeader1.DataLength); cnt++) {
- printf(" %02X", RxData1[cnt]);
- }
- printf("\n\r");
- //if (hfdcan->Instance == FDCAN1) {
- // HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
- // //echo
- // RxHeader1.Identifier++;
- // fdcan1_transmit(RxHeader1.Identifier, RxHeader1.DataLength, RxData1);
- //} else if(hfdcan->Instance == FDCAN2) {
- // HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);
- // //echo
- // RxHeader2.Identifier++;
- // fdcan2_transmit(RxHeader2.Identifier, RxHeader2.DataLength, RxData2);
- //} else if(hfdcan->Instance == FDCAN3) {
- // HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader3, RxData3);
- // //echo
- // RxHeader3.Identifier++;
- // fdcan3_transmit(RxHeader3.Identifier, RxHeader3.DataLength, RxData3);
- //} else {
- //
- //}
- }
- }
复制代码
注意注释中 RxHeader.DataLength => can_dlc 的对应关系.
示例如图:
图中消息来自fdcan2, can_id为0x18FF0005, 64字节数据, 开启了BRS和ESI, :后面是64字节的十六进制数据.
printf还是比较耗时间的, 这里仅做低负载下的演示, 实际使用不建议中断中这么搞.
发送处理
发送开启了BRS和ESI, 如果发送失败, 就延时100us后重发一次.
- #include <string.h>
- FDCAN_TxHeaderTypeDef TxHeader1;
- FDCAN_TxHeaderTypeDef TxHeader2;
- FDCAN_TxHeaderTypeDef TxHeader3;
- typedef struct {
- uint8_t flag;
- FDCAN_TxHeaderTypeDef TxHeader;
- uint8_t TxData[64];
- } FDCAN_SendFailTypeDef;
- FDCAN_SendFailTypeDef fdcan1_send_fail = {0};
- FDCAN_SendFailTypeDef fdcan2_send_fail = {0};
- FDCAN_SendFailTypeDef fdcan3_send_fail = {0};
- void fdcan1_transmit(uint32_t can_id, uint32_t DataLength, uint8_t tx_data[])
- {
- TxHeader1.Identifier = can_id;
- TxHeader1.IdType = FDCAN_EXTENDED_ID;
- if(can_id < 0x800) { //exactly not right
- TxHeader1.IdType = FDCAN_STANDARD_ID;
- }
- TxHeader1.TxFrameType = FDCAN_DATA_FRAME;
- TxHeader1.DataLength = DataLength;
- TxHeader1.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
- TxHeader1.BitRateSwitch = FDCAN_BRS_ON;
- TxHeader1.FDFormat = FDCAN_FD_CAN;
- TxHeader1.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
- TxHeader1.MessageMarker = 0; //marker++; //Tx Event FIFO Use
- if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader1, tx_data) != HAL_OK) {
- fdcan1_send_fail.flag = 1;
- memcpy(&fdcan1_send_fail.TxHeader, &TxHeader1, sizeof(FDCAN_TxHeaderTypeDef));
- memcpy(fdcan1_send_fail.TxData, tx_data, can_dlc2len(DataLength));
- }
- }
- int main(void)
- {
- ...
- /* USER CODE BEGIN 2 */
- fdcan1_config();
- fdcan2_config();
- fdcan3_config();
- for(uint8_t i = 0; i < 64; i++) {
- TxData1<i> = i;
- </i>TxData2 = i;
- TxData3 = i;
- }
- HAL_TIM_Base_Start_IT(&htim6);
- uint32_t count = 0;
- uint32_t cnt_100us = 0;
- uint32_t cnt_500us = 0;
- /* USER CODE END 2 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- if(tim6_flag && count < 1000) {
- tim6_flag = 0;
- TxData1[0] = count >> 8 & 0xFF;
- TxData1[1] = count & 0xFF;
- ++cnt_100us;
- cnt_500us = cnt_100us / 5;
- if(cnt_500us && (cnt_100us%5==0) ) {
- switch(cnt_500us) {
- case 1: fdcan1_transmit(0x123, FDCAN_DLC_BYTES_64, TxData1);
- fdcan1_transmit(0x124, FDCAN_DLC_BYTES_64, TxData1);
- fdcan1_transmit(0x125, FDCAN_DLC_BYTES_64, TxData1); break;
- case 4: fdcan1_transmit(0x12345678, FDCAN_DLC_BYTES_64, TxData1); break;
- case 5: fdcan1_transmit(0x12345679, FDCAN_DLC_BYTES_64, TxData1); break;
- case 6: fdcan1_transmit(0x1234567A, FDCAN_DLC_BYTES_64, TxData1); break;
- case 7: /* next send */ break;
- case 8: break;
- case 20: ++count; cnt_100us = 0; break; //10ms
- }
- } else { //fail retransmission once
- if(fdcan1_send_fail.flag) {
- fdcan1_transmit(fdcan1_send_fail.TxHeader.Identifier,
- fdcan1_send_fail.TxHeader.DataLength,
- fdcan1_send_fail.TxData);
- fdcan1_send_fail.flag = 0;
- }
- if(fdcan2_send_fail.flag) {
- fdcan2_transmit(fdcan2_send_fail.TxHeader.Identifier,
- fdcan2_send_fail.TxHeader.DataLength,
- fdcan2_send_fail.TxData);
- fdcan2_send_fail.flag = 0;
- }
- if(fdcan3_send_fail.flag) {
- fdcan3_transmit(fdcan3_send_fail.TxHeader.Identifier,
- fdcan3_send_fail.TxHeader.DataLength,
- fdcan3_send_fail.TxData);
- fdcan3_send_fail.flag = 0;
- }
- }
- }
- }
- /* USER CODE END 3 */
- }
复制代码
fdcan2, fdcan3和fdcan1的发送类似, 3个发送函数可以合并成一个, 这里没有合并.
发送函数中的DataLength指的是类似FDCAN_DLC_BYTES_64这种的宏定义, 而不是数字64.
这里用can_id < 0x800只是为了简便, 其实不正确, 这种情况下也有可能是扩展帧, 但通常不会这么用.
因为发送最多可以缓存3帧, 所以可以一口气发送3帧, 如case 1处, 也可以一帧一帧发送, 如case 4, case 5, case 6. 这里是1.5ms/3帧或者500us/帧.
因为总线中还有其他节点发送之类的, 有可能发送失败, 这里留了一次发送失败后延时100us重传的机会, 具体情况根据现场可另行调整.
如果fdcan1, fdcan2, fdcan3没有在一个网络中, 可以一口气 fdcan1发送3帧 + fdcan2发送3帧 + fdcan3发送3帧.
一般车辆总线中发送都是最快10ms内把要发的不同ID的数据一股脑发出去(当然也有20ms, 50ms, 100ms周期的数据这里暂不考虑), 所以这里100us中断计数100次就是10ms.
程序中发送1000*6=6000帧后停止发送, 10ms发6帧, 所以10s后数据就发完了.
使用Xavier配合测试一下
把STM32的FDCAN1连到Xavier的CAN1上, Xavier CAN1设置:
- #!/bin/sh
- sudo modprobe can
- sudo modprobe can_raw
- sudo modprobe mttcan
- sudo ip link set down can0
- sudo ip link set can0 type can bitrate 500000 sample-point 0.8 dbitrate 2000000 dsample-point 0.75 fd on restart-ms 100
- sudo ip link set up can0
- sudo ifconfig can0 txqueuelen 1000
- sudo ip link set down can1
- sudo ip link set can1 type can bitrate 500000 sample-point 0.8 dbitrate 2000000 dsample-point 0.75 fd on restart-ms 100
- sudo ip link set up can1
- sudo ifconfig can1 txqueuelen 1000
复制代码
Xavier也是仲裁段500Kbit/s, 采样点0.8, 数据段2Mbit/s, 采样点0.75.
restart-ms 100设置总线Bus-Off时, 100ms后重启.
设置完后查看设置状态 ip -details -statistics link show can1:
- $ ip -details -statistics link show can1
- 6: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 72 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000
- link/can promiscuity 0
- can <FD> state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 100
- bitrate 498701 sample-point 0.792
- tq 26 prop-seg 30 phase-seg1 30 phase-seg2 16 sjw 1
- mttcan: tseg1 2..255 tseg2 0..127 sjw 1..127 brp 1..511 brp-inc 1
- dbitrate 2021052 dsample-point 0.736
- dtq 26 dprop-seg 6 dphase-seg1 7 dphase-seg2 5 dsjw 1
- mttcan: dtseg1 1..31 dtseg2 0..15 dsjw 1..15 dbrp 1..15 dbrp-inc 1
- clock 38400000
- re-started bus-errors arbit-lost error-warn error-pass bus-off
- 0 0 0 13 20 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
- RX: bytes packets errors dropped overrun mcast
- 64578440 1013451 0 0 0 0
- TX: bytes packets errors dropped carrier collsns
- 952448 15914 0 0 0 0
复制代码
位速率和采样点的些许误差测试并无影响.
使用 candump -ta -x can1 >24.dat, 这里-ta显示绝对时间, 然后下载STM32程序运行, 上面的6000帧数据全部存到24.dat文件中了, 共计6000行, 这里截取首尾部分显示:
- (1613988959.105805) can1 RX B - 123 [64] 00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988959.106191) can1 RX B - 124 [64] 00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988959.106609) can1 RX B - 125 [64] 00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988959.107337) can1 RX B - 12345678 [64] 00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988959.107865) can1 RX B - 12345679 [64] 00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988959.108332) can1 RX B - 1234567A [64] 00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988959.115791) can1 RX B - 123 [64] 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988959.116215) can1 RX B - 124 [64] 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- ...
- (1613988969.087131) can1 RX B E 12345678 [64] 03 E6 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988969.087612) can1 RX B E 12345679 [64] 03 E6 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988969.088160) can1 RX B E 1234567A [64] 03 E6 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988969.095802) can1 RX B E 123 [64] 03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988969.095935) can1 RX B E 124 [64] 03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988969.096294) can1 RX B E 125 [64] 03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988969.097116) can1 RX B E 12345678 [64] 03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988969.097604) can1 RX B E 12345679 [64] 03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
- (1613988969.098102) can1 RX B E 1234567A [64] 03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
复制代码
这里前三行的格式问题, ESI的404行之前是-, 404行及以后是E, 暂时不解. 其它正常, ID顺序和数据都对得上.
Xavier发送脚本, ##后面的3表示开启BRS和ESI:
- #!/bin/sh
- while true; do
- cansend can1 18FF0001##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16
- cansend can1 18FF0002##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16
- cansend can1 18FF0003##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16
- cansend can1 18FF0004##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16
- cansend can1 18FF0005##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16
- cansend can1 18FF0006##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16
- sleep 0.01
- done
复制代码
可以在LPUART1串口中看到收到的数据, 如上面 新消息接收处理 小节配图.
|