usbcan例程开发开发上位机

该博客详细介绍了如何使用USBCAN设备解析S19文件并将数据转换为BIN格式,同时展示了发送逻辑。通过读取S19文件,将数据重新排序,然后使用定时器实现自动发送。在发送过程中,遇到问题如窗口卡死,通过定时器模拟发送按钮点击以解决。此外,还包含了一个接收线程用于接收和处理接收到的数据。
摘要由CSDN通过智能技术生成

1.工具usbcan 型号2e_u

官方给出的是使用mfc例程,此文章是根据例程解析s19文件,并发送部分数据

1.打开文件,并将s19文件转成bin逻辑

void CECanTestDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	unsigned char buffer_1[BUFSIZE];
	#if 1
	char szPath[MAX_PATH] = ""; //存放选择的目录路径 
	
	CString str;
	ZeroMemory(szPath, sizeof(szPath));
	BROWSEINFO bi;
	bi.hwndOwner = m_hWnd;
	bi.pidlRoot = NULL;
	bi.lpfn=BrowseCallbackProc;
    bi.lParam= long(DefaultDir);
	bi.pszDisplayName = szPath;
	bi.lpszTitle = "请选择需要打开的文件:";
	//bi.ulFlags = 0;
	bi.ulFlags = BIF_BROWSEINCLUDEFILES|BIF_STATUSTEXT;
	
	bi.iImage = 0;
	LPITEMIDLIST lp = SHBrowseForFolder(&bi);
	if(lp && SHGetPathFromIDList(lp, szPath))
	{
		::SHGetPathFromIDList(lp,szPath);
		change::get_path(DefaultDir,szPath,MAX_PATH);
		state1 = 1;

		//str.Format("选择的目录为 %s", szPath);
		//AfxMessageBox(str);
	}
	else
	{
		AfxMessageBox("无效的目录,请重新选择");
	}
	#endif

	 UpdateData(FALSE);
#if 0
	HANDLE hFile = CreateFile(_T("D:\\test.txt"),
		GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
		CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);//锟斤拷锟斤拷锟侥硷拷
#endif
	unsigned flag = 0;
	HANDLE hFile = NULL;
	LONG lDistance = 0;
	DWORD dwWritenSize = 0;
	BOOL bRet;
	DWORD dwReadSize = 0;
	unsigned int i, j;
	unsigned int temp, temp1;

	//hFile = CreateFile(_T("D:\\123.s19"),
	hFile = CreateFile(szPath,
		GENERIC_READ,
		FILE_SHARE_READ,
		NULL,
		OPEN_ALWAYS,
		FILE_SHARE_READ,
		NULL);
	bRet = ReadFile(hFile, s19, max_size, &dwReadSize, NULL);
	if (bRet)
	{
		ShowInfo(_T("文件预览"),0);
		//ShowInfo(_T("字节数"),0);
		//change::num_sring(buffer_1,&,1);
		unsigned int temp;
		temp = change::get_info(s19,dwReadSize);
		change::paixu(temp);
		temp = change::s19_to_bin(buffer,s19,temp);
		sum_date = temp;
		for(i = 0;i<16;i++)//此处为填充发出去的flash,防止写入错误的值
		{
			if(buffer[temp +i] < max_size)
				buffer[temp +i] = 0;
		}
		unsigned int dis_addr = addrinfo_1[0].addr;
#if 1//hl_test
		for(i=0;i<100;i++)//
#else
		for(i=0;i<(temp+15)/16;i++)//
#endif
		{
			unsigned int just_temp;
			just_temp = change::inttoAscii(buffer_1,dis_addr);
			dis_addr +=16;
			change::num_sring(buffer_1+just_temp,&buffer[i*16],16);
			ShowInfo((CString)buffer_1,0);
		}
		ShowInfo(_T("文件预览结束"),0);	
	}
	else
	{
		state = open_file_fail;
		MessageBox(_T("缺少文件!"));
	}
	state = open_file_ok;
	
}

 2.发送逻辑

