常用小功能之串口数据传输

xiaoxiao2025-08-09  31

COM1

设计页面:

源码:

public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { try { SerialPort sp = new SerialPort(this.txtPort.Text, 9600, Parity.None, 8, StopBits.One); //SerialPort sp = new SerialPort(this.txtPort.Text); byte[] m = new byte[13]; m[0] = 0x42; byte[] cardnoArr = System.Text.Encoding.ASCII.GetBytes(this.txtMsg.Text); for (int i = 1; i <= 10; i++ ) { if (i <= cardnoArr.Length) { m[i] = cardnoArr[i - 1]; } else { m[i] = 0x20; } } int v = 0; for (int i = 0; i < 11; i++ ) { v += m[i]; } m[12] = (byte)(v); m[11] = (byte)(v >> 8); //打开新的串行端口连接 sp.Open(); //丢弃来自串行驱动程序的接受缓冲区的数据 sp.DiscardInBuffer(); //丢弃来自串行驱动程序的传输缓冲区的数据 sp.DiscardOutBuffer(); //使用缓冲区的数据将指定数量的字节写入串行端口 sp.Write(m, 0, m.Length); //关闭端口连接 sp.Close(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } private string StringToHexString(string s, Encoding encode) { byte[] b = encode.GetBytes(s);//按照指定编码将string编程字节数组 string result = string.Empty; for (int i = 0; i < b.Length; i++)//逐字节变为16进制字符,以%隔开 { result += "%" + Convert.ToString(b[i], 16); } return result; }

COM2

设计页面

代码:

public Form1() { InitializeComponent(); } private ILog logger = LogManager.GetLogger(typeof(Form1)); /// <summary> /// 接收串口数据线程 /// </summary> private Thread recMsgThread; /// <summary> /// 解析数据处理队列 /// </summary> private WorkQueue<byte[]> parseDataProcQueue = new WorkQueue<byte[]>(); /// <summary> /// 刷卡事件处理队列 /// </summary> private WorkQueue<long> creditCardEventProcQueue = new WorkQueue<long>(); private SerialPort sp = null; private bool shouldStop = false; private void Form1_Load(object sender, EventArgs e) { parseDataProcQueue.WorkSequential = true; parseDataProcQueue.UserWork += new UserWorkEventHandler<byte[]>(ParsedData_UserWork); creditCardEventProcQueue.UserWork += new UserWorkEventHandler<long>(CreditCardEvent_UserWork); } /// <summary> /// 接收串口数据 /// </summary> private void RecPortMsg() { byte[] b; byte[] recArr; while (!shouldStop) { try { sp = new SerialPort(txtPort.Text, 9600, Parity.None, 8, StopBits.One); //sp = new SerialPort(txtPort.Text); //打开新的串行端口连接 sp.Open(); logger.Info(string.Format("SerialPort open success.{0}", txtPort.Text)); //丢弃来自串行驱动程序的接受缓冲区的数据 sp.DiscardInBuffer(); //丢弃来自串行驱动程序的传输缓冲区的数据 sp.DiscardOutBuffer(); StringBuilder sb = new StringBuilder(); while (!shouldStop) { b = new byte[32]; //从串口输入缓冲区读取一些字节 int n = sp.Read(b, 0, b.Length); if(n > 0) { recArr = new byte[n]; for (int i = 0; i < n; i++ ) { recArr[i] = b[i]; } //放入解析队列 parseDataProcQueue.EnqueueItem(recArr); } //当前线程挂起200毫秒 System.Threading.Thread.Sleep(200); } } catch (Exception ex) { logger.Error(string.Format("RecPortMsg error.{0}", ex.Message)); } System.Threading.Thread.Sleep(2000); } if (null != sp) { //关闭端口连接 sp.Close(); } } //10进制卡号按以下格式编码(16进制):42 xx xx xx xx xx xx 20 20 20 20 HH LL //注:通信包定长13bytes,包头以'B'开始,16进制0x42; //后跟10位卡号,以16进制ASCII码值发送; //卡号不满10位时,后补0x20(空格); //校验码计算:前11位的16进制值累加,2bytes,高位bytes+低位bytes。 //数据包 private byte[] dataPacket = new byte[13]; private int i_data = 0; private bool hasFind = false; /// <summary> /// 解析数据-工作处理 /// </summary> private void ParsedData_UserWork(object sender, WorkQueue<byte[]>.EnqueueEventArgs e) { byte bStart = 0x42; //通讯包头部 byte[] recArr = e.Item; try { foreach (byte b in recArr) { if (b == bStart) { hasFind = true; dataPacket = new byte[13]; i_data = 0; } if (hasFind) { if (i_data <= 12) { dataPacket[i_data++] = b; if (i_data == 13) //完整包 { //校验数据有效性 if (CheckDataValid(dataPacket)) { //解析获取卡号 long cardno = parseCardNo(dataPacket); logger.InfoFormat("Rec CardNo:{0}", cardno); //回复 if (null != sp) { byte[] postdata = new byte[2]; //返回成功 postdata[0] = 0x44; postdata[1] = 0x59; sp.Write(postdata, 0, postdata.Length); } //放入刷卡事件处理队列 creditCardEventProcQueue.EnqueueItem(cardno); } hasFind = false; } } } } } catch (Exception ex1) { logger.Error(string.Format("Parse data error.{0}", ex1.Message)); } } /// <summary> /// 校验数据包是否是有效的 /// 校验码计算:前11位的16进制值累加,2bytes,高位bytes+低位bytes。 /// </summary> /// <param name="dataPacket"></param> /// <returns></returns> private bool CheckDataValid(byte[] dataPacket) { bool valid = false; int v = 0; for (int i = 0; i < 11; i++) { v += dataPacket[i]; } byte LL = (byte)(v); byte HH = (byte)(v >> 8); if (dataPacket[11] == HH && dataPacket[12] == LL) { valid = true; } return valid; } //解析获取卡号 private long parseCardNo(byte[] dataPacket) { byte bSpace = 0x20; //空格 //获取卡号 string s_cardno = ""; long cardno = 0; for (int i = 1; i < 11; i++) { if (dataPacket[i] != bSpace) { s_cardno += (char)dataPacket[i]; } } cardno = long.Parse(s_cardno); return cardno; } /// <summary> /// 刷卡事件-工作处理 /// </summary> private void CreditCardEvent_UserWork(object sender, WorkQueue<long>.EnqueueEventArgs e) { long cardno = e.Item; ShowCardNo(cardno.ToString()); } /// <summary> /// 显示卡号 /// </summary> /// <param name="msg"></param> private void ShowCardNo(string msg) { if (InvokeRequired) { Invoke(new MethodInvoker(delegate { ShowCardNo(msg); })); return; } txtMsg.Text = msg; } private void button1_Click(object sender, EventArgs e) { recMsgThread = new Thread(new ThreadStart(RecPortMsg)); recMsgThread.Start(); button1.Enabled = false; button2.Enabled = true; } private void button2_Click(object sender, EventArgs e) { Stop(); button2.Enabled = false; button1.Enabled = true; } private void Stop() { this.shouldStop = true; if (null != recMsgThread) { recMsgThread.Abort(); } if (null != sp) { //关闭端口连接 sp.Close(); } } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { Stop(); }
转载请注明原文地址: https://www.6miu.com/read-5034544.html

最新回复(0)