技事纪-J1939-CAN多帧传输的实现

一次J1939多帧传输的实现

概述

起因是需要编写一个充电枪的CAN通讯部分的程序,但因为一帧超过8字节(CAN传输一帧八字节),需要使用多帧传输,参考J1939协议实现。

软件环境:QT+LINUX

语言:C++

硬件:nuc972板子,NUC972DF61YC

大致流程

查找资料,关于多帧传输,需要先进行“握手”再发送数据,具体可参考下图:

具体实现

一次多帧传输,需要数据传输方先发送多帧请求,进行多帧发送连接,当然,双方可以约定一个CAN帧,作为标志信号;故,首先要进行TP.CM.RTS的发送,收到接收方回复的同意信号:TP.CM.CTS方可进行传输数据data的发送,即发送TP.DT;发送结束,接收方需回复接收完成信号:TP.CM.END;其格式分别如下:

类型PGN01234567
RTSEC10数据长度数据长度包数FF00数据PGN00
CTSEC11接收包数下一包号FFFF00数据PGN00
ENDEC13接受长度接受长读收到包数FF00数据PGN00
DTEB包号data1data2data3data4data5data6data7

按照上述过程,在接受线程收到数据EC后进行sendingPGN、包数等数据赋值,在接收线程进行处理,经CAN盒测试,成功;

实际通讯

实际测试发现一直报错,之后发现EC还有一个FF错误帧,因为CAN超时1.25S没有回复,就判定失败,所以报错,我实现的只是单设备CAN多帧收发,同时只能与一个对象进行收发,但广播了多个对象,然后在接收线程里重新实现了CAN的收发,之后又发现,CAN收发处理for循环可能被其他所影响,于是重新添加线程,专门进行多帧收发,如下


