你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32f103CAN口怎么接收来自上机位的一包32字节的数据

[复制链接]
黄同学来学习 提问时间:2019-1-14 11:06 /
如何接收上机位发送一包“69311F000335500050003FE0100112BB3550B5780E4004B7FA84F500104E00064”这样的数据存放在数组中待解析

现在用例程函数接收   只能接收8个字节的数  或者main函数一直扫描can口   这样接收会严重丢帧

各位大神能不能支个招呀  

程序设计思想是怎么样的?怎么样实现一下子接收32字节的数据包不丢帧?

说明一下:上机位一包数据是分多帧发送的,每帧发送间隔是小于1ms的,求大神支招,或者有现成例程给我改一下
收藏 1 评论20 发布时间:2019-1-14 11:06

举报

20个回答
黄同学来学习 回答时间:2019-1-14 14:49:42
stm1024 发表于 2019-1-14 13:21
你的问题可能不是丢包,应该是数据被新的数据给替换了

//ÖжϷþÎñº¯Êý                            
void USB_LP_CAN1_RX0_IRQHandler(void)
{
          CanRxMsg RxMessage;
                int i=0;
    CAN_Receive(CAN1, 0, &RxMessage);
//                        for(i=0;i<RxMessage.DLC;i++)
//                                {
//                                        if(RxMessage.Data==0x40)
//                                        {
//                                                canData=RxMessage.Data;
//                                        }
                        for(i=0;i<8;i++)//ÓÐÊý¾Ý½ÓÊÕÖжϣ¬ÕâÀï½ÓÊÕµ½Ò»Ö¡Êý¾Ý£¬¼´8×Ö½Ú
                        {
                                canData[j]=RxMessage.Data;
                                j++;
                        }
                       
                        if(canData[0]==0x40)//ÅжÏÊÇ·ñ±¨ÎĵÚÒ»×Ö½ÚÊÇ·ñΪ0x40
                        {       
                                canData_len=(canData[1]<<8|canData[2]);//½«µ±Ç°±¨Îij¤¶È°´8×Ö½Ú¼ÆËã
                                sun=canData_len/8;//¼ÆË㵱ǰ±¨ÎÄÓжàÉÙÖ¡Êý¾Ý
                        }
                        if(sun==0)//ÊÇ·ñ½ÓÊÕÍ굱ǰ±¨ÎÄÖ¡Êý
                        {
                                j=0;//½«Êý×éϱ껹ԭΪ0
                        }       
                        sun--;

//        j++;
//        printf("\r\n%d\r\n",j);
//                printf("\r\n");
}


这个是我改的中断服务函数   一直不行
黄同学来学习 回答时间:2019-1-14 14:57:28
stm1024 发表于 2019-1-14 13:21
你的问题可能不是丢包,应该是数据被新的数据给替换了

//中断服务函数                            
void USB_LP_CAN1_RX0_IRQHandler(void)
{
          CanRxMsg RxMessage;
                int i=0;
    CAN_Receive(CAN1, 0, &RxMessage);
//                        for(i=0;i<RxMessage.DLC;i++)
//                                {
//                                        if(RxMessage.Data==0x40)
//                                        {
//                                                canData=RxMessage.Data;
//                                        }
                        for(i=0;i<8;i++)//有数据接收中断,这里接收到一帧数据,即8字节
                        {
                                canData[j]=RxMessage.Data;
                                j++;
                        }
                       
                        if(canData[0]==0x40)//判断是否报文第一字节是否为0x40
                        {       
                                canData_len=(canData[1]<<8|canData[2]);//将当前报文长度按8字节计算
                                sun=canData_len/8;//计算当前报文有多少帧数据
                        }
                        if(sun==0)//是否接收完当前报文帧数
                        {
                                j=0;//将数组下标还原为0
                        }       
                        sun--;

//        j++;
//        printf("\r\n%d\r\n",j);
//                printf("\r\n");
}
黄同学来学习 回答时间:2019-1-14 14:55:13
stm1024 发表于 2019-1-14 13:21
你的问题可能不是丢包,应该是数据被新的数据给替换了

//中断服务函数                            
void USB_LP_CAN1_RX0_IRQHandler(void)
{
          CanRxMsg RxMessage;
                int i=0;
    CAN_Receive(CAN1, 0, &RxMessage);
//                        for(i=0;i<RxMessage.DLC;i++)
//                                {
//                                        if(RxMessage.Data==0x40)
//                                        {
//                                                canData=RxMessage.Data;
//                                        }
                        for(i=0;i<8;i++)//有数据接收中断,这里接收到一帧数据,即8字节
                        {
                                canData[j]=RxMessage.Data;
                                j++;
                        }
                       
                        if(canData[0]==0x40)//判断是否报文第一字节是否为0x40
                        {       
                                canData_len=(canData[1]<<8|canData[2]);//将当前报文长度按8字节计算
                                sun=canData_len/8;//计算当前报文有多少帧数据
                        }
                        if(sun==0)//是否接收完当前报文帧数
                        {
                                j=0;//将数组下标还原为0
                        }       
                        sun--;

//        j++;
//        printf("\r\n%d\r\n",j);
//                printf("\r\n");
}
废鱼 回答时间:2019-1-14 11:13:40
用CAN中断接收,把数据放入到指定的缓冲区中。外部再对缓冲区进行数据处理。

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

