?? unit1.cpp
字號:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
/*
下面是具體的調用動態庫的做法,采用的是動態加載的方法,主要就是在程序初始化的
時候從動態庫中取得各個函數的地址并保存起來,然后在需要的時候調用就可以了,最后在
程序退出的時候釋放掉打開的動態庫句柄就行。
*/
//首先定義需要用到的數據結構
//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;
//接下來定義要導入的函數類型
//根據ControlCAN.h中的函數聲明定義函數指針類型
//////////////////////////////////////////////////////////////////////////
typedef DWORD (CALLBACK* LPVCI_OpenDevice)(DWORD,DWORD,DWORD);
typedef DWORD (CALLBACK* LPVCI_CloseDevice)(DWORD,DWORD);
typedef DWORD (CALLBACK* LPVCI_InitCan)(DWORD,DWORD,DWORD,PVCI_INIT_CONFIG);
typedef DWORD (CALLBACK* LPVCI_ReadBoardInfo)(DWORD,DWORD,PVCI_BOARD_INFO);
typedef DWORD (CALLBACK* LPVCI_ReadErrInfo)(DWORD,DWORD,DWORD,PVCI_ERR_INFO);
typedef DWORD (CALLBACK* LPVCI_ReadCanStatus)(DWORD,DWORD,DWORD,PVCI_CAN_STATUS);
typedef DWORD (CALLBACK* LPVCI_GetReference)(DWORD,DWORD,DWORD,DWORD,PVOID);
typedef DWORD (CALLBACK* LPVCI_SetReference)(DWORD,DWORD,DWORD,DWORD,PVOID);
typedef ULONG (CALLBACK* LPVCI_GetReceiveNum)(DWORD,DWORD,DWORD);
typedef DWORD (CALLBACK* LPVCI_ClearBuffer)(DWORD,DWORD,DWORD);
typedef DWORD (CALLBACK* LPVCI_StartCAN)(DWORD,DWORD,DWORD);
typedef DWORD (CALLBACK* LPVCI_ResetCAN)(DWORD,DWORD,DWORD);
typedef ULONG (CALLBACK* LPVCI_Transmit)(DWORD,DWORD,DWORD,PVCI_CAN_OBJ,ULONG);
typedef ULONG (CALLBACK* LPVCI_Receive)(DWORD,DWORD,DWORD,PVCI_CAN_OBJ,ULONG,INT);
//////////////////////////////////////////////////////////////////////////
HANDLE m_hDLL;//用來保存打開的動態庫句柄
//接口函數指針
LPVCI_OpenDevice VCI_OpenDevice;
LPVCI_CloseDevice VCI_CloseDevice;
LPVCI_InitCan VCI_InitCAN;
LPVCI_ReadBoardInfo VCI_ReadBoardInfo;
LPVCI_ReadErrInfo VCI_ReadErrInfo;
LPVCI_ReadCanStatus VCI_ReadCanStatus;
LPVCI_GetReference VCI_GetReference;
LPVCI_SetReference VCI_SetReference;
LPVCI_GetReceiveNum VCI_GetReceiveNum;
LPVCI_ClearBuffer VCI_ClearBuffer;
LPVCI_StartCAN VCI_StartCAN;
LPVCI_ResetCAN VCI_ResetCAN;
LPVCI_Transmit VCI_Transmit;
LPVCI_Receive VCI_Receive;
////////////////////////////////////////////////////////////////////////////
DWORD m_devtype=5;//PCI9820類型號
DWORD m_devind=0;
DWORD m_cannum=0;
int m_connect=0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
m_hDLL = LoadLibrary("ControlCAN.dll");//打開動態庫
//取得函數地址
VCI_OpenDevice=(LPVCI_OpenDevice)GetProcAddress(m_hDLL,"VCI_OpenDevice");
VCI_CloseDevice=(LPVCI_CloseDevice)GetProcAddress(m_hDLL,"VCI_CloseDevice");
VCI_InitCAN=(LPVCI_InitCan)GetProcAddress(m_hDLL,"VCI_InitCAN");
VCI_ReadBoardInfo=(LPVCI_ReadBoardInfo)GetProcAddress(m_hDLL,"VCI_ReadBoardInfo");
VCI_ReadErrInfo=(LPVCI_ReadErrInfo)GetProcAddress(m_hDLL,"VCI_ReadErrInfo");
VCI_ReadCanStatus=(LPVCI_ReadCanStatus)GetProcAddress(m_hDLL,"VCI_ReadCANStatus");
VCI_GetReference=(LPVCI_GetReference)GetProcAddress(m_hDLL,"VCI_GetReference");
VCI_SetReference=(LPVCI_SetReference)GetProcAddress(m_hDLL,"VCI_SetReference");
VCI_GetReceiveNum=(LPVCI_GetReceiveNum)GetProcAddress(m_hDLL,"VCI_GetReceiveNum");
VCI_ClearBuffer=(LPVCI_ClearBuffer)GetProcAddress(m_hDLL,"VCI_ClearBuffer");
VCI_StartCAN=(LPVCI_StartCAN)GetProcAddress(m_hDLL,"VCI_StartCAN");
VCI_ResetCAN=(LPVCI_ResetCAN)GetProcAddress(m_hDLL,"VCI_ResetCAN");
VCI_Transmit=(LPVCI_Transmit)GetProcAddress(m_hDLL,"VCI_Transmit");
VCI_Receive=(LPVCI_Receive)GetProcAddress(m_hDLL,"VCI_Receive");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
if(m_connect==1)
{
m_connect=0;
WaitForSingleObject(m_readhandle,2000);
m_readhandle=NULL;
VCI_CloseDevice(m_devtype,m_devind);
}
FreeLibrary(m_hDLL);//釋放動態庫句柄
}
//---------------------------------------------------------------------------
void ReceiveThread(void *param)
{
TListBox *box=(TListBox*)param;
VCI_CAN_OBJ receivedata[50];
VCI_ERR_INFO errinfo;
int len,i;
AnsiString str,tmpstr;
while(1)
{
if(m_connect==0)
break;
Sleep(1);
len=VCI_Receive(m_devtype,m_devind,m_cannum,receivedata,50,200);
if(len<=0)
{
//注意:如果沒有讀到數據則必須調用此函數來讀取出當前的錯誤碼,
//千萬不能省略這一步(即使你可能不想知道錯誤碼是什么)
VCI_ReadErrInfo(m_devtype,m_devind,m_cannum,&errinfo);
}
else
{
for(i=0;i<len;i++)
{
str="接收到數據幀: ";
if(receivedata[i].TimeFlag==0)
tmpstr="時間標識:無 ";
else
tmpstr="時間標識:0x"+IntToHex((int)receivedata[i].TimeStamp,8)+" ";
str+=tmpstr;
tmpstr="幀ID:0x"+IntToHex((int)receivedata[i].ID,8)+" ";
str+=tmpstr;
str+="幀格式:";
if(receivedata[i].RemoteFlag==0)
tmpstr="數據幀 ";
else
tmpstr="遠程幀 ";
str+=tmpstr;
str+="幀類型:";
if(receivedata[i].ExternFlag==0)
tmpstr="標準幀 ";
else
tmpstr="擴展幀 ";
str+=tmpstr;
box->Items->Add(str);
if(receivedata[i].RemoteFlag==0)
{
str="數據:";
if(receivedata[i].DataLen>8)
receivedata[i].DataLen=8;
for(int j=0;j<receivedata[i].DataLen;j++)
{
tmpstr=IntToHex((int)receivedata[i].Data[j],2)+" ";
str+=tmpstr;
}
box->Items->Add(str);
}
}
box->ItemIndex=box->Items->Count-1;
}
}
_endthread();
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(m_connect==1)
{
Button1->Caption ="連接";
m_connect=0;
WaitForSingleObject(m_readhandle,2000);
m_readhandle=NULL;
VCI_CloseDevice(m_devtype,m_devind);
return;
}
int index = ComboBox1->ItemIndex;
int cannum = ComboBox2->ItemIndex;
VCI_INIT_CONFIG initconfig;
initconfig.AccCode=StrToInt("0x"+Edit2->Text);
initconfig.AccMask=StrToInt("0x"+Edit3->Text);
initconfig.Timing0=StrToInt("0x"+Edit5->Text);
initconfig.Timing1=StrToInt("0x"+Edit6->Text);
initconfig.Filter=ComboBox3->ItemIndex;
initconfig.Mode=ComboBox4->ItemIndex;
if(index>=0&&cannum>=0)
{
if(VCI_OpenDevice(m_devtype,index,0)==1)
{
if(VCI_InitCAN(m_devtype,index,cannum,&initconfig)==1)
{
Button1->Caption ="斷開";
m_connect=1;
m_devind=index;
m_cannum=cannum;
m_readhandle=(HANDLE)_beginthread(ReceiveThread,0,(void*)ListBox1);
}
else
{
ShowMessage("初始化CAN錯誤");
}
}
else
{
ShowMessage("打開端口錯誤");
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
if(m_connect==0)
{
ShowMessage("請先打開端口");
return;
}
if(VCI_ResetCAN(m_devtype,m_devind,m_cannum)==1)
{
ListBox1->Items->Add("復位CAN成功");
}
else
{
ListBox1->Items->Add("復位CAN失敗");
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
if(m_connect==0)
{
ShowMessage("請先打開端口");
return;
}
if(VCI_StartCAN(m_devtype,m_devind,m_cannum)==1)
{
ListBox1->Items->Add("啟動CAN成功");
}
else
{
ListBox1->Items->Add("啟動CAN失敗");
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button6Click(TObject *Sender)
{
if(m_connect==0)
{
ShowMessage("請先打開端口");
return;
}
DWORD i= ComboBox3->ItemIndex;
if(VCI_SetReference(m_devtype,m_devind,0,1,(PVOID)&i)==1)
{
ListBox1->Items->Add("更改成功");
}
else
{
ListBox1->Items->Add("更改失敗");
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
ComboBox1->ItemIndex = 0;
ComboBox2->ItemIndex = 0;
ComboBox3->ItemIndex = 0;
ComboBox4->ItemIndex = 0;
ComboBox5->ItemIndex = 2;
ComboBox6->ItemIndex =0;
ComboBox7->ItemIndex =0;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
if(m_connect==0)
{
ShowMessage("請先打開端口");
return;
}
BYTE sendtype,frametype,frameformat;
DWORD id;
BYTE data[8];
sendtype=ComboBox5->ItemIndex;
frametype=ComboBox6->ItemIndex;
frameformat=ComboBox7->ItemIndex;
id=StrToInt("0x"+Edit1->Text);
AnsiString str=Edit4->Text;
AnsiString strdata;
int i,kkk;
for(i=0;i<8;i++)
{
strdata=str.SubString(3*i+1,2);
strdata=strdata.Trim();
kkk=strdata.Length();
if(kkk==0)
{
goto exit;
}
data[i]=StrToInt(strdata);
//sscanf(strdata.c_str(),"%x",data+i);
}
exit:
VCI_CAN_OBJ senddata;
senddata.SendType=sendtype;
senddata.ExternFlag=frametype;
senddata.RemoteFlag=frameformat;
senddata.ID=id;
senddata.DataLen=i;
memcpy(senddata.Data,data,i);
if(VCI_Transmit(m_devtype,m_devind,m_cannum,&senddata,1)==1)
{
ListBox1->Items->Add("發送成功");
}
else
{
ListBox1->Items->Add("發送失敗");
}
}
//---------------------------------------------------------------------------
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -