using ProjectBase.Data.Logs;
using System;
using System.Text;
///
/// Inclusion of PEAK PCAN-Basic namespace
///
using TPCANHandle = System.UInt16;
using TPCANBitrateFD = System.String;
using TPCANTimestampFD = System.UInt64;
namespace SIASUN.Autopilot.Device
{
public class CanHelper : ICanHelper
{
#region Delegates
///
/// Read-Delegate Handler
///
//private delegate void ReadDelegateHandler();
#endregion
#region Members
///
/// Saves the desired connection mode
///
private bool m_IsFD = false;
///
/// Saves the handle of a PCAN hardware
///
private TPCANHandle m_PcanHandle;
///
/// Saves the baudrate register for a conenction
///
private TPCANBaudrate m_Baudrate;
///
/// Saves the type of a non-plug-and-play hardware
///
private TPCANType m_HwType;
///
/// Stores the status of received messages for its display
///
private System.Collections.ArrayList m_LastMsgsList;
///
/// Read Delegate for calling the function "ReadMessages"
///
//private ReadDelegateHandler m_ReadDelegate;
///
/// Receive-Event
///
private System.Threading.AutoResetEvent m_ReceiveEvent;
///
/// Thread for message reading (using events)
///
private System.Threading.Thread m_ReadThread;
///
/// Handles of non plug and play PCAN-Hardware
///
private TPCANHandle[] m_NonPnPHandles;
///
/// MessageType is extend or standard
///
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
///
/// 初始化can总线
///
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);
}
}
///
/// Activates/deaactivates the different controls of the main-form according
/// with the current connection status
///
/// Current status. True if connected, false otherwise
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();
}
}
///
/// Thread-Function used for reading PCAN-Basic messages
///
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();
}
}
///
/// Function for reading PCAN-Basic messages
///
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));
}
///
/// Function for reading messages on FD devices
///
/// A TPCANStatus error code
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;
}
///
/// Function for reading CAN messages on normal CAN devices
///
/// A TPCANStatus error code
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;
}
///
/// Processes a received message, in order to convert to bll
///
/// The received PCAN-Basic message
/// True if the message must be created, false if it must be modified
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);
}
///
/// Processes a received message, in order to show it in the Message-ListView
///
/// The received PCAN-Basic message
/// True if the message must be created, false if it must be modified
private void ProcessMessage(TPCANMsgFD theMsg, TPCANTimestampFD itsTimeStamp)
{
MessageStatus msgStsCurrentMsg;
msgStsCurrentMsg = new MessageStatus(theMsg, itsTimeStamp);
// 拆包
Package_Data_Msg