嵌入式技术论坛
直播中

马占云

7年用户 1600经验值
私信 关注
[问答]

怎样去解决CAN发送与接收的丢包问题

CAN发送与接收的丢包问题
硬件:STM32F4IGT6
操作系统:RTTV4.1.0
CAN使用RTT的设备驱动
CAN波特率 1Mbps
通讯线不超过1米,电机CAN线和单片机CAN线与分析仪can线采用单向连接
测量终端电阻值为60Ω
使用标准CAN通信,不使用CANOEPN协议进行收发。
使用CAN分析仪进行发送 5ms间隔发送一帧标准帧
如图所示,单片机使用msh命令canstat查看接收丢包为0

1.jpg

使用CAN分析仪进行发送 1ms间隔发送一帧标准帧
如图所示,基本就没有接收

1.jpg

问题1:为什么基本接收不到?是硬件问题,还是搭载操作系统导致的?

使用CAN分析仪进行接收 单片机1ms间隔发送一帧标准帧
如图所示,发送正常。

1.jpg

但是发送频率并不是1ms一次。而是3ms发送3次。

1.jpg

试了下无间隔发送,变成3ms发送十几次左右。也是无丢包
发送测试代码如下,间隔时间使用rt_thread_mdelay(1)函数

void can_send_test(void)
{
struct rt_can_msg msg = {0};
rt_size_t size;
static rt_uint8_t num = 0;
msg.id = 0x78; /* ID 为 0x78 /
msg.ide = RT_CAN_STDID; /
标准格式 /
msg.rtr = RT_CAN_DTR; /
数据帧 /
msg.len = 8; /
数据长度为 8 /
/
待发送的 8 字节数据 /
msg.data[0] = 0x00;
msg.data[1] = num++;
msg.data[2] = 0x22;
msg.data[3] = 0x33;
msg.data[4] = num++;
msg.data[5] = 0x55;
msg.data[6] = 0x66;
msg.data[7] = 0x77;
/
发送一帧 CAN 数据 /
for(int i = 0;i < 1000;i++)
{
rt_thread_mdelay(1);
size = rt_device_write(can_dev, 0, &msg, sizeof(msg));
if (size == 0)
{
rt_kprintf("can dev write data failed!\n");
}
}
}
/
导出到 msh 命令列表中 */

MSH_CMD_EXPORT(can_send_test, can send test);

问题2:为什么发送会隔几秒发送多次?是不是fifo导致的?

使用CANOEPN协议进行收发,使用canfestival软件包
单片机发送数据,无接收
没有发送丢包

1.jpg

2.jpg

.单片机与电机通信,有收发
发送丢包率大概3.3%

1.jpg

通信内容

1.jpg

总线负载

1.jpg

问题3:为什么canfestival发送会丢包,裸机不会?为什么单独发送不会,收发就会?

是不是canfestival线程处理不够快导致的

将can的自动重发功能打开
可以不产生丢包
drv_can->CanHandle.Init.AutoRetransmission = ENABLE;

1.jpg

问题4:打开自动重发会有什么影响?会不会造成can通信延迟?

希望各位大佬可以解答一下我得到困惑。

刚用canopen,can之前也是使用标准can通信一下。对底层也不是很了解

回帖(7)

王越建

2022-11-8 11:27:39
没有使用过rtt的can驱动框架,之前项目使用到can通讯。使用esp32和stm32f407通讯,没有使用canopen,自己定义的通讯协议,主要发送json字符串数据,一个json字符串会发送多次can帧。
stm32f1 f4系列can只有3个发送和接收fifo,esp32快速发送can包时,stm32如果没有来得及取,fifo很容易就满了。
我当时的情况是,即使把can中断优先级调为最高,在中断中马上通过消息队列缓存起来,依然会产生大量丢包,can通讯速率从1M降到20kp还是一样。
最开始的解决办法是,发送3帧就延时5ms,太浪费效率了。
后来根据can协议发送成功是有ack标志位的,然后就是每次发送一条can消息就判断标志位是否接收成功,接收成功继续发送下一帧,超时就发送错误。
自动重发文档介绍的就很详细了,在我的项目中自动重发反而会导致一些问题还要占一个发送fifo,我就把它关了

1.jpg
举报

马占云

2022-11-8 11:27:46
那么问题1的答案就是分析仪发太快了,STM32接收FIFO处理不过来了。是硬件不够快。
问题2也是因为fifo的问题。发送太快了,只能先存到缓存内,然后等上一次发送完成在发送。所以会发几次延时几ms
问题四的话,其实有canopen发送丢包也是可以纠错的。
不知道有了canoepn的话,还需不需要自动重发。开更好还是不开好
举报

王越建

2022-11-8 11:28:18
问题一stm32其实很快,通过判断标志位,can的实际传输速度也是很快的,20多个can帧不到1ms,没有深度测试过,看的打印log的时间信息
问题二不确定,stm32发送can帧时,确实是往发送fifo添加报文,我的项目中发送fifo没有占满过,因为esp32有64个接收fifo。
软件层面如果做了丢包处理,就不需要开启硬件自动重发吧,除非canopen支持stm32的自动重发功能
举报

马占云

2022-11-8 11:28:27
问题1可能是我用了操作系统的原因,处理就肯定没有裸机快了。
问题2其实不怎么重要,实际上也不需要这么快的发送速率。
canopen支不支持自动重发不知道,但是开了自动重发,通讯是正常的,延迟不知道怎么样。
canopen丢包过多,是会关闭can通讯的,
举报

马占云

2022-11-8 11:28:44
关于问题2:我有了答案了。。。。
是分析仪的问题。换了一个贵的分析仪就好了。
使用RTT操作系统,标准CAN,1M波特率,无间隔发送100次,无接收。
如图所示。左边是便宜的,右边是贵的
1.jpg
测试发现,便宜的分析仪,测试ms级的发送都有误差。贵的可以测试100us级。
结论:一分钱一分货。
标准CAN最短发送间隔应该是128us,一个CAN帧有128bit,1M波特率刚好128us一帧
举报

马占云

2022-11-8 11:28:50
问题3的答案
丢包的原因
准确来说是撞包。由于两个不同节点同时发送CAN数据,由于优先级仲裁,导致低优先级的帧没有发送出去,硬件判断进入SCE中断后,转入发送失败事件处理。发送失败事件处理中判断为丢包,把计数加一
裸机发送不会是总线上没有同时两个节点都发送数据。或者是MCU发送的帧ID大于分析仪发送的。或者是速率不够快,造成撞包的几率减少
举报

马占云

2022-11-8 11:28:56
问题4
打开自动重发后,如果判断发送失败,会重复发送当前数据,直到发送成功。
一个会造成后面的数据会延迟发送。
另一个万一总线通信不良,比如短路、断路。会导致一直发送当前数据。如果没有做相应处理。另一个发送出错会进入SCE中断,自动重发下,没有发送出去会循环进入SCE中断的过程。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分