一次J1939多帧传输的实现
概述
起因是需要编写一个充电枪的CAN通讯部分的程序,但因为一帧超过8字节(CAN传输一帧八字节),需要使用多帧传输,参考J1939协议实现。
软件环境:QT+LINUX
语言:C++
硬件:nuc972板子,NUC972DF61YC
大致流程
查找资料,关于多帧传输,需要先进行“握手”再发送数据,具体可参考下图:
具体实现
一次多帧传输,需要数据传输方先发送多帧请求,进行多帧发送连接,当然,双方可以约定一个CAN帧,作为标志信号;故,首先要进行TP.CM.RTS的发送,收到接收方回复的同意信号:TP.CM.CTS方可进行传输数据data的发送,即发送TP.DT;发送结束,接收方需回复接收完成信号:TP.CM.END;其格式分别如下:
类型 | PGN | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|---|
RTS | EC | 10 | 数据长度 | 数据长度 | 包数 | FF | 00 | 数据PGN | 00 |
CTS | EC | 11 | 接收包数 | 下一包号 | FF | FF | 00 | 数据PGN | 00 |
END | EC | 13 | 接受长度 | 接受长读 | 收到包数 | FF | 00 | 数据PGN | 00 |
DT | EB | 包号 | data1 | data2 | data3 | data4 | data5 | data6 | data7 |
按照上述过程,在接受线程收到数据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);
}
}
希望有大佬指点一下,是否能更好实现?