STM1024 回答时间:2019-1-14 11:19:21
本帖最后由 stm1024 于 2019-1-14 11:20 编辑

正统的做法是采用CAN FD,最多可支持64bytes的数据场。但是目前103的CAN控制器不支持CAN FD,如果你想用一帧报文传输,原则是不能实现的。
不过也有work around的方法,就是把数据拆分为多次发送。
例如你这里有32个字节,你可以分5帧发送,为什么不是4帧呢?因为第五帧要用来做校验和,验证数据的完整性。
在具体实施上,可以采用一个ID发送,也可以分多个ID发送。如果共用一个ID,则建议每个ID的数据场中,第一个字节用来标识子组数据的位置,便于以后还原,这样的话最少要5次。如果是多个ID,则位置根据ID来确定。

最后就是,下位机的CAN接收报文,尽可能使用interrupt方式,而不是polling方式。

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

黄同学来学习 回答时间:2019-1-14 11:20:24
安 发表于 2019-1-14 11:13
用CAN中断接收,把数据放入到指定的缓冲区中。外部再对缓冲区进行数据处理。 ...

大神  非常感谢你能回复我   我是can新手   现在还是在改代码的阶段   其他的都是半桶水   能不能说具体一点  缓冲区下次接收就已经覆盖前一帧的数据了
黄同学来学习 回答时间:2019-1-14 11:29:28
stm1024 发表于 2019-1-14 11:19
正统的做法是采用CAN FD,最多可支持64bytes的数据场。但是目前103的CAN控制器不支持CAN FD,如果你想用一 ...

大神  我需要一个小时来理解你的话   水平不够  还在复制改代码的阶段     现在上机位的报文就是你说的同个ID多帧分多次发送的   就是我接收不会接   用中断接收只存了8个字节其他的不见了   只接收到最后的8个字节
废鱼 回答时间:2019-1-14 11:38:00
需要你自己开一个缓冲区,可以存放多个CAN数据的。每包CAN数据第一个自己最好是指示包序号。通过对所有的CAN数据进行整理进行数据重新排序。
比如:
CAN[0]={01,01,02,03,04,05,06,07}
CAN[1]={02,08,09,10,11,12,13,14}
重新排列以后是:01,02,03,04,05,06,07,08,09,10,11,12,13,14
黄同学来学习 回答时间:2019-1-14 11:52:19
安 发表于 2019-1-14 11:38
需要你自己开一个缓冲区,可以存放多个CAN数据的。每包CAN数据第一个自己最好是指示包序号。通过对所有的CA ...

我是已经定义了一个数组candata[1000]={0};这个就是用来存接收上机位 的报文的有些时候不止32个字节的   我就想怎么把接收到报文完整地存进这个数组里面   上机位的报文含有包头“69”和报文长度的   现在就是不知道怎么完整接收存进自己定义的数组里面
STM1024 回答时间:2019-1-14 13:21:14
黄同学来学习 发表于 2019-1-14 11:29
大神  我需要一个小时来理解你的话   水平不够  还在复制改代码的阶段     现在上机位的报文就是你说的同 ...

你需要做一个buffer。看你其他的回复,这个是有的。但是你在中断中要跟踪缓冲区的下标。例如来第一个报文的时候,buffer的起始Index为0,第二帧报文来了,起始index应该是8,否则把之前存的数据都给刷新变没了。
STM1024 回答时间:2019-1-14 13:21:57
黄同学来学习 发表于 2019-1-14 11:20
大神  非常感谢你能回复我   我是can新手   现在还是在改代码的阶段   其他的都是半桶水   能不能说具体 ...

你的问题可能不是丢包,应该是数据被新的数据给替换了
Johnson Cao 回答时间:2019-1-14 13:57:15
使用环形缓冲区,中断写,main里读就行了.环形缓冲研究下,以后搞通信,用得上的地方多了去.

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

STM1024 回答时间:2019-1-14 15:35:02
黄同学来学习 发表于 2019-1-14 14:57
//中断服务函数                            
void USB_LP_CAN1_RX0_IRQHandler(void)
{

if(RxMessage.Data==0x40)
为什么有这种写法?Data是一个数组啊喂
西点钟灵毓秀 回答时间:2019-1-14 15:52:29
打包,拆包,重组,校验

评分

参与人数 1蝴蝶豆 +1 收起 理由
STMCU + 1

查看全部评分

12下一页

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版