void CECanTestDlg::OnButtonSend() 
{
	// TODO: Add your control notification handler code here
	
	
	/*
	if(m_connect==0)
	{
		MessageBox(_T("Not open device!"),_T("Alarm"),MB_OK|MB_ICONQUESTION);
		return;
	}
	CAN_OBJ frameinfo;
	char szFrameID[9];
	unsigned char FrameID[4]={0,0,0,0};
	memset(szFrameID,'0',9);
	CString sTmp;
	BYTE datalen=0;
	
	UpdateData(true);
	if(m_EditSendFrmID.GetLength()==0||
		(m_EditSendData.GetLength()==0&&m_ComboSendFrmType.GetCurSel()==0))
	{
		ShowInfo("Input data",1);
		return;
	}
	
	if(m_EditSendFrmID.GetLength()>8)
	{
		ShowInfo("ID rang over",1);
		return;
	}
	if(m_EditSendData.GetLength()>24)
	{
		ShowInfo("data over len,max 8 byte",1);
		return;
	}
	if(m_ComboSendFrmType.GetCurSel()==0)
	{
		if(m_EditSendData.GetLength()%3==1)
		{
			ShowInfo("data format fault,please input again",1);
			return;		
		}		
	}

	GetDlgItemText(IDC_EDIT_SENDFRAMEID,m_EditSendFrmID);

	GetDlgItemText(IDC_EDIT_SENDDATA,m_EditSendData);

	int i,k;
	k=0;
	CString cstmp="";
	datalen=(m_EditSendData.GetLength()+1)/3;

	for(i=0;i<m_EditSendData.GetLength();i++)
	{
			
		

		if(m_EditSendData.Mid(i+1,1)!=" ")
			cstmp=cstmp+m_EditSendData.Mid(i+1,1);
		else
		{
			if(cstmp!="")
			{
				frameinfo.Data[k]=(unsigned char)_tcstoul(cstmp,0,16);
				cstmp="";
				k=k+1;
			}
		}

				
	}



	UpdateData(false);
	
	frameinfo.DataLen=k;


	frameinfo.RemoteFlag=m_ComboSendFrmFmt.GetCurSel();
	frameinfo.ExternFlag=m_ComboSendFrmType.GetCurSel();
	if(frameinfo.ExternFlag==1)
	{
		frameinfo.ID=((DWORD)FrameID[0]<<24)+((DWORD)FrameID[1]<<16)+((DWORD)FrameID[2]<<8)+
			((DWORD)FrameID[3]);
	}
	else
	{
		frameinfo.ID=((DWORD)FrameID[2]<<8)+((DWORD)FrameID[3]);		
	}


	frameinfo.ID=_tcstoul(m_EditSendFrmID, 0, 16); 


	
	if(Transmit(m_devtype,0,0,&frameinfo,1)==1)
	{
		ShowInfo("Send success",0);		
	}
	else
	{
		ShowInfo("Send fault",2);		
	}
	
	  */

	//if(m_connect==0)
	//	return;
	CAN_OBJ frameinfo;
	char szFrameID[9];
	unsigned char FrameID[4]={0,0,0,0};
	memset(szFrameID,'0',9);
	unsigned char Data[8];
	char szData[25];
	BYTE datalen=0;
	
	UpdateData(true);
#if 0
	if(m_EditSendFrmID.GetLength()==0||
		(m_EditSendData.GetLength()==0&&m_ComboSendFrmType.GetCurSel()==0))
	{
		ShowInfo("请输入数据",1);
		return;
	}
	
	if(m_EditSendFrmID.GetLength()>8)
	{
		ShowInfo("ID值超过范围",1);
		return;
	}
	if(m_EditSendData.GetLength()>24)
	{
		ShowInfo("数据长度超过范围,最大为8个字节",1);
		return;
	}
	if(m_ComboSendFrmType.GetCurSel()==0)
	{
		if(m_EditSendData.GetLength()%3==1)
		{
			ShowInfo("数据格式不对,请重新输入",1);
			return;		
		}		
	}
	memcpy(&szFrameID[8-m_EditSendFrmID.GetLength()],(LPCTSTR)m_EditSendFrmID,m_EditSendFrmID.GetLength());
	strtodata((unsigned char*)szFrameID,FrameID,4,0);

	datalen=(m_EditSendData.GetLength()+1)/3;
	strcpy(szData,(LPCTSTR)m_EditSendData);
	strtodata((unsigned char*)szData,Data,datalen,1);


	UpdateData(false);
	
	frameinfo.SendType = 0;
	frameinfo.DataLen=datalen;
	memcpy(&frameinfo.Data,Data,datalen);

	frameinfo.RemoteFlag=m_ComboSendFrmFmt.GetCurSel();
	frameinfo.ExternFlag=m_ComboSendFrmType.GetCurSel();
	if(frameinfo.ExternFlag==1)
	{
		frameinfo.ID=((DWORD)FrameID[0]<<24)+((DWORD)FrameID[1]<<16)+((DWORD)FrameID[2]<<8)+
			((DWORD)FrameID[3]);
	}
	else
	{
		frameinfo.ID=((DWORD)FrameID[2]<<8)+((DWORD)FrameID[3]);		
	}
//	frameinfo.SendType=m_ComboSendType.GetCurSel();

	if(Transmit(m_devtype,0,0,&frameinfo,1)==1)
	{
		ShowInfo("写入成功",0);		
	}
	else
	{
		ShowInfo("写入失败",2);		
	}
#endif

	
	
	if(m_EditSendFrmID.GetLength()>8)
	{
		ShowInfo("ID值超过范围",1);
		return;
	}


	memcpy(&szFrameID[8-m_EditSendFrmID.GetLength()],(LPCTSTR)m_EditSendFrmID,m_EditSendFrmID.GetLength());
	strtodata((unsigned char*)szFrameID,FrameID,4,0);

	datalen=(m_EditSendData.GetLength()+1)/3;
	strcpy(szData,(LPCTSTR)m_EditSendData);
	strtodata((unsigned char*)szData,Data,datalen,1);


	UpdateData(false);
	
	frameinfo.SendType = 0;
	frameinfo.DataLen=datalen;
	//memcpy(&frameinfo.Data,Data,datalen);

	frameinfo.RemoteFlag=m_ComboSendFrmFmt.GetCurSel();
	frameinfo.ExternFlag=m_ComboSendFrmType.GetCurSel();
	if(frameinfo.ExternFlag==1)
	{
		frameinfo.ID=((DWORD)FrameID[0]<<24)+((DWORD)FrameID[1]<<16)+((DWORD)FrameID[2]<<8)+
			((DWORD)FrameID[3]);
	}
	else
	{
		frameinfo.ID=((DWORD)FrameID[2]<<8)+((DWORD)FrameID[3]);		
	}
	unsigned int i,j;
	unsigned char temp = 0;
	unsigned char buffer_2[30];//显示数字
	
	if(0 == addr)
		ShowInfo(_T("开始写入"),0);
	unsigned int uds_order;
	uds_order = addr;
	{

		uds::send_order(addr);//装填数据
		
		if(uds::send_handle(frameinfo.Data))//打包成网络层
		{
			addr++;
		}
		else
		{
			
		}
		

		unsigned char buffer_1[30];//显示最终字符
#if hl_test	
		if(1)		//测试为发送成功
#else
		if(Transmit(m_devtype,0,0,&frameinfo,1)==1)
#endif
		{
			change::num_sring(buffer_1,&frameinfo.Data[0],8);
			ShowInfo(buffer_1,0);		
		}
		else
		{
			change::num_sring(buffer_1,&frameinfo.Data[0],8);
			ShowInfo(buffer_1,0);
			ShowInfo("写入失败",2);		
		}
		
	}

	SetTimer(timer1,100,NULL);//10ms进去1次,开启定时器



	

	char buffer_name[50];
	change::int_to_char(buffer_name,uds_send_info.to_send);
	VALUE.SetWindowText((LPCTSTR)(buffer_name));
	change::int_to_char(buffer_name,uds_send_info.length);
	VALUE2.SetWindowText((LPCTSTR)(buffer_name));
	change::int_to_char(buffer_name,ceshi);
	VALUE3.SetWindowText((LPCTSTR)(buffer_name));

	if((addr >= handle_num))
	{
		addr = 0;
		ShowInfo(_T("写入完成"),0);//在对话框中写入提示
		KillTimer(timer1);
	}
	else
	{
		
	}
#if 0	
	CString jindu;
	//显示进度条,暂时不处理
	if(sum_date)
		jindu.Format("%d",addr*100/sum_date);
	else
		jindu.Format("%d",0);
#endif
	
	//GetDlgItem(IDC_EDIT1)->SetWindowText((jindu));//写数值
	//GetDlgItem(IDC_STATIC)->SetTextColor(RGB(255, 0, 0));
	
	
}

