创新can调试器Linux版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
5.5 KiB

4 years ago
  1. from ctypes import *
  2. import logging
  3. import platform
  4. from can import BusABC, Message
  5. logger = logging.getLogger(__name__)
  6. class VCI_INIT_CONFIG(Structure):
  7. _fields_ = [("AccCode", c_int32),
  8. ("AccMask", c_int32),
  9. ("Reserved", c_int32),
  10. ("Filter", c_ubyte),
  11. ("Timing0", c_ubyte),
  12. ("Timing1", c_ubyte),
  13. ("Mode", c_ubyte)]
  14. class VCI_CAN_OBJ(Structure):
  15. _fields_ = [("ID", c_uint),
  16. ("TimeStamp", c_int),
  17. ("TimeFlag", c_byte),
  18. ("SendType", c_byte),
  19. ("RemoteFlag", c_byte),
  20. ("ExternFlag", c_byte),
  21. ("DataLen", c_byte),
  22. ("Data", c_ubyte * 8),
  23. ("Reserved", c_byte * 3)]
  24. VCI_USBCAN2 = 4
  25. STATUS_OK = 0x01
  26. STATUS_ERR = 0x00
  27. TIMING_DICT = {
  28. 5000: (0xBF, 0xFF),
  29. 10000: (0x31, 0x1C),
  30. 20000: (0x18, 0x1C),
  31. 33330: (0x09, 0x6F),
  32. 40000: (0x87, 0xFF),
  33. 50000: (0x09, 0x1C),
  34. 66660: (0x04, 0x6F),
  35. 80000: (0x83, 0xFF),
  36. 83330: (0x03, 0x6F),
  37. 100000: (0x04, 0x1C),
  38. 125000: (0x03, 0x1C),
  39. 200000: (0x81, 0xFA),
  40. 250000: (0x01, 0x1C),
  41. 400000: (0x80, 0xFA),
  42. 500000: (0x00, 0x1C),
  43. 666000: (0x80, 0xB6),
  44. 800000: (0x00, 0x16),
  45. 1000000: (0x00, 0x14),
  46. }
  47. try:
  48. if platform.system() == "Windows":
  49. CANalystII = WinDLL("./ControlCAN.dll")
  50. else:
  51. CANalystII = CDLL("./libcontrolcan.so")
  52. logger.info("Loaded CANalystII library")
  53. except OSError as e:
  54. CANalystII = None
  55. logger.info("Cannot load CANalystII library")
  56. class CANalystIIBus(BusABC):
  57. def __init__(self, channel, bitrate=None, Timing0=None, Timing1=None, can_filters=None):
  58. # def __init__(self, channel, device=0, bitrate=None, Timing0=None, Timing1=None, can_filters=None):
  59. """
  60. :param channel: channel number
  61. :param device: device number
  62. :param bitrate: bitrate rate
  63. :param Timing0: customize the timing register if bitrate is not specified
  64. :param Timing1:
  65. :param can_filters: filters for packet
  66. """
  67. super(CANalystIIBus, self).__init__(channel, can_filters)
  68. if isinstance(channel, (list, tuple)):
  69. self.channels = channel
  70. elif isinstance(channel, int):
  71. self.channels = [channel]
  72. else:
  73. # Assume comma separated string of channels
  74. self.channels = [int(ch.strip()) for ch in channel.split(',')]
  75. # self.device = device
  76. # self.channel_info = "CANalyst-II: device {}, channels {}".format(self.device, self.channels)
  77. self.channel_info = "CANalyst-II: channels {}".format(self.channels)
  78. bitrate = int(bitrate)
  79. if bitrate is not None:
  80. try:
  81. Timing0, Timing1 = TIMING_DICT[bitrate]
  82. except KeyError:
  83. raise ValueError("bitrate is not supported")
  84. if Timing0 is None or Timing1 is None:
  85. raise ValueError("Timing registers are not set")
  86. self.init_config = VCI_INIT_CONFIG(0x80000008, 0xFFFFFFFF, 0, 1, Timing0, Timing1, 0)
  87. if CANalystII.VCI_OpenDevice(VCI_USBCAN2, 0, 0) == STATUS_ERR:
  88. logger.error("VCI_OpenDevice Error")
  89. for channel in self.channels:
  90. if CANalystII.VCI_InitCAN(VCI_USBCAN2, 0, channel, byref(self.init_config)) == STATUS_ERR:
  91. logger.error("VCI_InitCAN Error")
  92. self.shutdown()
  93. return
  94. if CANalystII.VCI_ClearBuffer(VCI_USBCAN2, 0, channel) ==STATUS_ERR:
  95. logger.error("VCI_ClearBuffer Error")
  96. self.shutdown()
  97. return
  98. if CANalystII.VCI_StartCAN(VCI_USBCAN2, 0, channel) == STATUS_ERR:
  99. logger.error("VCI_StartCAN Error")
  100. self.shutdown()
  101. return
  102. def send(self, msg, timeout=None):
  103. """
  104. :param msg: message to send
  105. :param timeout: timeout is not used here
  106. :return:
  107. """
  108. extern_flag = 1 if msg.is_extended_id else 0
  109. raw_message = VCI_CAN_OBJ(msg.arbitration_id, 0, 0, 0, msg.is_remote_frame, extern_flag, msg.dlc, (c_ubyte * 8)(*msg.data), (c_byte * 3)(*[0, 0, 0]))
  110. if msg.channel is not None:
  111. channel = msg.channel
  112. elif len(self.channels) == 1:
  113. channel = self.channels[0]
  114. else:
  115. raise ValueError(
  116. "msg.channel must be set when using multiple channels.")
  117. CANalystII.VCI_Transmit(VCI_USBCAN2, 0 , channel, byref(raw_message), 1)
  118. def _recv_internal(self, timeout=None):
  119. """
  120. :param timeout: float in seconds
  121. :return:
  122. """
  123. raw_message = VCI_CAN_OBJ()
  124. timeout = -1 if timeout is None else int(timeout * 1000)
  125. if CANalystII.VCI_Receive(VCI_USBCAN2, 0, self.channels[0], byref(raw_message), 1, timeout) <= STATUS_ERR:
  126. return None, False
  127. else:
  128. return (
  129. Message(
  130. timestamp=raw_message.TimeStamp if raw_message.TimeFlag else 0.0,
  131. arbitration_id=raw_message.ID,
  132. is_remote_frame=raw_message.RemoteFlag,
  133. channel=0,
  134. dlc=raw_message.DataLen,
  135. data=raw_message.Data,
  136. ),
  137. False,
  138. )
  139. def flush_tx_buffer(self):
  140. for channel in self.channels:
  141. CANalystII.VCI_ClearBuffer(VCI_USBCAN2, 0, channel)
  142. def shutdown(self):
  143. CANalystII.VCI_CloseDevice(VCI_USBCAN2, 0)