python上位机调用CAN通信

简单介绍使用python来调用CAN通讯的DLL实现方法,以及使用过程中遇到的错误。这里使用的是沈阳广成科技有限公司的USBCAN接口卡,上位机调用他们提供一个ECanVci.dll文件,如下:

canDLL = ctypes.WinDLL(“D:/ECanVci.dll”) #调用can的dll文件,网上方法有很多种,这里是直接将dll文件放在D盘根目录。

为了方便实现CAN的通信,首先需要定义两个结构体,一个用来初始化CAN,一个用来存放CAN报文的信息,如下

  class VCI_INIT_CONFIG(Structure):
    _fields_=[("AccCode",c_ulong),
             ("AccMask",c_ulong),
             ("Reserved",c_ulong),             #初始化类型定义的这个函数类型,有要求
             ("Filter", c_ubyte),
             ("Timing0", c_ubyte),
             ("Timing1", c_ubyte),
             ("Mode",c_ubyte)
    ]

VCI_INIT_CONFIG结 构 体定义 ECAN 系 列 接 口 卡 的 初始化信息。
通过改变 Timing0 和 Timing1 的值来设定CAN的波特率。

class VCI_CAN_OBJ(Structure):
    _fields_ = [("ID", c_uint),
        ("TimeStamp", c_uint),
        ("TimeFlag", c_ubyte),
        ("SendType", c_ubyte),
        ("RemoteFlag", c_ubyte),
        ("ExternFlag", c_ubyte),
        ("DataLen", c_ubyte),
        ("Data", c_ubyte*8),
        ("Reserved", c_ubyte*3)
        ]

VCI_CAN_OBJ结构体表示帧的数据结构。在发送函数Transmit和接收函数Receive中被用来传送CAN信息帧。结构体的具体定义如下:

ID:报文帧ID。

TimeStamp:接收到信息帧时的时间标识,从CAN控制器初始化开始计时,单位微秒。

TimeFlag:是否使用时间标识,为1时TimeStamp有效,TimeFlag和TimeStamp只在此帧为接收帧时有意义。

SendType:发送帧类型。=0时为正常发送,=1时为单次发送(不自动重发),=2时为自发自收(用于测试CAN卡是否损坏),=3时为单次自发自收(只发送一次,用于自测试),只在此帧为发送帧时有意义。

RemoteFlag:是否是远程帧。=0时为数据帧,=1时为远程帧。

ExternFlag:是否是扩展帧。=0时为标准帧(11位帧ID),=1时为扩展帧(29位帧ID)。

DataLen:数据长度DLC(<=8),即Data的长度。

Data:CAN报文的数据。空间受DataLen的约束。

Reserved:系统保留。

具体的CAN收发函数调用如下:

发送函数:

Transmit:返回实际发送成功的帧数量。

mta = VCI_CAN_OBJ()
                    mta.ID = 0x100
                    mta.TimeStamp = 0
                    mta.TimeFlag = 0
                    mta.SendType = 0
                    mta.RemoteFlag = 0
                    mta.ExternFlag = 0
                    mta.DataLen = 8
                    mta.Data = (0x00, 0x01, 0x02, 0x03,0x04,0x05,0x06,0x07)
                    transmit = canDLL.Transmit(self.nDeviceType, self.nDeviceInd, self.nCANInd, byref(mta), 1)

Transmit(DWORD DevType, DWORD DevIndex, DWORD CANIndex,P_CAN_OBJ pSend, ULONG Len);
DevType:设备类型号。
DevIndex:设备索引号,比如当只有一个设备时,索引号为0,有两个时可以为0或1。
CANIndex:第几路CAN。
pSend:要发送的数据帧数组的首指针。
Len:要发送的数据帧数组的长度。
返回值:返回实际发送的帧数。

接受函数:

Receive:此函数从指定的设备CAN通道的缓冲区里读取数据。

dto = VCI_CAN_OBJ()
        dto.ID = 0x101
        dto.TimeStamp = 0
        dto.TimeFlag = 0
        dto.SendType = 0
        dto.RemoteFlag = 0
        dto.ExternFlag = 0
        dto.DataLen = 8
        dto.Data = (0,0,0,0,0,0,0,0)

        receive = canDLL.Receive(self.nDeviceType, self.nDeviceInd, self.nCANInd, byref(dto), 1,10)

byref(dto):将接受到的帧信息存放在结构体dto中
1:表示接受的数据帧长度
10:等待超时时间,以毫秒为单位。

遇到的错误:

1、
receive = canDLL.Receive(self.nDeviceType, self.nDeviceInd, self.nCANInd,byref(dto), 100,400)
将接受到的数据帧长度改为100时,当CAN总线上持续有CAN报文传输时,数组将会溢出,上位机直接卡退。

你可能感兴趣的:(python,c++)