3.实际发现在发送函数中一直发送数据,窗口会会卡死,无法相应其他操作,可以使用一个定时器来一直点击发送按钮,实现自动发送的效果。

void CECanTestDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if(timer1 == nIDEvent)
	{
		//if(1)0 == old_addr)//只有在不接收时间才发送
		{
			PostMessage(WM_COMMAND, MAKEWPARAM(IDC_BUTTON_SEND, BN_CLICKED), NULL);
		}
			
	}
	CDialog::OnTimer(nIDEvent);
}
SetTimer(timer1,100,NULL);//10ms进去1次,开启定时器

当不用定时器时,停止定时器

KillTimer(timer1);

定时器结束时调用此函数,会模拟发送一个点击发送的指令,

void CECanTestDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if(timer1 == nIDEvent)
	{
		//if(1)0 == old_addr)//只有在不接收时间才发送
		{
			PostMessage(WM_COMMAND, MAKEWPARAM(IDC_BUTTON_SEND, BN_CLICKED), NULL);
		}
			
	}
	CDialog::OnTimer(nIDEvent);
}

 在停止发送时,也可以停止定时器

解析s19文件

此处解析s19的思路为创建一个足够大的内容空间,将s19中提取的数据填入到此内存空间中,有的s19地址是部分是乱的,从新排列有利于发送数据

