123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673 |
- using ProjectBase.Data.Logs;
- using System;
- using System.Text;
- /// <summary>
- /// Inclusion of PEAK PCAN-Basic namespace
- /// </summary>
- using TPCANHandle = System.UInt16;
- using TPCANBitrateFD = System.String;
- using TPCANTimestampFD = System.UInt64;
- namespace SIASUN.Autopilot.Device
- {
- public class CanHelper : ICanHelper
- {
- #region Delegates
- /// <summary>
- /// Read-Delegate Handler
- /// </summary>
- //private delegate void ReadDelegateHandler();
- #endregion
- #region Members
- /// <summary>
- /// Saves the desired connection mode
- /// </summary>
- private bool m_IsFD = false;
- /// <summary>
- /// Saves the handle of a PCAN hardware
- /// </summary>
- private TPCANHandle m_PcanHandle;
- /// <summary>
- /// Saves the baudrate register for a conenction
- /// </summary>
- private TPCANBaudrate m_Baudrate;
- /// <summary>
- /// Saves the type of a non-plug-and-play hardware
- /// </summary>
- private TPCANType m_HwType;
- /// <summary>
- /// Stores the status of received messages for its display
- /// </summary>
- private System.Collections.ArrayList m_LastMsgsList;
- /// <summary>
- /// Read Delegate for calling the function "ReadMessages"
- /// </summary>
- //private ReadDelegateHandler m_ReadDelegate;
- /// <summary>
- /// Receive-Event
- /// </summary>
- private System.Threading.AutoResetEvent m_ReceiveEvent;
- /// <summary>
- /// Thread for message reading (using events)
- /// </summary>
- private System.Threading.Thread m_ReadThread;
- /// <summary>
- /// Handles of non plug and play PCAN-Hardware
- /// </summary>
- private TPCANHandle[] m_NonPnPHandles;
- /// <summary>
- /// MessageType is extend or standard
- /// </summary>
- private bool bExtend = false;
- private bool bFD = false;
- private bool bBRS = false;
- private bool bRemote = false;
- public CanHelper()
- {
- // Creates the list for received messages
- //
- //m_LastMsgsList = new System.Collections.ArrayList();
- // Creates the delegate used for message reading
- //
- //m_ReadDelegate = new ReadDelegateHandler(ReadMessages);
- // Creates the event used for signalize incomming messages
- //
- m_ReceiveEvent = new System.Threading.AutoResetEvent(false);
- }
- #endregion
- /// <summary>
- /// 初始化can总线
- /// </summary>
- public void Initialize()
- {
- try
- {
- string IOCan = System.Configuration.ConfigurationManager.AppSettings["IO_CAN"];
- string Interrupt = System.Configuration.ConfigurationManager.AppSettings["Interrupt_CAN"];
- setBaudrate();
- setCANHandle();
- setHardWareType();
- TPCANStatus stsResult;
- // Connects a selected PCAN-Basic channel
- stsResult = PCANBasic.Initialize(
- m_PcanHandle,
- m_Baudrate,
- m_HwType,
- Convert.ToUInt32(IOCan, 16),
- Convert.ToUInt16(Interrupt));
- if (stsResult != TPCANStatus.PCAN_ERROR_OK)
- LogHelper.log.Error(GetFormatedError(stsResult));
- else
- // Prepares the PCAN-Basic's PCAN-Trace file
- //
- ConfigureTraceFile();
- // Sets the connection status of the main-form
- //
- SetConnectionStatus(stsResult == TPCANStatus.PCAN_ERROR_OK);
- }
- catch (Exception ex)
- {
- LogHelper.log.Error("can总线初始化失败。", ex);
- }
- }
- /// <summary>
- /// Activates/deaactivates the different controls of the main-form according
- /// with the current connection status
- /// </summary>
- /// <param name="bConnected">Current status. True if connected, false otherwise</param>
- private void SetConnectionStatus(bool bConnected)
- {
- if (!bConnected)
- {
- LogHelper.log.Debug("can总线未连接成功");
- }
- else
- {
- // Create and start the tread to read CAN Message using SetRcvEvent()
- //
- System.Threading.ThreadStart threadDelegate = new System.Threading.ThreadStart(this.CANReadThreadFunc);
- m_ReadThread = new System.Threading.Thread(threadDelegate);
- m_ReadThread.IsBackground = true;
- m_ReadThread.Start();
- }
- }
- /// <summary>
- /// Thread-Function used for reading PCAN-Basic messages
- /// </summary>
- private void CANReadThreadFunc()
- {
- UInt32 iBuffer;
- TPCANStatus stsResult;
- iBuffer = Convert.ToUInt32(m_ReceiveEvent.SafeWaitHandle.DangerousGetHandle().ToInt32());
- // Sets the handle of the Receive-Event.
- //
- stsResult = PCANBasic.SetValue(m_PcanHandle, TPCANParameter.PCAN_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));
- if (stsResult != TPCANStatus.PCAN_ERROR_OK)
- {
- LogHelper.log.Error(GetFormatedError(stsResult));
- return;
- }
- // While this mode is selected
- while (true)
- {
- // Waiting for Receive-Event
- //
- if (m_ReceiveEvent.WaitOne(50))
- ReadMessages();
- }
- }
- /// <summary>
- /// Function for reading PCAN-Basic messages
- /// </summary>
- private void ReadMessages()
- {
- TPCANStatus stsResult;
- // We read at least one time the queue looking for messages.
- // If a message is found, we look again trying to find more.
- // If the queue is empty or an error occurr, we get out from
- // the dowhile statement.
- do
- {
- stsResult = m_IsFD ? ReadMessageFD() : ReadMessage();
- if (stsResult == TPCANStatus.PCAN_ERROR_ILLOPERATION)
- break;
- } while (!Convert.ToBoolean(stsResult & TPCANStatus.PCAN_ERROR_QRCVEMPTY));
- }
- /// <summary>
- /// Function for reading messages on FD devices
- /// </summary>
- /// <returns>A TPCANStatus error code</returns>
- private TPCANStatus ReadMessageFD()
- {
- TPCANMsgFD CANMsg;
- TPCANTimestampFD CANTimeStamp;
- TPCANStatus stsResult;
- // We execute the "Read" function of the PCANBasic
- //
- stsResult = PCANBasic.ReadFD(m_PcanHandle, out CANMsg, out CANTimeStamp);
- if (stsResult != TPCANStatus.PCAN_ERROR_QRCVEMPTY)
- // We process the received message
- //
- ProcessMessage(CANMsg, CANTimeStamp);
- return stsResult;
- }
- /// <summary>
- /// Function for reading CAN messages on normal CAN devices
- /// </summary>
- /// <returns>A TPCANStatus error code</returns>
- private TPCANStatus ReadMessage()
- {
- TPCANMsg CANMsg;
- TPCANTimestamp CANTimeStamp;
- TPCANStatus stsResult;
- // We execute the "Read" function of the PCANBasic
- //
- stsResult = PCANBasic.Read(m_PcanHandle, out CANMsg, out CANTimeStamp);
- if (stsResult != TPCANStatus.PCAN_ERROR_QRCVEMPTY)
- // We process the received message
- //
- ProcessMessage(CANMsg, CANTimeStamp);
- return stsResult;
- }
- /// <summary>
- /// Processes a received message, in order to convert to bll
- /// </summary>
- /// <param name="theMsg">The received PCAN-Basic message</param>
- /// <returns>True if the message must be created, false if it must be modified</returns>
- private void ProcessMessage(TPCANMsg theMsg, TPCANTimestamp itsTimeStamp)
- {
- TPCANMsgFD newMsg;
- TPCANTimestampFD newTimestamp;
- newMsg = new TPCANMsgFD();
- newMsg.DATA = new byte[64];
- newMsg.ID = theMsg.ID;
- newMsg.DLC = theMsg.LEN;
- for (int i = 0; i < ((theMsg.LEN > 8) ? 8 : theMsg.LEN); i++)
- newMsg.DATA[i] = theMsg.DATA[i];
- newMsg.MSGTYPE = theMsg.MSGTYPE;
- newTimestamp = Convert.ToUInt64(itsTimeStamp.micros + 1000 * itsTimeStamp.millis + 0x100000000 * 1000 * itsTimeStamp.millis_overflow);
- ProcessMessage(newMsg, newTimestamp);
- }
- /// <summary>
- /// Processes a received message, in order to show it in the Message-ListView
- /// </summary>
- /// <param name="theMsg">The received PCAN-Basic message</param>
- /// <returns>True if the message must be created, false if it must be modified</returns>
- private void ProcessMessage(TPCANMsgFD theMsg, TPCANTimestampFD itsTimeStamp)
- {
- MessageStatus msgStsCurrentMsg;
- msgStsCurrentMsg = new MessageStatus(theMsg, itsTimeStamp);
- // 拆包
- Package_Data_Msg<object> rp = new Package_Data_Msg<object>();
- object up = rp.UnPackage(msgStsCurrentMsg.IdString, msgStsCurrentMsg.CANMsg.DATA);
- // 将事件加入委托链
- EventManage.Instance.RaiseEvent(msgStsCurrentMsg.IdString, rp.Message);
- }
- /// <summary>
- /// 断开连接
- /// </summary>
- public void disConnect()
- {
- // Abort Read Thread if it exists
- //
- if (m_ReadThread != null)
- {
- m_ReadThread.Abort();
- m_ReadThread.Join();
- m_ReadThread = null;
- }
- // Releases the used PCAN-Basic channel
- //
- PCANBasic.Uninitialize(m_PcanHandle);
- }
- /// <summary>
- /// 设置波特率
- /// </summary>
- private void setBaudrate()
- {
- int baudRate = int.Parse(System.Configuration.ConfigurationManager.AppSettings["Baudrate_CAN"]);
- switch (baudRate)
- {
- case 0:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_1M;
- break;
- case 1:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_800K;
- break;
- case 2:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_500K;
- break;
- case 3:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_250K;
- break;
- case 4:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_125K;
- break;
- case 5:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_100K;
- break;
- case 6:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_95K;
- break;
- case 7:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_83K;
- break;
- case 8:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_50K;
- break;
- case 9:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_47K;
- break;
- case 10:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_33K;
- break;
- case 11:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_20K;
- break;
- case 12:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_10K;
- break;
- case 13:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_5K;
- break;
- default:
- m_Baudrate = TPCANBaudrate.PCAN_BAUD_500K;
- break;
- }
- }
- /// <summary>
- /// 设置CAN总线句柄
- /// </summary>
- private void setCANHandle()
- {
- int handle = int.Parse(System.Configuration.ConfigurationManager.AppSettings["TPHandle_CAN"]);
- switch (handle)
- {
- case 0:
- m_PcanHandle = PCANBasic.PCAN_NONEBUS;
- break;
- case 1:
- m_PcanHandle = PCANBasic.PCAN_ISABUS1;
- break;
- case 2:
- m_PcanHandle = PCANBasic.PCAN_ISABUS2;
- break;
- case 3:
- m_PcanHandle = PCANBasic.PCAN_ISABUS3;
- break;
- case 4:
- m_PcanHandle = PCANBasic.PCAN_ISABUS4;
- break;
- case 5:
- m_PcanHandle = PCANBasic.PCAN_ISABUS5;
- break;
- case 6:
- m_PcanHandle = PCANBasic.PCAN_ISABUS6;
- break;
- case 7:
- m_PcanHandle = PCANBasic.PCAN_ISABUS7;
- break;
- case 8:
- m_PcanHandle = PCANBasic.PCAN_ISABUS8;
- break;
- case 9:
- m_PcanHandle = PCANBasic.PCAN_DNGBUS1;
- break;
- case 10:
- m_PcanHandle = PCANBasic.PCAN_PCIBUS1;
- break;
- case 11:
- m_PcanHandle = PCANBasic.PCAN_PCIBUS2;
- break;
- case 12:
- m_PcanHandle = PCANBasic.PCAN_PCIBUS3;
- break;
- case 13:
- m_PcanHandle = PCANBasic.PCAN_PCIBUS4;
- break;
- case 14:
- m_PcanHandle = PCANBasic.PCAN_PCIBUS5;
- break;
- case 15:
- m_PcanHandle = PCANBasic.PCAN_PCIBUS6;
- break;
- case 16:
- m_PcanHandle = PCANBasic.PCAN_PCIBUS7;
- break;
- case 17:
- m_PcanHandle = PCANBasic.PCAN_PCIBUS8;
- break;
- case 18:
- m_PcanHandle = PCANBasic.PCAN_USBBUS1;
- break;
- case 19:
- m_PcanHandle = PCANBasic.PCAN_USBBUS2;
- break;
- case 20:
- m_PcanHandle = PCANBasic.PCAN_USBBUS3;
- break;
- case 21:
- m_PcanHandle = PCANBasic.PCAN_USBBUS4;
- break;
- case 22:
- m_PcanHandle = PCANBasic.PCAN_USBBUS5;
- break;
- case 23:
- m_PcanHandle = PCANBasic.PCAN_USBBUS6;
- break;
- case 24:
- m_PcanHandle = PCANBasic.PCAN_USBBUS7;
- break;
- case 25:
- m_PcanHandle = PCANBasic.PCAN_USBBUS8;
- break;
- case 26:
- m_PcanHandle = PCANBasic.PCAN_PCCBUS1;
- break;
- case 27:
- m_PcanHandle = PCANBasic.PCAN_PCCBUS2;
- break;
- default:
- m_PcanHandle = PCANBasic.PCAN_PCCBUS2;
- break;
- }
- }
- private void setHardWareType()
- {
- int hwType = int.Parse(System.Configuration.ConfigurationManager.AppSettings["HwType_CAN"]);
- switch (hwType)
- {
- case 0:
- m_HwType = TPCANType.PCAN_TYPE_ISA;
- break;
- case 1:
- m_HwType = TPCANType.PCAN_TYPE_ISA_SJA;
- break;
- case 2:
- m_HwType = TPCANType.PCAN_TYPE_ISA_PHYTEC;
- break;
- case 3:
- m_HwType = TPCANType.PCAN_TYPE_DNG;
- break;
- case 4:
- m_HwType = TPCANType.PCAN_TYPE_DNG_EPP;
- break;
- case 5:
- m_HwType = TPCANType.PCAN_TYPE_DNG_SJA;
- break;
- case 6:
- m_HwType = TPCANType.PCAN_TYPE_DNG_SJA_EPP;
- break;
- default:
- m_HwType = TPCANType.PCAN_TYPE_DNG_SJA_EPP;
- break;
- }
- }
-
- /// <summary>
- /// 写入数据包
- /// </summary>
- /// <param name="data"></param>
- public void Write(byte[] data, string id)
- {
- TPCANStatus stsResult;
- // Send the message
- //
- stsResult = m_IsFD ? WriteFrameFD(data, id) : WriteFrame(data, id);
- // The message was successfully sent
- //
- if (stsResult == TPCANStatus.PCAN_ERROR_OK)
- LogHelper.log.Debug("Message was successfully SENT");
- // An error occurred. We show the error.
- //
- else
- LogHelper.log.Error(GetFormatedError(stsResult));
- }
- /// <summary>
- /// 写入数据帧
- /// </summary>
- /// <param name="data">标准数据</param>
- /// <param name="id">id</param>
- /// <returns></returns>
- private TPCANStatus WriteFrame(byte[] data, string id)
- {
- TPCANMsg CANMsg;
- // We create a TPCANMsg message structure
- //
- CANMsg = new TPCANMsg();
- CANMsg.DATA = new byte[8];
- // We configurate the Message. The ID,
- // Length of the Data, Message Type
- // and the data
- //
- CANMsg.ID = Convert.ToUInt32(id, 16);
- CANMsg.LEN = Convert.ToByte(data.Length);
- CANMsg.MSGTYPE = bExtend ? TPCANMessageType.PCAN_MESSAGE_EXTENDED : TPCANMessageType.PCAN_MESSAGE_STANDARD;
- // If a remote frame will be sent, the data bytes are not important.
- //
- if (bRemote)
- CANMsg.MSGTYPE |= TPCANMessageType.PCAN_MESSAGE_RTR;
- else
- {
- // We get so much data as the Len of the message
- //
- for (int i = 0; i < GetLengthFromDLC(CANMsg.LEN, true); i++)
- {
- CANMsg.DATA[i] = data[i];
- }
- }
- // The message is sent to the configured hardware
- //
- return PCANBasic.Write(m_PcanHandle, ref CANMsg);
- }
- /// <summary>
- /// FD类型写入数据帧
- /// </summary>
- /// <param name="data">数据</param>
- /// <param name="id"></param>
- /// <returns></returns>
- private TPCANStatus WriteFrameFD(byte[] data, string id)
- {
- TPCANMsgFD CANMsg;
- int iLength;
- // We create a TPCANMsgFD message structure
- //
- CANMsg = new TPCANMsgFD();
- CANMsg.DATA = new byte[64];
- // We configurate the Message. The ID,
- // Length of the Data, Message Type
- // and the data
- //
- CANMsg.ID = Convert.ToUInt32(id, 16);
- CANMsg.DLC = Convert.ToByte(data.Length);
- CANMsg.MSGTYPE = bExtend ? TPCANMessageType.PCAN_MESSAGE_EXTENDED : TPCANMessageType.PCAN_MESSAGE_STANDARD;
- CANMsg.MSGTYPE |= bFD ? TPCANMessageType.PCAN_MESSAGE_FD : TPCANMessageType.PCAN_MESSAGE_STANDARD;
- CANMsg.MSGTYPE |= bBRS ? TPCANMessageType.PCAN_MESSAGE_BRS : TPCANMessageType.PCAN_MESSAGE_STANDARD;
- // If a remote frame will be sent, the data bytes are not important.
- //
- if (bRemote)
- CANMsg.MSGTYPE |= TPCANMessageType.PCAN_MESSAGE_RTR;
- else
- {
- // We get so much data as the Len of the message
- //
- iLength = GetLengthFromDLC(CANMsg.DLC, (CANMsg.MSGTYPE & TPCANMessageType.PCAN_MESSAGE_FD) == 0);
- for (int i = 0; i < iLength; i++)
- {
- CANMsg.DATA[i] = data[i];
- }
- }
- // The message is sent to the configured hardware
- //
- return PCANBasic.WriteFD(m_PcanHandle, ref CANMsg);
- }
- /// <summary>
- /// Configures the PCAN-Trace file for a PCAN-Basic Channel
- /// </summary>
- private void ConfigureTraceFile()
- {
- UInt32 iBuffer;
- TPCANStatus stsResult;
- // Configure the maximum size of a trace file to 5 megabytes
- //
- iBuffer = 5;
- stsResult = PCANBasic.SetValue(m_PcanHandle, TPCANParameter.PCAN_TRACE_SIZE, ref iBuffer, sizeof(UInt32));
- if (stsResult != TPCANStatus.PCAN_ERROR_OK)
- LogHelper.log.Error(GetFormatedError(stsResult));
- // Configure the way how trace files are created:
- // * Standard name is used
- // * Existing file is ovewritten,
- // * Only one file is created.
- // * Recording stopts when the file size reaches 5 megabytes.
- //
- iBuffer = PCANBasic.TRACE_FILE_SINGLE | PCANBasic.TRACE_FILE_OVERWRITE;
- stsResult = PCANBasic.SetValue(m_PcanHandle, TPCANParameter.PCAN_TRACE_CONFIGURE, ref iBuffer, sizeof(UInt32));
- if (stsResult != TPCANStatus.PCAN_ERROR_OK)
- LogHelper.log.Error(GetFormatedError(stsResult));
- }
- /// <summary>
- /// Help Function used to get an error as text
- /// </summary>
- /// <param name="error">Error code to be translated</param>
- /// <returns>A text with the translated error</returns>
- private string GetFormatedError(TPCANStatus error)
- {
- StringBuilder strTemp;
- // Creates a buffer big enough for a error-text
- //
- strTemp = new StringBuilder(256);
- // Gets the text using the GetErrorText API function
- // If the function success, the translated error is returned. If it fails,
- // a text describing the current error is returned.
- //
- if (PCANBasic.GetErrorText(error, 0, strTemp) != TPCANStatus.PCAN_ERROR_OK)
- return string.Format("An error occurred. Error-code's text ({0:X}) couldn't be retrieved", error);
- else
- return strTemp.ToString();
- }
- #region Help functions
- /// <summary>
- /// Convert a CAN DLC value into the actual data length of the CAN/CAN-FD frame.
- /// </summary>
- /// <param name="dlc">A value between 0 and 15 (CAN and FD DLC range)</param>
- /// <param name="isSTD">A value indicating if the msg is a standard CAN (FD Flag not checked)</param>
- /// <returns>The length represented by the DLC</returns>
- private int GetLengthFromDLC(int dlc, bool isSTD)
- {
- if (dlc <= 8)
- return dlc;
- if (isSTD)
- return 8;
- switch (dlc)
- {
- case 9: return 12;
- case 10: return 16;
- case 11: return 20;
- case 12: return 24;
- case 13: return 32;
- case 14: return 48;
- case 15: return 64;
- default: return dlc;
- }
- }
- #endregion help functions
- }
- }
|