基于CAN总线的汽车诊断协议UDS(上位机开发驱动篇)
本篇作为UDS上位机的驱动开发篇,从市面上多见的CAN分析仪着手介绍UDS上位机驱动开发和移植的一般过程,目的是使UDS上位机软件能适应多家CAN分析仪,降低使用者的硬件成本。
一:广成CAN分析仪的驱动开发
首先创建ECANDLL类,从广成提供的二次开发包中获取ECANVCI.dll文件,将DLL文件放置与生成程序的目录中,如下类中创建了CAN常用的控制函数。
public static class ECANDLL
{
[DllImport("ECANVCI.dll", EntryPoint = "OpenDevice")]
public static extern ECANStatus OpenDevice(
UInt32 DeviceType,
UInt32 DeviceInd,
UInt32 Reserved);
[DllImport("ECANVCI.dll", EntryPoint = "CloseDevice")]
public static extern ECANStatus CloseDevice(
UInt32 DeviceType,
UInt32 DeviceInd);
[DllImport("ECANVCI.dll", EntryPoint = "InitCAN")]
public static extern ECANStatus InitCAN(
UInt32 DeviceType,
UInt32 DeviceInd,
UInt32 CANInd,
ref INIT_CONFIG InitConfig);
[DllImport("ECANVCI.dll", EntryPoint = "StartCAN")]
public static extern ECANStatus StartCAN(
UInt32 DeviceType,
UInt32 DeviceInd,
UInt32 CANInd);
[DllImport("ECANVCI.dll", EntryPoint = "ResetCAN")]
public static extern ECANStatus ResetCAN(
UInt32 DeviceType,
UInt32 DeviceInd,
UInt32 CANInd);
[DllImport("ECANVCI.dll", EntryPoint = "Transmit")]
public static extern ECANStatus Transmit(
UInt32 DeviceType,
UInt32 DeviceInd,
UInt32 CANInd,
ref CAN_OBJ Send,
UInt16 length);
[DllImport("ECANVCI.dll", EntryPoint = "Receive")]
public static extern ECANStatus Receive(
UInt32 DeviceType,
UInt32 DeviceInd,
UInt32 CANInd,
out CAN_OBJ Receive,
UInt32 length,
UInt32 WaitTime);
[DllImport("ECANVCI.dll", EntryPoint = "ReadErrInfo")]
public static extern ECANStatus ReadErrInfo(
UInt32 DeviceType,
UInt32 DeviceInd,
UInt32 CANInd,
out CAN_ERR_INFO ReadErrInfo);
}
在MainForm中,针对不同的控件调用不同的控制函数
如初始化:
INIT_CONFIG init_config = new INIT_CONFIG();
init_config.AccCode = 0;
init_config.AccMask = 0xffffff;
init_config.Filter = 0;
switch (m_Baudrate)
{
case 0: //1000
init_config.Timing0 = 0;
init_config.Timing1 = 0x14;
break;
case 1: //800
init_config.Timing0 = 0;
init_config.Timing1 = 0x16;
break;
case 2: //666
init_config.Timing0 = 0x80;
init_config.Timing1 = 0xb6;
break;
case 3: //500
init_config.Timing0 = 0;
init_config.Timing1 = 0x1c;
break;
case 4://400
init_config.Timing0 = 0x80;
init_config.Timing1 = 0xfa;
break;
case 5://250
init_config.Timing0 = 0x01;
init_config.Timing1 = 0x1c;
break;
case 6://200
init_config.Timing0 = 0x81;
init_config.Timing1 = 0xfa;
break;
case 7://125
init_config.Timing0 = 0x03;
init_config.Timing1 = 0x1c;
break;
case 8://100
init_config.Timing0 = 0x04;
init_config.Timing1 = 0x1c;
break;
case 9://80
init_config.Timing0 = 0x83;
init_config.Timing1 = 0xff;
break;
case 10://50
init_config.Timing0 = 0x09;
init_config.Timing1 = 0x1c;
break;
}
init_config.Mode = 0;
if (ECANDLL.OpenDevice(m_devtype, m_devind, 0) != ECAN.ECANStatus.STATUS_OK)
{
MessageBox.Show("Open device fault!", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
//Set can1 baud
if (ECANDLL.InitCAN(m_devtype, m_devind, 0, ref init_config) != ECAN.ECANStatus.STATUS_OK)
{
MessageBox.Show("Init can fault!", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
ECANDLL.CloseDevice(1, 0);
return;
}
二:周立功CAN分析仪驱动开发
周立功的CAN分析仪与广成基本相同,将DLL文件替换为周立功的DLL文件。在初始化和其他调用函数中注意m_devtype和m_devind与广成的不同,这两个变量的取值可通过不同厂家的测试软件中获取。
一般的广成m_devtype =1,m_devind=0,周立功USBCAN II m_devtype =4,m_devind=0.
ECANDLL.OpenDevice(m_devtype, m_devind, 0)
三:Kvaser CAN分析仪驱动开发
Kvaser CAN驱动开发与上述两者差别较大。
首先引入驱动DLL文件
以下是初始化过程
int hnd = Canlib.canOpenChannel(channel, Canlib.canOPEN_ACCEPT_VIRTUAL);
CheckStatus("Open channel", (Canlib.canStatus)hnd);
if (hnd >= 0)
{
handle = hnd;
}
int[] bitrates = new int[] {
Canlib.BAUD_1M,
Canlib.BAUD_500K,
Canlib.BAUD_250K,
Canlib.BAUD_125K,
Canlib.BAUD_100K,
Canlib.BAUD_83K,
Canlib.BAUD_62K,
Canlib.BAUD_50K,
};
int bitrate = bitrates[comboBoxBaud.SelectedIndex];
Canlib.canStatus status = Canlib.canSetBusParams(handle, bitrate, 0, 0, 0, 0, 0);
CheckStatus("Setting bitrate to " + comboBoxBaud.SelectedItem, status);
Canlib.canBusOn(handle);
CheckStatus("Bus on", status);
if (status == Canlib.canStatus.canOK)
{
onBus = true;
/*
if (!dumper.IsBusy)
{
dumper.RunWorkerAsync();
}*/
}
写CAN报文函数
Canlib.canStatus status = Canlib.canWrite(handle, id, dat, dlc, flags);
读CAN报文函数
status = Canlib.canReadWait(handle, out id, dat, out dlc, out flags, out time, 50);