void ControllerRecvmanypacksMain::run()
{

    while (!m_quit) {
int  the_RSN_i = 0;
        if(can_boot_stop ==false){
 //printf("test:boot false:%d\n");
           for (the_RSN_i=0;the_RSN_i<14;the_RSN_i++)
           {
               if((Send_RSN_frame[the_RSN_i].pduformat==0x00)&&(Parser_RSN_frame[the_RSN_i].pduformat==0x00))
               {continue;
               }
               if(Parser_RSN_frame[the_RSN_i].pduformat==TP_CM)
               {
                   uint8_t J1939_TP = ControllerParserMain::JL_packets_req[the_RSN_i].JL_reqback[0];
                   if (J1939_TP==0x10) {

                       if (JL_Sendingpacks_PGN[the_RSN_i]==0) {
                           // printf("test:TP_CM:%d\n",from_address);
                           JL_Sendingpacks_PGN[the_RSN_i] = ControllerParserMain::JL_packets_req[the_RSN_i].JL_reqback[6] ;
                           if(JL_Sendingpacks_PGN[the_RSN_i]==0x00)
                           {
                               //JL_packets_back[the_RSN_i].JL_con_TP_CM_address.JL_con_to =Parser_RSN_frame[the_RSN_i].gunno;
                               memcpy(ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback,ControllerSendMain::JL_packets_reqback[2].JL_reqback,8);
                               ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback[6]=JL_Sendingpacks_PGN[the_RSN_i];
                               con_send_data(TP_CM,&ControllerSendMain::JL_packets_back[the_RSN_i]);
                           }
                           else
                           {

                               memcpy(ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback,ControllerSendMain::JL_packets_reqback[1].JL_reqback,8);
                               ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback[1]=ControllerParserMain::JL_packets_req[the_RSN_i].JL_reqback[3];
                               ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback[6]=JL_Sendingpacks_PGN[the_RSN_i];
                               con_send_data(TP_CM,&ControllerSendMain::JL_packets_back[the_RSN_i]);


                               memcpy(ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback,ControllerSendMain::JL_packets_reqback[3].JL_reqback,8);
                              ControllerSendMain:: JL_packets_back[the_RSN_i].JL_reqback[1]=ControllerParserMain::JL_packets_req[the_RSN_i].JL_reqback[1];
                               ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback[2]=ControllerParserMain::JL_packets_req[the_RSN_i].JL_reqback[2];
                              ControllerSendMain:: JL_packets_back[the_RSN_i].JL_reqback[3]=ControllerParserMain::JL_packets_req[the_RSN_i].JL_reqback[3];
                               ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback[6]=JL_Sendingpacks_PGN[the_RSN_i];
                              // con_send_data(TP_CM,&JL_packets_back[the_RSN_i]);

                           }
                       }

                    }
                    if (J1939_TP==0x11) {

                        int cnt;
                        if(JL_Sendingpacks_PGN[the_RSN_i]==0x00){
                        JL_Sendingpacks_PGN[the_RSN_i] = ControllerParserMain::JL_packets_req[the_RSN_i].JL_reqback[6] ;
                       switch (JL_Sendingpacks_PGN[the_RSN_i]) {
                       case SSN:
                           for (cnt=0;cnt<3;cnt++)
                           {
                           ControllerSendMain::JL_packs_datas[cnt].JL_con_TP_DT_address.JL_con_from = Parser_RSN_frame[the_RSN_i].gunno;
                          ControllerSendMain:: JL_packs_datas[cnt].pack_no=cnt+1;
                           if(cnt==2){
                           ControllerSendMain:: JL_packs_datas[cnt].the_dlc=8;
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[0]= ControllerSendMain::con_SSN[the_RSN_i].SSN[cnt*7];
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[1]= ControllerSendMain:: con_SSN[the_RSN_i].SSN[1+cnt*7];
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[2]= ControllerSendMain::con_SSN[the_RSN_i].SSN[2+cnt*7];
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[3]= 0xFF;
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[4]= 0xFF;
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[5]= 0xFF;
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[6]= 0xFF;
                           }
                           else{
                            ControllerSendMain::JL_packs_datas[cnt].the_dlc=8;
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[0]= ControllerSendMain::con_SSN[the_RSN_i].SSN[cnt*7];
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[1]= ControllerSendMain::con_SSN[the_RSN_i].SSN[1+cnt*7];
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[2]= ControllerSendMain::con_SSN[the_RSN_i].SSN[2+cnt*7];
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[3]= ControllerSendMain::con_SSN[the_RSN_i].SSN[3+cnt*7];
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[4]= ControllerSendMain::con_SSN[the_RSN_i].SSN[4+cnt*7];
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[5]= ControllerSendMain::con_SSN[the_RSN_i].SSN[5+cnt*7];
                            ControllerSendMain::JL_packs_datas[cnt].pack_data[6]= ControllerSendMain::con_SSN[the_RSN_i].SSN[6+cnt*7];
                           }
                           con_send_data(TP_DT,&ControllerSendMain::JL_packs_datas[cnt]);

                           }
                           break;
                       default:
                           break;
                       }
                              }

                        }
                    if (J1939_TP==0x13) {
                        if(JL_Sendingpacks_PGN[the_RSN_i] == ControllerParserMain::JL_packets_req[the_RSN_i].JL_reqback[6] )
                        {
                            JL_Sendingpacks_PGN[the_RSN_i]=0x00;
                        }
                    }

                    if (J1939_TP==0xFF) {
                        if(JL_Sendingpacks_PGN[the_RSN_i] == ControllerParserMain::JL_packets_req[the_RSN_i].JL_reqback[6] )
                        {
                            if(JL_Sendingpacks_PGN[the_RSN_i]==RSN)
                             {   JL_RSN_sending=0;
                            memset(ControllerParserMain::con_RSN_back[the_RSN_i].RSN_req,0x00,17);
                            }
                             JL_Sendingpacks_PGN[the_RSN_i]=0x00;
                        }
                    }

                    memset(&Parser_RSN_frame[the_RSN_i], 0x00, sizeof(con_frame_info_t));
                    continue;
               }


               /*******************overtime*********************/
               if(Parser_RSN_frame[the_RSN_i].pduformat==TP_DT){
               if ( controller_time()-Parser_RSN_frame[the_RSN_i].time>=1250) {

                                   Send_RSN_frame[the_RSN_i].gunno=0xFF;
                                   Send_RSN_frame[the_RSN_i].pduformat=JL_Sendingpacks_PGN[the_RSN_i];
                                   memset(&Parser_RSN_frame[the_RSN_i], 0x00, sizeof(con_frame_info_t));
               }else if (Parser_RSN_frame[the_RSN_i].count==ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback[3]) {

                   Send_RSN_frame[the_RSN_i].gunno=0x13;
                   Send_RSN_frame[the_RSN_i].pduformat=JL_Sendingpacks_PGN[the_RSN_i];
                   memset(&Parser_RSN_frame[the_RSN_i], 0x00, sizeof(con_frame_info_t));
               }
               continue;
               }
               /******************send***********************/
               if(Send_RSN_frame[the_RSN_i].pduformat!=0x00)
               {
                  // uint8_t J1939_TP = ControllerParserMain::JL_packets_req[the_RSN_i].JL_reqback[0];
                   if (Send_RSN_frame[the_RSN_i].gunno==0x10) {

                       if( JL_Sendingpacks_PGN[the_RSN_i] == Send_RSN_frame[the_RSN_i].pduformat){
                           memcpy(ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback,ControllerSendMain::JL_packets_reqback[0].JL_reqback,8);
                           ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback[6]=JL_Sendingpacks_PGN[the_RSN_i];

                                     if(the_RSN_i<2)  {
                                     ControllerSendMain:: JL_packets_back[the_RSN_i].JL_con_TP_CM_address.JL_con_from = 0x31+the_RSN_i;
                               }else if (the_RSN_i<14) {
                                     ControllerSendMain:: JL_packets_back[the_RSN_i].JL_con_TP_CM_address.JL_con_from = 0x40+the_RSN_i-1;
                               }
                                     switch ( JL_Sendingpacks_PGN[the_RSN_i]) {
                                     case SSN:
                                        ControllerSendMain:: JL_packets_back[the_RSN_i].JL_reqback[1]= 0x11;
                                        ControllerSendMain:: JL_packets_back[the_RSN_i].JL_reqback[3]= 0x03;
                                         break;
                                     default:
                                         break;
                                     }
                                 con_send_data(TP_CM ,&ControllerSendMain::JL_packets_back[the_RSN_i]);
                           }
                    }
                    if (Send_RSN_frame[the_RSN_i].gunno==0x11) {
                        //.............. receive 0x10  then  send 0x11
                        }
                    if (Send_RSN_frame[the_RSN_i].gunno==0x13) {
                        if (JL_Sendingpacks_PGN[the_RSN_i]==Send_RSN_frame[the_RSN_i].pduformat) {
                                  con_send_data(TP_CM ,&ControllerSendMain::JL_packets_back[the_RSN_i]);
                                  if(JL_Sendingpacks_PGN[the_RSN_i]==RSN)
                                   {
                                  ControllerParserMain::con_RSN_back[the_RSN_i].RSN_receive_success=1;
                                   JL_RSN_sending=0;

                                  }
                                  if(JL_Sendingpacks_PGN[the_RSN_i]==VIR)
                                  {   if(ControllerParserMain::con_VIR_back[the_RSN_i-2].receive_or_not ==0)
                                     { ControllerParserMain::con_VIR_back[the_RSN_i-2].receive_or_not = 1; }

                                      printf("VIR get successful:%d,gun:%d\n",ControllerParserMain::con_VIR_back[the_RSN_i-2].receive_or_not,the_RSN_i);
                                  }
                                   JL_Sendingpacks_PGN[the_RSN_i]=0x00;

                            }
                    }

                    if (Send_RSN_frame[the_RSN_i].gunno==0xFF) {

                            if (JL_Sendingpacks_PGN[the_RSN_i]==Send_RSN_frame[the_RSN_i].pduformat) {
                                memcpy(ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback,ControllerSendMain::JL_packets_reqback[2].JL_reqback,8);
                                ControllerSendMain::JL_packets_back[the_RSN_i].JL_reqback[6]=JL_Sendingpacks_PGN[the_RSN_i];
                                          if(the_RSN_i<2)  {
                                           ControllerSendMain::JL_packets_back[the_RSN_i].JL_con_TP_CM_address.JL_con_from = 0x31+the_RSN_i;
                                    }else if (the_RSN_i<14) {
                                           ControllerSendMain::JL_packets_back[the_RSN_i].JL_con_TP_CM_address.JL_con_from = 0x40+the_RSN_i-1;
                                    }
                                      con_send_data(TP_CM ,&ControllerSendMain::JL_packets_back[the_RSN_i]);

                                       if(JL_Sendingpacks_PGN[the_RSN_i]==RSN)
                                        {   JL_RSN_sending=0;
                                            memset(ControllerParserMain::con_RSN_back[the_RSN_i].RSN_req,0x00,17);
                                        }
                                        JL_Sendingpacks_PGN[the_RSN_i]=0x00;
                                }
                    }
                    memset(&Send_RSN_frame[the_RSN_i], 0x00, sizeof(con_frame_info_t));
                    continue;
               }
           }
        }else{
           // printf("test:boot true:%d\n");
        }
        msleep(300);
    }
}

希望有大佬指点一下,是否能更好实现?

参考:

 一个大佬的好帖子

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

H_sHe_N

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值