CanHelper.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. using ProjectBase.Data.Logs;
  2. using System;
  3. using System.Text;
  4. /// <summary>
  5. /// Inclusion of PEAK PCAN-Basic namespace
  6. /// </summary>
  7. using TPCANHandle = System.UInt16;
  8. using TPCANBitrateFD = System.String;
  9. using TPCANTimestampFD = System.UInt64;
  10. namespace SIASUN.Autopilot.Device
  11. {
  12. public class CanHelper : ICanHelper
  13. {
  14. #region Delegates
  15. /// <summary>
  16. /// Read-Delegate Handler
  17. /// </summary>
  18. //private delegate void ReadDelegateHandler();
  19. #endregion
  20. #region Members
  21. /// <summary>
  22. /// Saves the desired connection mode
  23. /// </summary>
  24. private bool m_IsFD = false;
  25. /// <summary>
  26. /// Saves the handle of a PCAN hardware
  27. /// </summary>
  28. private TPCANHandle m_PcanHandle;
  29. /// <summary>
  30. /// Saves the baudrate register for a conenction
  31. /// </summary>
  32. private TPCANBaudrate m_Baudrate;
  33. /// <summary>
  34. /// Saves the type of a non-plug-and-play hardware
  35. /// </summary>
  36. private TPCANType m_HwType;
  37. /// <summary>
  38. /// Stores the status of received messages for its display
  39. /// </summary>
  40. private System.Collections.ArrayList m_LastMsgsList;
  41. /// <summary>
  42. /// Read Delegate for calling the function "ReadMessages"
  43. /// </summary>
  44. //private ReadDelegateHandler m_ReadDelegate;
  45. /// <summary>
  46. /// Receive-Event
  47. /// </summary>
  48. private System.Threading.AutoResetEvent m_ReceiveEvent;
  49. /// <summary>
  50. /// Thread for message reading (using events)
  51. /// </summary>
  52. private System.Threading.Thread m_ReadThread;
  53. /// <summary>
  54. /// Handles of non plug and play PCAN-Hardware
  55. /// </summary>
  56. private TPCANHandle[] m_NonPnPHandles;
  57. /// <summary>
  58. /// MessageType is extend or standard
  59. /// </summary>
  60. private bool bExtend = false;
  61. private bool bFD = false;
  62. private bool bBRS = false;
  63. private bool bRemote = false;
  64. public CanHelper()
  65. {
  66. // Creates the list for received messages
  67. //
  68. //m_LastMsgsList = new System.Collections.ArrayList();
  69. // Creates the delegate used for message reading
  70. //
  71. //m_ReadDelegate = new ReadDelegateHandler(ReadMessages);
  72. // Creates the event used for signalize incomming messages
  73. //
  74. m_ReceiveEvent = new System.Threading.AutoResetEvent(false);
  75. }
  76. #endregion
  77. /// <summary>
  78. /// 初始化can总线
  79. /// </summary>
  80. public void Initialize()
  81. {
  82. try
  83. {
  84. string IOCan = System.Configuration.ConfigurationManager.AppSettings["IO_CAN"];
  85. string Interrupt = System.Configuration.ConfigurationManager.AppSettings["Interrupt_CAN"];
  86. setBaudrate();
  87. setCANHandle();
  88. setHardWareType();
  89. TPCANStatus stsResult;
  90. // Connects a selected PCAN-Basic channel
  91. stsResult = PCANBasic.Initialize(
  92. m_PcanHandle,
  93. m_Baudrate,
  94. m_HwType,
  95. Convert.ToUInt32(IOCan, 16),
  96. Convert.ToUInt16(Interrupt));
  97. if (stsResult != TPCANStatus.PCAN_ERROR_OK)
  98. LogHelper.log.Error(GetFormatedError(stsResult));
  99. else
  100. // Prepares the PCAN-Basic's PCAN-Trace file
  101. //
  102. ConfigureTraceFile();
  103. // Sets the connection status of the main-form
  104. //
  105. SetConnectionStatus(stsResult == TPCANStatus.PCAN_ERROR_OK);
  106. }
  107. catch (Exception ex)
  108. {
  109. LogHelper.log.Error("can总线初始化失败。", ex);
  110. }
  111. }
  112. /// <summary>
  113. /// Activates/deaactivates the different controls of the main-form according
  114. /// with the current connection status
  115. /// </summary>
  116. /// <param name="bConnected">Current status. True if connected, false otherwise</param>
  117. private void SetConnectionStatus(bool bConnected)
  118. {
  119. if (!bConnected)
  120. {
  121. LogHelper.log.Debug("can总线未连接成功");
  122. }
  123. else
  124. {
  125. // Create and start the tread to read CAN Message using SetRcvEvent()
  126. //
  127. System.Threading.ThreadStart threadDelegate = new System.Threading.ThreadStart(this.CANReadThreadFunc);
  128. m_ReadThread = new System.Threading.Thread(threadDelegate);
  129. m_ReadThread.IsBackground = true;
  130. m_ReadThread.Start();
  131. }
  132. }
  133. /// <summary>
  134. /// Thread-Function used for reading PCAN-Basic messages
  135. /// </summary>
  136. private void CANReadThreadFunc()
  137. {
  138. UInt32 iBuffer;
  139. TPCANStatus stsResult;
  140. iBuffer = Convert.ToUInt32(m_ReceiveEvent.SafeWaitHandle.DangerousGetHandle().ToInt32());
  141. // Sets the handle of the Receive-Event.
  142. //
  143. stsResult = PCANBasic.SetValue(m_PcanHandle, TPCANParameter.PCAN_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));
  144. if (stsResult != TPCANStatus.PCAN_ERROR_OK)
  145. {
  146. LogHelper.log.Error(GetFormatedError(stsResult));
  147. return;
  148. }
  149. // While this mode is selected
  150. while (true)
  151. {
  152. // Waiting for Receive-Event
  153. //
  154. if (m_ReceiveEvent.WaitOne(50))
  155. ReadMessages();
  156. }
  157. }
  158. /// <summary>
  159. /// Function for reading PCAN-Basic messages
  160. /// </summary>
  161. private void ReadMessages()
  162. {
  163. TPCANStatus stsResult;
  164. // We read at least one time the queue looking for messages.
  165. // If a message is found, we look again trying to find more.
  166. // If the queue is empty or an error occurr, we get out from
  167. // the dowhile statement.
  168. do
  169. {
  170. stsResult = m_IsFD ? ReadMessageFD() : ReadMessage();
  171. if (stsResult == TPCANStatus.PCAN_ERROR_ILLOPERATION)
  172. break;
  173. } while (!Convert.ToBoolean(stsResult & TPCANStatus.PCAN_ERROR_QRCVEMPTY));
  174. }
  175. /// <summary>
  176. /// Function for reading messages on FD devices
  177. /// </summary>
  178. /// <returns>A TPCANStatus error code</returns>
  179. private TPCANStatus ReadMessageFD()
  180. {
  181. TPCANMsgFD CANMsg;
  182. TPCANTimestampFD CANTimeStamp;
  183. TPCANStatus stsResult;
  184. // We execute the "Read" function of the PCANBasic
  185. //
  186. stsResult = PCANBasic.ReadFD(m_PcanHandle, out CANMsg, out CANTimeStamp);
  187. if (stsResult != TPCANStatus.PCAN_ERROR_QRCVEMPTY)
  188. // We process the received message
  189. //
  190. ProcessMessage(CANMsg, CANTimeStamp);
  191. return stsResult;
  192. }
  193. /// <summary>
  194. /// Function for reading CAN messages on normal CAN devices
  195. /// </summary>
  196. /// <returns>A TPCANStatus error code</returns>
  197. private TPCANStatus ReadMessage()
  198. {
  199. TPCANMsg CANMsg;
  200. TPCANTimestamp CANTimeStamp;
  201. TPCANStatus stsResult;
  202. // We execute the "Read" function of the PCANBasic
  203. //
  204. stsResult = PCANBasic.Read(m_PcanHandle, out CANMsg, out CANTimeStamp);
  205. if (stsResult != TPCANStatus.PCAN_ERROR_QRCVEMPTY)
  206. // We process the received message
  207. //
  208. ProcessMessage(CANMsg, CANTimeStamp);
  209. return stsResult;
  210. }
  211. /// <summary>
  212. /// Processes a received message, in order to convert to bll
  213. /// </summary>
  214. /// <param name="theMsg">The received PCAN-Basic message</param>
  215. /// <returns>True if the message must be created, false if it must be modified</returns>
  216. private void ProcessMessage(TPCANMsg theMsg, TPCANTimestamp itsTimeStamp)
  217. {
  218. TPCANMsgFD newMsg;
  219. TPCANTimestampFD newTimestamp;
  220. newMsg = new TPCANMsgFD();
  221. newMsg.DATA = new byte[64];
  222. newMsg.ID = theMsg.ID;
  223. newMsg.DLC = theMsg.LEN;
  224. for (int i = 0; i < ((theMsg.LEN > 8) ? 8 : theMsg.LEN); i++)
  225. newMsg.DATA[i] = theMsg.DATA[i];
  226. newMsg.MSGTYPE = theMsg.MSGTYPE;
  227. newTimestamp = Convert.ToUInt64(itsTimeStamp.micros + 1000 * itsTimeStamp.millis + 0x100000000 * 1000 * itsTimeStamp.millis_overflow);
  228. ProcessMessage(newMsg, newTimestamp);
  229. }
  230. /// <summary>
  231. /// Processes a received message, in order to show it in the Message-ListView
  232. /// </summary>
  233. /// <param name="theMsg">The received PCAN-Basic message</param>
  234. /// <returns>True if the message must be created, false if it must be modified</returns>
  235. private void ProcessMessage(TPCANMsgFD theMsg, TPCANTimestampFD itsTimeStamp)
  236. {
  237. MessageStatus msgStsCurrentMsg;
  238. msgStsCurrentMsg = new MessageStatus(theMsg, itsTimeStamp);
  239. // 拆包
  240. Package_Data_Msg<object> rp = new Package_Data_Msg<object>();
  241. object up = rp.UnPackage(msgStsCurrentMsg.IdString, msgStsCurrentMsg.CANMsg.DATA);
  242. // 将事件加入委托链
  243. EventManage.Instance.RaiseEvent(msgStsCurrentMsg.IdString, rp.Message);
  244. }
  245. /// <summary>
  246. /// 断开连接
  247. /// </summary>
  248. public void disConnect()
  249. {
  250. // Abort Read Thread if it exists
  251. //
  252. if (m_ReadThread != null)
  253. {
  254. m_ReadThread.Abort();
  255. m_ReadThread.Join();
  256. m_ReadThread = null;
  257. }
  258. // Releases the used PCAN-Basic channel
  259. //
  260. PCANBasic.Uninitialize(m_PcanHandle);
  261. }
  262. /// <summary>
  263. /// 设置波特率
  264. /// </summary>
  265. private void setBaudrate()
  266. {
  267. int baudRate = int.Parse(System.Configuration.ConfigurationManager.AppSettings["Baudrate_CAN"]);
  268. switch (baudRate)
  269. {
  270. case 0:
  271. m_Baudrate = TPCANBaudrate.PCAN_BAUD_1M;
  272. break;
  273. case 1:
  274. m_Baudrate = TPCANBaudrate.PCAN_BAUD_800K;
  275. break;
  276. case 2:
  277. m_Baudrate = TPCANBaudrate.PCAN_BAUD_500K;
  278. break;
  279. case 3:
  280. m_Baudrate = TPCANBaudrate.PCAN_BAUD_250K;
  281. break;
  282. case 4:
  283. m_Baudrate = TPCANBaudrate.PCAN_BAUD_125K;
  284. break;
  285. case 5:
  286. m_Baudrate = TPCANBaudrate.PCAN_BAUD_100K;
  287. break;
  288. case 6:
  289. m_Baudrate = TPCANBaudrate.PCAN_BAUD_95K;
  290. break;
  291. case 7:
  292. m_Baudrate = TPCANBaudrate.PCAN_BAUD_83K;
  293. break;
  294. case 8:
  295. m_Baudrate = TPCANBaudrate.PCAN_BAUD_50K;
  296. break;
  297. case 9:
  298. m_Baudrate = TPCANBaudrate.PCAN_BAUD_47K;
  299. break;
  300. case 10:
  301. m_Baudrate = TPCANBaudrate.PCAN_BAUD_33K;
  302. break;
  303. case 11:
  304. m_Baudrate = TPCANBaudrate.PCAN_BAUD_20K;
  305. break;
  306. case 12:
  307. m_Baudrate = TPCANBaudrate.PCAN_BAUD_10K;
  308. break;
  309. case 13:
  310. m_Baudrate = TPCANBaudrate.PCAN_BAUD_5K;
  311. break;
  312. default:
  313. m_Baudrate = TPCANBaudrate.PCAN_BAUD_500K;
  314. break;
  315. }
  316. }
  317. /// <summary>
  318. /// 设置CAN总线句柄
  319. /// </summary>
  320. private void setCANHandle()
  321. {
  322. int handle = int.Parse(System.Configuration.ConfigurationManager.AppSettings["TPHandle_CAN"]);
  323. switch (handle)
  324. {
  325. case 0:
  326. m_PcanHandle = PCANBasic.PCAN_NONEBUS;
  327. break;
  328. case 1:
  329. m_PcanHandle = PCANBasic.PCAN_ISABUS1;
  330. break;
  331. case 2:
  332. m_PcanHandle = PCANBasic.PCAN_ISABUS2;
  333. break;
  334. case 3:
  335. m_PcanHandle = PCANBasic.PCAN_ISABUS3;
  336. break;
  337. case 4:
  338. m_PcanHandle = PCANBasic.PCAN_ISABUS4;
  339. break;
  340. case 5:
  341. m_PcanHandle = PCANBasic.PCAN_ISABUS5;
  342. break;
  343. case 6:
  344. m_PcanHandle = PCANBasic.PCAN_ISABUS6;
  345. break;
  346. case 7:
  347. m_PcanHandle = PCANBasic.PCAN_ISABUS7;
  348. break;
  349. case 8:
  350. m_PcanHandle = PCANBasic.PCAN_ISABUS8;
  351. break;
  352. case 9:
  353. m_PcanHandle = PCANBasic.PCAN_DNGBUS1;
  354. break;
  355. case 10:
  356. m_PcanHandle = PCANBasic.PCAN_PCIBUS1;
  357. break;
  358. case 11:
  359. m_PcanHandle = PCANBasic.PCAN_PCIBUS2;
  360. break;
  361. case 12:
  362. m_PcanHandle = PCANBasic.PCAN_PCIBUS3;
  363. break;
  364. case 13:
  365. m_PcanHandle = PCANBasic.PCAN_PCIBUS4;
  366. break;
  367. case 14:
  368. m_PcanHandle = PCANBasic.PCAN_PCIBUS5;
  369. break;
  370. case 15:
  371. m_PcanHandle = PCANBasic.PCAN_PCIBUS6;
  372. break;
  373. case 16:
  374. m_PcanHandle = PCANBasic.PCAN_PCIBUS7;
  375. break;
  376. case 17:
  377. m_PcanHandle = PCANBasic.PCAN_PCIBUS8;
  378. break;
  379. case 18:
  380. m_PcanHandle = PCANBasic.PCAN_USBBUS1;
  381. break;
  382. case 19:
  383. m_PcanHandle = PCANBasic.PCAN_USBBUS2;
  384. break;
  385. case 20:
  386. m_PcanHandle = PCANBasic.PCAN_USBBUS3;
  387. break;
  388. case 21:
  389. m_PcanHandle = PCANBasic.PCAN_USBBUS4;
  390. break;
  391. case 22:
  392. m_PcanHandle = PCANBasic.PCAN_USBBUS5;
  393. break;
  394. case 23:
  395. m_PcanHandle = PCANBasic.PCAN_USBBUS6;
  396. break;
  397. case 24:
  398. m_PcanHandle = PCANBasic.PCAN_USBBUS7;
  399. break;
  400. case 25:
  401. m_PcanHandle = PCANBasic.PCAN_USBBUS8;
  402. break;
  403. case 26:
  404. m_PcanHandle = PCANBasic.PCAN_PCCBUS1;
  405. break;
  406. case 27:
  407. m_PcanHandle = PCANBasic.PCAN_PCCBUS2;
  408. break;
  409. default:
  410. m_PcanHandle = PCANBasic.PCAN_PCCBUS2;
  411. break;
  412. }
  413. }
  414. private void setHardWareType()
  415. {
  416. int hwType = int.Parse(System.Configuration.ConfigurationManager.AppSettings["HwType_CAN"]);
  417. switch (hwType)
  418. {
  419. case 0:
  420. m_HwType = TPCANType.PCAN_TYPE_ISA;
  421. break;
  422. case 1:
  423. m_HwType = TPCANType.PCAN_TYPE_ISA_SJA;
  424. break;
  425. case 2:
  426. m_HwType = TPCANType.PCAN_TYPE_ISA_PHYTEC;
  427. break;
  428. case 3:
  429. m_HwType = TPCANType.PCAN_TYPE_DNG;
  430. break;
  431. case 4:
  432. m_HwType = TPCANType.PCAN_TYPE_DNG_EPP;
  433. break;
  434. case 5:
  435. m_HwType = TPCANType.PCAN_TYPE_DNG_SJA;
  436. break;
  437. case 6:
  438. m_HwType = TPCANType.PCAN_TYPE_DNG_SJA_EPP;
  439. break;
  440. default:
  441. m_HwType = TPCANType.PCAN_TYPE_DNG_SJA_EPP;
  442. break;
  443. }
  444. }
  445. /// <summary>
  446. /// 写入数据包
  447. /// </summary>
  448. /// <param name="data"></param>
  449. public void Write(byte[] data, string id)
  450. {
  451. TPCANStatus stsResult;
  452. // Send the message
  453. //
  454. stsResult = m_IsFD ? WriteFrameFD(data, id) : WriteFrame(data, id);
  455. // The message was successfully sent
  456. //
  457. if (stsResult == TPCANStatus.PCAN_ERROR_OK)
  458. LogHelper.log.Debug("Message was successfully SENT");
  459. // An error occurred. We show the error.
  460. //
  461. else
  462. LogHelper.log.Error(GetFormatedError(stsResult));
  463. }
  464. /// <summary>
  465. /// 写入数据帧
  466. /// </summary>
  467. /// <param name="data">标准数据</param>
  468. /// <param name="id">id</param>
  469. /// <returns></returns>
  470. private TPCANStatus WriteFrame(byte[] data, string id)
  471. {
  472. TPCANMsg CANMsg;
  473. // We create a TPCANMsg message structure
  474. //
  475. CANMsg = new TPCANMsg();
  476. CANMsg.DATA = new byte[8];
  477. // We configurate the Message. The ID,
  478. // Length of the Data, Message Type
  479. // and the data
  480. //
  481. CANMsg.ID = Convert.ToUInt32(id, 16);
  482. CANMsg.LEN = Convert.ToByte(data.Length);
  483. CANMsg.MSGTYPE = bExtend ? TPCANMessageType.PCAN_MESSAGE_EXTENDED : TPCANMessageType.PCAN_MESSAGE_STANDARD;
  484. // If a remote frame will be sent, the data bytes are not important.
  485. //
  486. if (bRemote)
  487. CANMsg.MSGTYPE |= TPCANMessageType.PCAN_MESSAGE_RTR;
  488. else
  489. {
  490. // We get so much data as the Len of the message
  491. //
  492. for (int i = 0; i < GetLengthFromDLC(CANMsg.LEN, true); i++)
  493. {
  494. CANMsg.DATA[i] = data[i];
  495. }
  496. }
  497. // The message is sent to the configured hardware
  498. //
  499. return PCANBasic.Write(m_PcanHandle, ref CANMsg);
  500. }
  501. /// <summary>
  502. /// FD类型写入数据帧
  503. /// </summary>
  504. /// <param name="data">数据</param>
  505. /// <param name="id"></param>
  506. /// <returns></returns>
  507. private TPCANStatus WriteFrameFD(byte[] data, string id)
  508. {
  509. TPCANMsgFD CANMsg;
  510. int iLength;
  511. // We create a TPCANMsgFD message structure
  512. //
  513. CANMsg = new TPCANMsgFD();
  514. CANMsg.DATA = new byte[64];
  515. // We configurate the Message. The ID,
  516. // Length of the Data, Message Type
  517. // and the data
  518. //
  519. CANMsg.ID = Convert.ToUInt32(id, 16);
  520. CANMsg.DLC = Convert.ToByte(data.Length);
  521. CANMsg.MSGTYPE = bExtend ? TPCANMessageType.PCAN_MESSAGE_EXTENDED : TPCANMessageType.PCAN_MESSAGE_STANDARD;
  522. CANMsg.MSGTYPE |= bFD ? TPCANMessageType.PCAN_MESSAGE_FD : TPCANMessageType.PCAN_MESSAGE_STANDARD;
  523. CANMsg.MSGTYPE |= bBRS ? TPCANMessageType.PCAN_MESSAGE_BRS : TPCANMessageType.PCAN_MESSAGE_STANDARD;
  524. // If a remote frame will be sent, the data bytes are not important.
  525. //
  526. if (bRemote)
  527. CANMsg.MSGTYPE |= TPCANMessageType.PCAN_MESSAGE_RTR;
  528. else
  529. {
  530. // We get so much data as the Len of the message
  531. //
  532. iLength = GetLengthFromDLC(CANMsg.DLC, (CANMsg.MSGTYPE & TPCANMessageType.PCAN_MESSAGE_FD) == 0);
  533. for (int i = 0; i < iLength; i++)
  534. {
  535. CANMsg.DATA[i] = data[i];
  536. }
  537. }
  538. // The message is sent to the configured hardware
  539. //
  540. return PCANBasic.WriteFD(m_PcanHandle, ref CANMsg);
  541. }
  542. /// <summary>
  543. /// Configures the PCAN-Trace file for a PCAN-Basic Channel
  544. /// </summary>
  545. private void ConfigureTraceFile()
  546. {
  547. UInt32 iBuffer;
  548. TPCANStatus stsResult;
  549. // Configure the maximum size of a trace file to 5 megabytes
  550. //
  551. iBuffer = 5;
  552. stsResult = PCANBasic.SetValue(m_PcanHandle, TPCANParameter.PCAN_TRACE_SIZE, ref iBuffer, sizeof(UInt32));
  553. if (stsResult != TPCANStatus.PCAN_ERROR_OK)
  554. LogHelper.log.Error(GetFormatedError(stsResult));
  555. // Configure the way how trace files are created:
  556. // * Standard name is used
  557. // * Existing file is ovewritten,
  558. // * Only one file is created.
  559. // * Recording stopts when the file size reaches 5 megabytes.
  560. //
  561. iBuffer = PCANBasic.TRACE_FILE_SINGLE | PCANBasic.TRACE_FILE_OVERWRITE;
  562. stsResult = PCANBasic.SetValue(m_PcanHandle, TPCANParameter.PCAN_TRACE_CONFIGURE, ref iBuffer, sizeof(UInt32));
  563. if (stsResult != TPCANStatus.PCAN_ERROR_OK)
  564. LogHelper.log.Error(GetFormatedError(stsResult));
  565. }
  566. /// <summary>
  567. /// Help Function used to get an error as text
  568. /// </summary>
  569. /// <param name="error">Error code to be translated</param>
  570. /// <returns>A text with the translated error</returns>
  571. private string GetFormatedError(TPCANStatus error)
  572. {
  573. StringBuilder strTemp;
  574. // Creates a buffer big enough for a error-text
  575. //
  576. strTemp = new StringBuilder(256);
  577. // Gets the text using the GetErrorText API function
  578. // If the function success, the translated error is returned. If it fails,
  579. // a text describing the current error is returned.
  580. //
  581. if (PCANBasic.GetErrorText(error, 0, strTemp) != TPCANStatus.PCAN_ERROR_OK)
  582. return string.Format("An error occurred. Error-code's text ({0:X}) couldn't be retrieved", error);
  583. else
  584. return strTemp.ToString();
  585. }
  586. #region Help functions
  587. /// <summary>
  588. /// Convert a CAN DLC value into the actual data length of the CAN/CAN-FD frame.
  589. /// </summary>
  590. /// <param name="dlc">A value between 0 and 15 (CAN and FD DLC range)</param>
  591. /// <param name="isSTD">A value indicating if the msg is a standard CAN (FD Flag not checked)</param>
  592. /// <returns>The length represented by the DLC</returns>
  593. private int GetLengthFromDLC(int dlc, bool isSTD)
  594. {
  595. if (dlc <= 8)
  596. return dlc;
  597. if (isSTD)
  598. return 8;
  599. switch (dlc)
  600. {
  601. case 9: return 12;
  602. case 10: return 16;
  603. case 11: return 20;
  604. case 12: return 24;
  605. case 13: return 32;
  606. case 14: return 48;
  607. case 15: return 64;
  608. default: return dlc;
  609. }
  610. }
  611. #endregion help functions
  612. }
  613. }