1此处将s19拆解成带有地址的数据包,

unsigned int change::get_info(unsigned char *sour,int length)//128k为0x2 0000,int 可以容纳
{
	
	unsigned int i,j = 0;
	char temp;
	for(i = 0;i<length;)
	{
		temp = sour[i];
		if(sour[i] == 's'||sour[i] == 'S')//当有s判断下一至来判断地址的长度
		{
			if('0' == sour[i+1])//此处没有有效数据
			{
				i++;
				continue;
			}
			else if('1' == sour[i+1])
			{
				addrinfo_1[j].length = (Ascii2char(sour[i+2],sour[i+3])-3);//此处不乘以2,防止越界,-3地址2,校验1
				addrinfo_1[j].addr = Ascii2int(sour[i+4],sour[i+5],sour[i+6],sour[i+7]);
				addrinfo_1[j].position = i+8;
				j++;
				i += 8;
			}
			else if('2' == sour[i+1])
			{
				addrinfo_1[j].length = (Ascii2char(sour[i+2],sour[i+3])-4);//此处不乘以2,防止越界  -4地址3,校验1
				addrinfo_1[j].addr = Ascii2int(sour[i+4],sour[i+5],sour[i+6],sour[i+7]);
				addrinfo_1[j].addr <<= 8;
				addrinfo_1[j].addr += (Ascii2char(sour[i+8],sour[i+9]));
				addrinfo_1[j].position = i+10;
				j++;
				i += 8;
			}
			else
			{
				i++;//终止
				return j;
			}
		}
		else
		{
			i++;
		}
	}
	return j;
}

 将得到的数据填入到内存中,方便发送时取用

unsigned int change::s19_to_bin(unsigned char *dst,unsigned char *sour,int length)//128k为0x2 0000,int 可以容纳
{
	unsigned int i,j,k = 0;
	unsigned int temp = 0;//
	unsigned int temp_addr = 0;//
	unsigned int temp1 = 0;//转成的16进制数
	unsigned int temp2 = 0;//转成的16进制数
	for(i = 0;i <length;i++)
	{
#if 0
		temp = addrinfo_1[paixunum[i]].length;
		temp <<= 1;

		for(j = 0;j < temp;j += 2)
		{
			temp1 = sour[addrinfo_1[paixunum[i]].position+j];
			temp2 = sour[addrinfo_1[paixunum[i]].position+j+1];
			dst[k++] = Ascii2char(temp1,temp2);
		}
#endif
		temp = addrinfo_1[paixunum[i]].length;
		temp <<= 1;
		temp_addr = addrinfo_1[i].addr;
		for(j = 0;j < temp;j += 2)
		{
			temp1 = sour[addrinfo_1[i].position+j];
			temp2 = sour[addrinfo_1[i].position+j+1];
			dst[temp_addr++] = Ascii2char(temp1,temp2);
		}
		

	}
	return temp_addr;
}

