关于发送和接受can数据包的VC例子。

解决方案 »

  1.   

    对于这些硬件类的编程,你应该找一下can的协议说明,然后再搜索一下“can 程序”,结合的看一下,很快就能把程序作出来的。
      

  2.   

    什么样的例子 我搞过CAN 周立功的
      

  3.   


    //接口卡类型定义
    #define VCI_PCI5121 1
    #define VCI_PCI9810 2
    #define VCI_USBCAN1 3
    #define VCI_USBCAN2 4
    #define VCI_PCI9820 5
    #define VCI_CAN232 6
    //CAN错误码
    #define ERR_CAN_OVERFLOW 0x0001 //CAN控制器内部FIFO溢出
    #define ERR_CAN_ERRALARM 0x0002 //CAN控制器错误报警
    #define ERR_CAN_PASSIVE 0x0004 //CAN控制器消极错误
    #define ERR_CAN_LOSE 0x0008 //CAN控制器仲裁丢失
    #define ERR_CAN_BUSERR 0x0010 //CAN控制器总线错误//通用错误码
    #define ERR_DEVICEOPENED 0x0100 //设备已经打开
    #define ERR_DEVICEOPEN 0x0200 //打开设备错误
    #define ERR_DEVICENOTOPEN 0x0400 //设备没有打开
    #define ERR_BUFFEROVERFLOW 0x0800 //缓冲区溢出
    #define ERR_DEVICENOTEXIST 0x1000 //此设备不存在
    #define ERR_LOADKERNELDLL 0x2000 //装载动态库失败
    #define ERR_CMDFAILED 0x4000 //执行命令失败错误码
    #define ERR_BUFFERCREATE 0x8000 //内存不足
    //函数调用返回状态值
    #define STATUS_OK 1
    #define STATUS_ERR 0
    //1.ZLGCAN系列接口卡信息的数据类型。
    typedef  struct  _VCI_BOARD_INFO{
    USHORT hw_Version;
    USHORT fw_Version;
    USHORT dr_Version;
    USHORT in_Version;
    USHORT irq_Num;
    BYTE can_Num;
    CHAR str_Serial_Num[20];
    CHAR str_hw_Type[40];
    USHORT Reserved[4];
    } VCI_BOARD_INFO,*PVCI_BOARD_INFO; //2.定义CAN信息帧的数据类型。
    typedef  struct  _VCI_CAN_OBJ{
    UINT ID;
    UINT TimeStamp;
    BYTE TimeFlag;
    BYTE SendType;
    BYTE RemoteFlag;//是否是远程帧
    BYTE ExternFlag;//是否是扩展帧
    BYTE DataLen;
    BYTE Data[8];
    BYTE Reserved[3];
    }VCI_CAN_OBJ,*PVCI_CAN_OBJ;//3.定义CAN控制器状态的数据类型。
    typedef struct _VCI_CAN_STATUS{
    UCHAR ErrInterrupt;
    UCHAR regMode;
    UCHAR regStatus;
    UCHAR regALCapture;
    UCHAR regECCapture; 
    UCHAR regEWLimit;
    UCHAR regRECounter; 
    UCHAR regTECounter;
    DWORD Reserved;
    }VCI_CAN_STATUS,*PVCI_CAN_STATUS;//4.定义错误信息的数据类型。
    typedef struct _ERR_INFO{
    UINT ErrCode;
    BYTE Passive_ErrData[3];
    BYTE ArLost_ErrData;
    } VCI_ERR_INFO,*PVCI_ERR_INFO;//5.定义初始化CAN的数据类型
    typedef struct _INIT_CONFIG{
    DWORD AccCode;
    DWORD AccMask;
    DWORD Reserved;
    UCHAR Filter;
    UCHAR Timing0;
    UCHAR Timing1;
    UCHAR Mode;
    }VCI_INIT_CONFIG,*PVCI_INIT_CONFIG;DWORD __stdcall VCI_OpenDevice(DWORD DeviceType,DWORD DeviceInd,DWORD Reserved);
    DWORD __stdcall VCI_CloseDevice(DWORD DeviceType,DWORD DeviceInd);
    DWORD __stdcall VCI_InitCAN(DWORD DeviceType, DWORD DeviceInd, DWORD CANInd, PVCI_INIT_CONFIG pInitConfig);DWORD __stdcall VCI_ReadBoardInfo(DWORD DeviceType,DWORD DeviceInd,PVCI_BOARD_INFO pInfo);
    DWORD __stdcall VCI_ReadErrInfo(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_ERR_INFO pErrInfo);
    DWORD __stdcall VCI_ReadCANStatus(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_STATUS pCANStatus);DWORD __stdcall VCI_GetReference(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,DWORD RefType,PVOID pData);
    DWORD __stdcall VCI_SetReference(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,DWORD RefType,PVOID pData);ULONG __stdcall VCI_GetReceiveNum(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);
    DWORD __stdcall VCI_ClearBuffer(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);DWORD __stdcall VCI_StartCAN(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);
    DWORD __stdcall VCI_ResetCAN(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd);ULONG __stdcall VCI_Transmit(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_OBJ pSend,ULONG Len);
    ULONG __stdcall VCI_Receive(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_OBJ pReceive,ULONG Len,INT WaitTime=-1)
    以上为头文件 然后你必须把对方的LIB文件导入库引入工程以下是对话框 其中实现收发
      

  4.   

    void CTestDlg::OnButtonStartcan() 
    {
    // TODO: Add your control notification handler code here
    if(m_connect==0)
    return;
    if(VCI_StartCAN(m_devtype,m_devind,m_cannum)==1)
    {
    ShowInfo("启动成功",0);
    }
    else
    {
    CString str;
    str="启动失败";
    ShowInfo(str,2);
    }
       theApp.TimerID=timeSetEvent(3,0,fnTimerProc,NULL,TIME_PERIODIC);//设置多媒体定时器。
       SetTimer(1,55,NULL);
    }void CTestDlg::OnButtonConnect() 
    {
    // TODO: Add your control notification handler code here
    if(m_connect==1)
    {
    m_connect=0;
    Sleep(500);
    GetDlgItem(IDC_BUTTON_CONNECT)->SetWindowText("连接");
    VCI_CloseDevice(m_devtype,m_devind);
    return;
    } VCI_INIT_CONFIG init_config;
    int index,filtertype,mode,cannum;
    CString strcode,strmask,strtiming0,strtiming1,strtmp;
    char szcode[20],szmask[20],sztiming0[20],sztiming1[20];
    unsigned char sztmp[4];
    DWORD code,mask,timing0,timing1;

    UpdateData(true);
    index=0;//设备索引好,0为PCI5121,m_ComboIndex.GetCurSel();
    filtertype=filter_type;//滤波的方式,0为单滤波,1为双滤波。m_ComboFilterType.GetCurSel();
    mode=0;//m_ComboMode.GetCurSel();//0 正常模式 1,只听模式。
    cannum=can_number;//CAN 的路数,0或1;m_ComboCANInd.GetCurSel();
    strcode=Acode;//m_EditCode;代码
    strmask=Amask;//m_EditMask;验收屏蔽码;
       if(braut==0){strtiming0="c0";strtiming1="14";}
    if(braut==1){strtiming0="c0";strtiming1="1c";}
        if(braut==2){strtiming0="c1";strtiming1="1c";}
       if(braut==3){strtiming0="c3";strtiming1="1c";}
       if(braut==4){strtiming0="c4";strtiming1="1c";}
       if(braut==5){strtiming0="c9";strtiming1="1c";}
       if(braut==6){strtiming0="18";strtiming1="1c";}
       if(braut==7){strtiming0="31";strtiming1="1c";} UpdateData(false);

    strtmp=strcode;
    strcode.Format("%08s",strtmp);
    strtmp=strmask;
    strmask.Format("%08s",strtmp);
    strtmp=strtiming0;
    strtiming0.Format("%02s",strtmp);
    strtmp=strtiming1;
    strtiming1.Format("%02s",strtmp);

    strcpy(szcode,(LPCTSTR)strcode);
    strcpy(szmask,(LPCTSTR)strmask);
    strcpy(sztiming0,(LPCTSTR)strtiming0);
    strcpy(sztiming1,(LPCTSTR)strtiming1);

    if(strtodata((unsigned char*)szcode,sztmp,4,0)!=0)
    {
    MessageBox("验收码数据格式不对!","警告",MB_OK|MB_ICONQUESTION);
    return;
    }
    code=(((DWORD)sztmp[0])<<24)+(((DWORD)sztmp[1])<<16)+(((DWORD)sztmp[2])<<8)+
    ((DWORD)sztmp[3]);

    if(strtodata((unsigned char*)szmask,sztmp,4,0)!=0)
    {
    MessageBox("屏蔽码数据格式不对!","警告",MB_OK|MB_ICONQUESTION);
    return;
    }
    mask=(((DWORD)sztmp[0])<<24)+(((DWORD)sztmp[1])<<16)+(((DWORD)sztmp[2])<<8)+
    ((DWORD)sztmp[3]);

    if(strtodata((unsigned char*)sztiming0,sztmp,1,0)!=0)
    {
    MessageBox("定时器0数据格式不对!","警告",MB_OK|MB_ICONQUESTION);
    return;
    }
    timing0=((DWORD)sztmp[0]);

    if(strtodata((unsigned char*)sztiming1,sztmp,1,0)!=0)
    {
    MessageBox("定时器1数据格式不对!","警告",MB_OK|MB_ICONQUESTION);
    return;
    }
    timing1=((DWORD)sztmp[0]);

    init_config.AccCode=code;
    init_config.AccMask=mask;
    init_config.Filter=filtertype;
    init_config.Mode=mode;
    init_config.Timing0=timing0;
    init_config.Timing1=timing1;

    if(VCI_OpenDevice(m_devtype,index,0)!=STATUS_OK)
    {
    MessageBox("打开设备失败!","警告",MB_OK|MB_ICONQUESTION);
    return;
    }
    if(VCI_InitCAN(m_devtype,index,cannum,&init_config)!=STATUS_OK)
    {
    MessageBox("初始化CAN失败!","警告",MB_OK|MB_ICONQUESTION);
    VCI_CloseDevice(m_devtype,index);
    return;
    }
    m_connect=1;
    m_devind=index;
    m_cannum=cannum;
    GetDlgItem(IDC_BUTTON_CONNECT)->SetWindowText("断开");
    // AfxBeginThread(ReceiveThread,this);//开始线程;
    }
    void CALLBACK fnTimerProc(UINT uID,UINT uMsg,DWORD dwUser,DWORD dw1,DWORD dw2)//多媒体定时器回掉函数

    CTestDlg * dlg;
       dlg=(CTestDlg *)(theApp.m_pMainWnd);  
       dlg->receive();///调用接受函数。
      
       sjtime++;   if(sjtime%1==0) 
      {
       dlg->send();
       }
    }
    int CTestDlg::receive()   //接受函数。
    { CTestDlg * dlg;
       dlg=(CTestDlg *)(theApp.m_pMainWnd);  
    CListBox *box=(CListBox *)dlg->GetDlgItem(IDC_LIST_INFO);
    VCI_CAN_OBJ frameinfo[50];
    VCI_ERR_INFO errinfo;
    int len=1;
    int i=0;
    CString str,tmpstr;
    // Sleep(1);
    if(dlg->m_connect==0)
           return(0);
    len=VCI_Receive(dlg->m_devtype,dlg->m_devind,dlg->m_cannum,frameinfo,5,0);
    if(len<=0)
    {
    //注意:如果没有读到数据则必须调用此函数来读取出当前的错误码,
    //千万不能省略这一步(即使你可能不想知道错误码是什么)
    VCI_ReadErrInfo(dlg->m_devtype,dlg->m_devind,dlg->m_cannum,&errinfo);
    }
    else
    {
    for(i=0;i<len;i++)
    {
    fprintf(dlg->fp,"%d ",dlg->receivetime);

    str="接收到数据帧:  ";
    if(frameinfo[i].TimeFlag==0)
    tmpstr="时间标识:无  ";
         else
    tmpstr.Format("时间标识:%08x ",frameinfo[i].TimeStamp);
    str+=tmpstr;
    tmpstr.Format("帧ID:%08x ",frameinfo[i].ID);
    str+=tmpstr;
    str+="帧格式:";
    if(frameinfo[i].RemoteFlag==0)
    tmpstr="数据帧 ";
    else
    tmpstr="远程帧 ";
    str+=tmpstr;
    str+="帧类型:";
    if(frameinfo[i].ExternFlag==0)
    tmpstr="标准帧 ";
    else
    tmpstr="扩展帧 ";
         str+=tmpstr;
    // box->InsertString(box->GetCount(),str);//不显示否则来不及
    fprintf(dlg->fp,"%s ",str);
    if(frameinfo[i].RemoteFlag==0)//若是数据就接受数据
    {
    str="数据:";
    if(frameinfo[i].DataLen>8)
    frameinfo[i].DataLen=8;
    for(int j=0;j<frameinfo[i].DataLen;j++)
    {
    tmpstr.Format("%02x ",frameinfo[i].Data[j]);
    str+=tmpstr;
    }
    //EnterCriticalSection(&(dlg->m_Section));
    //LeaveCriticalSection(&(dlg->m_Section));
    // box->InsertString(box->GetCount(),str);//不显示否则来不及
         fprintf(dlg->fp,"%s\n",str);//将收到的数据放到文件中。
    }
    if(frameinfo[i].RemoteFlag!=0)
    {  str="远程帧";
       fprintf(dlg->fp,"%s\n",str);
    }

        dlg->receivetime++;//receive 次数。
    }
    box->SetCurSel(box->GetCount()-1);
    }
    return(1);
    }
    void CTestDlg::send()
    { if(m_connect==0)
    return;
    VCI_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;// int i=0;    memcpy(&szFrameID[0],(LPCTSTR)sendid,8);//注意这种将CString 类型转化位char的方法。 strtodata((unsigned char*)szFrameID,FrameID,4,0); for(i=0;i<8;i++)//发送数据每一次都变化;
    {if(senddata[i]>0xff)
    senddata[i]=0;
    else senddata[i]++;} for(i=0;i<8;i++)
    {Data[i]=senddata[i];}//将发送数据放如临时的数组

    datalen=8;//每一帧数据长度; frameinfo.DataLen=datalen;//datalen; memcpy(&frameinfo.Data,Data,datalen);//将数据给帧。
    frameinfo.RemoteFlag=RemoteFlag_yes_no; //0为数据帧,1为远程帧//m_ComboSendFrmFmt.GetCurSel();
    frameinfo.ExternFlag=ExternFlag_yes_no; //0为标准帧,1为扩展帧//  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=Send_Type;//等于0时表示发送,1表示单次发送,2表示自发自收,3为单次自己发自己收m_ComboSendType.GetCurSel(); if(VCI_Transmit(m_devtype,m_devind,m_cannum,&frameinfo,1)==1)
    {
    ShowInfo("写入成功",0);

    }
    else
    {
    ShowInfo("写入失败",2);
    }
    }