秋荷雨翔 通过本文主要向大家介绍了圆c通过不同的三点,安全员c证通过率,c919通过首飞技术评审,司法考试c证通过率,如何通过互联网赚钱等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
下面分几部分介绍C#实现自动售货机接口的方法,代码写的非常详细,不懂的地方有注释可以参考下。
MachineJP类:
第1部分:串口初始化,串口数据读写
using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using MachineJPDll.Models; using MachineJPDll.Utils; namespace MachineJPDll { /// <summary> /// 售货机接口(接口) /// </summary> public partial class MachineJP { #region 变量 /// <summary> /// 串口资源 /// </summary> private SerialPort m_SerialPort = null; /// <summary> /// 待发送给串口的命令列表 /// </summary> private List<Cmd> m_CommandList = new List<Cmd>(); /// <summary> /// 等待ACK_RPT或NAK_RPT的PC端向VMC端发送的消息列表 /// </summary> private List<MT> m_WaitResultMTList = new List<MT>(); /// <summary> /// 从串口接收的数据集合(数据已通过验证) /// </summary> private ReceiveDataCollection m_ReceiveDataCollection = new ReceiveDataCollection(); #endregion #region 构造函数与析构函数 /// <summary> /// 售货机接口(接口) /// </summary> public MachineJP() { } ~MachineJP() { if (m_SerialPort != null) { m_SerialPort.Close(); m_SerialPort.Dispose(); m_SerialPort = null; } } #endregion #region 读取串口数据 /// <summary> /// 读取串口数据 /// </summary> /// <returns>从串口读取的数据</returns> private byte[] ReadPort() { //读取串口数据 DateTime dt = DateTime.Now; while (m_SerialPort.BytesToRead < 2) { Thread.Sleep(1); if (DateTime.Now.Subtract(dt).TotalMilliseconds > 1500) //超时 { return new byte[0]; } } List<byte> recList = new List<byte>(); byte[] recData = new byte[m_SerialPort.BytesToRead]; m_SerialPort.Read(recData, 0, recData.Length); recList.AddRange(recData); int length = recData[1] + 2; //报文数据总长度 while (recList.Count < length) { if (m_SerialPort.BytesToRead > 0) { recData = new byte[m_SerialPort.BytesToRead]; m_SerialPort.Read(recData, 0, recData.Length); recList.AddRange(recData); } Thread.Sleep(1); } return recList.ToArray(); } #endregion #region 向串口发送数据 /// <summary> /// 向串口发送数据 /// </summary> /// <param name="cmd">待发送的命令</param> /// <param name="SN">序列号</param> private void WritePort(Cmd cmd, byte SN) { //发送数据 List<byte> sendData = cmd.Data; sendData[1] = (byte)sendData.Count; sendData[2] = SN; byte[] checkCode = CommonUtil.CalCheckCode(sendData, sendData.Count); sendData.AddRange(checkCode); if (cmd.Mt != null) { m_WaitResultMTList.Add(cmd.Mt); } m_SerialPort.Write(sendData.ToArray(), 0, sendData.Count); LogHelper.Log(LogMsgType.Info, true, sendData.ToArray()); } #endregion #region 发送ACK消息 /// <summary> /// 发送ACK消息 /// </summary> /// <param name="SN">序列号</param> private void SendACK(byte SN) { List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x40, 0x80 }; WritePort(new Cmd(sendData), SN); } #endregion #region Init 初始化 /// <summary> /// 初始化 /// </summary> /// <param name="com">串口号(例:COM1)</param> public void Init(string com) { if (m_SerialPort == null) { m_SerialPort = new SerialPort(com, 9600, Parity.None, 8, StopBits.One); m_SerialPort.ReadBufferSize = 1024; m_SerialPort.WriteBufferSize = 1024; m_SerialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived); } if (!m_SerialPort.IsOpen) { m_SerialPort.Open(); } GET_SETUP(); CONTROL_IND(0x13, new byte[] { 0x00 }); //初始化完成标志 GET_STATUS(); SetDecimalPlaces(2); //设置小数点位数 } #endregion #region Close 关闭连接 /// <summary> /// 关闭连接 /// </summary> public void Close() { m_SerialPort.Close(); } #endregion #region 接收串口数据 /// <summary> /// 接收串口数据 /// </summary> /// <param name="type">消息类型</param> /// <param name="subtype">消息子类型</param> public byte[] Receive(byte type, byte subtype) { return m_ReceiveDataCollection.Get(type, subtype); } /// <summary> /// 接收串口数据 /// </summary> /// <param name="type">消息类型</param> /// <param name="subtype">消息子类型</param> public byte[] WaitReceive(byte type, byte subtype) { DateTime time = DateTime.Now; while (true) { byte[] receiveData = m_ReceiveDataCollection.Get(type, subtype); if (receiveData != null) return receiveData; if (DateTime.Now.Subtract(time).TotalMinutes > 3) return null; Thread.Sleep(50); } } /// <summary> /// 接收串口数据 /// </summary> /// <param name="type">消息类型</param> public byte[] WaitReceive(byte type) { DateTime time = DateTime.Now; while (true) { byte[] receiveData = m_ReceiveDataCollection.Get(type); if (receiveData != null) return receiveData; if (DateTime.Now.Subtract(time).TotalMinutes > 3) return null; Thread.Sleep(50); } } #endregion #region 判断消息是否发送成功 /// <summary> /// 判断消息是否发送成功 /// </summary> public bool SendSuccess(byte type, byte subtype) { DateTime time = DateTime.Now; while (true) { if (DateTime.Now.Subtract(time).TotalMinutes > 3) { return false; } byte[] ack = m_ReceiveDataCollection.Get(type, subtype); byte[] nak = m_ReceiveDataCollection.Get(type, subtype); if (ack != null) return true; if (nak != null) return false; Thread.Sleep(1); } } #endregion } }</div>
第2部分:接收串口数据,并响应货机,向货机发送数据
using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Text; using MachineJPDll.Models; using MachineJPDll.Utils; /* * VMC->PC数据的接收,货机事件的分发 */ namespace MachineJPDll { partial class MachineJP { #region serialPort_DataReceived /// <summary> /// 数据接收事件的方法 /// </summary> public void serialPort_DataReceived(object obj, SerialDataReceivedEventArgs args) { byte[] receiveData = ReadPort(); if (CommonUtil.ValidReceiveData(receiveData)) //只处理验证正确的数据,不正确的数据抛弃不处理 { LogHelper.Log(LogMsgType.Info, false, receiveData); byte SN = CommonUtil.GetSN(receiveData); MT mt = new MT(receiveData); #region 轮询(POLL) if (mt.Type == 0x03) { if (m_CommandList.Count > 0) { WritePo