如果要对接收值进行判定,在一下函数中进行判断

UINT CECanTestDlg::ReceiveThread(void *param)
{
	CECanTestDlg *dlg=(CECanTestDlg*)param;
	CListBox *box=(CListBox *)dlg->GetDlgItem(IDC_LIST_INFO);
	CAN_OBJ frameinfo[50];

	int len=1;
	int i=0;
	old_addr = 1;//接收为1
	CString str,tmpstr;
	while(1)
	{
		Sleep(1);
		if(dlg->m_connect==0)
		{
			old_addr = 0;//退出为空闲状态
			break;
		}
			
		len=Receive(dlg->m_devtype,0,0,frameinfo,50,100);
		if(len>0)
		{
		
			for(i=0;i<len;i++)
			{
				str="Rec:  ";
				if(frameinfo[i].TimeFlag==0)
					tmpstr="Time:  ";
				else
					tmpstr.Format(_T("Time:%08x "),frameinfo[i].TimeStamp);
				str+=tmpstr;
				tmpstr.Format(_T("ID:%08x "),frameinfo[i].ID);
				str+=tmpstr;
				str+="Format:";
				if(frameinfo[i].RemoteFlag==0)
					tmpstr="Data ";
				else
					tmpstr="Romte ";
				str+=tmpstr;
				str+="Type:";
				if(frameinfo[i].ExternFlag==0)
					tmpstr="Stand ";
				else
					tmpstr="Exten ";
				str+=tmpstr;
				box->InsertString(box->GetCount(),str);
				if(frameinfo[i].RemoteFlag==0)
				{
					str="Data:";
					if(frameinfo[i].DataLen>8)
						frameinfo[i].DataLen=8;
					for(int j=0;j<frameinfo[i].DataLen;j++)
					{
						tmpstr.Format(_T("%02x "),frameinfo[i].Data[j]);
						str+=tmpstr;
					}
					//此处加入逻辑
					if(frameinfo[i].ID)//暂时不判断
					{
#if 0
						if(1 == frameinfo[i].Data[0])
						{
							addr++;
						}

#endif
						
						uds::rec_date(frameinfo[i].Data);
						
					}
					
					box->InsertString(box->GetCount(),str);
					
				}				
			}
			box->SetCurSel(box->GetCount()-1);
		}
	}
	old_addr = 0;//退出为空闲状态
	return 0;
}

软件地址根据usbcan例程修改解析s19文件,且外发bin的例程-互联网文档类资源-CSDN下载

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LabVIEW作为一种强大的图形化编程语言和开发环境,可以方便地实现ZLG USB-CAN二次开发例程。 首先,我们需要安装ZLG USB-CAN的驱动程序,并将其与LabVIEW进行连接。可以通过在LabVIEW中使用VISA(Virtual Instrument Software Architecture)来实现与硬件设备的通信。在安装完成驱动程序后,我们就可以开始构建自己的二次开发例程了。 接下来,我们需要创建一个新的VI(Virtual Instrument)。在VI中,我们可以使用LabVIEW提供的各种函数和工具来进行CAN通信的设置和控制。例如,我们可以使用VISA函数库中的VISA Open函数来打开与ZLG USB-CAN设备的连接,并选择相应的设备和通信接口。然后,我们可以使用VISA Write和VISA Read函数来读写CAN消息。 LabVIEW还提供了丰富的图形化界面设计工具,用于创建可视化的用户界面。我们可以使用这些工具来设计一个直观、易用的界面,以便用户能够方便地操作和监控CAN通信。 此外,LabVIEW还支持各种数据处理和分析功能,可以帮助我们对CAN消息进行解析、过滤和转换等操作。我们可以使用LabVIEW提供的图形化编程工具来实现这些功能,而无需编写复杂的代码。 总之,利用LabVIEW进行ZLG USB-CAN二次开发例程非常方便。LabVIEW提供了丰富的功能和工具,可以帮助我们快速搭建CAN通信系统,并实现各种自定义的功能和算法。无论是初学者还是有经验的开发者,都可以通过LabVIEW轻松地进行ZLG USB-CAN二次开发
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值