//线程执行读取串口数据事件 private void RecvData_DoWork(object sender, DoWorkEventArgs e) { SerialToTextBox Example = (SerialToTextBox)e.Argument; Example.Port.DiscardOutBuffer();//先将串口驱动中的缓冲数据丢弃 string NextBuf = string.Empty; byte[] DataBuff = new byte[51200]; int index = 0; while (Example.Port.IsOpen) //如果该串口处于打开/连接状态,则进行数据的接收 { int n = Example.Port.BytesToRead; //字节数 if (n > 0) { //Console.WriteLine(n); byte[] buf = new byte[n]; //获取到串口缓冲区上接收到的字节数量 Example.Port.Read(buf, 0, n); //buffer offset count Console.WriteLine(buf.Length); DealRecvData(buf, ref NextBuf, ref index, Example, ref DataBuff); //根据具体需求从这些sector中分别读取PageData和其他的统计数据 } else { Thread.Sleep(300); } } }
//打印log,以及将log写入文件 private void LogPrint(string Log, SerialToTextBox Example) { string temp = Regex.Replace(Log, @"SINGLE_START_S_N", ""); string result = Regex.Replace(temp, @"SINGLE_START_S_S", ""); temp = Regex.Replace(result, @"SINGLE_START_S_R", ""); //委托主线程对UI控件进行操作 this.BeginInvoke(new System.Threading.ThreadStart(delegate() { if (Example.PrintBox.Text.Length > 0xFFFF) { Example.PrintBox.Clear(); } Example.PrintBox.Text += temp; })); try { string time = "[" + DateTime.Now.ToString() + "." + DateTime.Now.Millisecond.ToString("000") + "] "; //使用正则表达式在所有的换行符后加入当前时间戳 string WriteText = Regex.Replace(temp, @"\n", "\n" + time); File.AppendAllText(SerialToPath[Example.Port.PortName], WriteText); } catch { return; } }
//运行脚本 //运行脚本需要判断当前连接了几个串口,然后针对于每个串口需要新建一个窗口,每个串口对应一接收数据的线程。 //所有的串口发送数据只用一个线程,先解析脚本,将所有需要发送的数据添加到list中,然后循环发送所有的CMD。 private void RunBtn_Click(object sender, EventArgs e) { if (PortList.Count == 0) { MessageBox.Show("please open serial port first !!!", "WARNING", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } RunBtn.Enabled = false; SendToolStripButton.Enabled = false; //ManualFlag = -1; WriteDataList.Clear(); PageLength.Clear(); ComDataPath.Clear(); //处理脚本 if (!ScriptIdentify()) { RunBtn.Enabled = true; SendToolStripButton.Enabled = true; return; } int i = 5, j = 5; //遍历每个串口 foreach (SerialPort port in PortList.Values) { if (!SerialToPath.ContainsKey(port.PortName)) { //创建输出打印框 PrintLog PortLogBox = new PrintLog(); PortLogBox.Top = i; PortLogBox.Left = j; PortLogBox.Text = port.PortName; PortLogBox.Show(); //创建写入本地文件句柄 CreateFileHandle(port.PortName); //接收数据线程 BackgroundWorker backgroundWorker = new BackgroundWorker(); backgroundWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.RecvData_DoWork); SerialToTextBox Argument = new SerialToTextBox(port, PortLogBox.PrintLogBox); backgroundWorker.RunWorkerAsync(Argument); i += 20; j += 20; } this.Activate(); } flashToolStripMenuItem.Enabled = false; //发送数据线程 BackgroundWorker SendWoker = new BackgroundWorker(); SendWoker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.SendData_DoWork); IsRecvSingle = true; SendWoker.RunWorkerAsync(); }
//判断是否收到了下一个cmd的命令 private void RecvNextCmd(ref string NextBuffer, SerialToTextBox Example) { if (NextBuffer.Contains("SINGLE_START_S_N")) { lock (locker) { IsSendData[Example.Port.PortName] = true; IsRecvSingle = true; } LogPrint(NextBuffer, Example); NextBuffer = string.Empty; } }
/** * Data:从串口缓冲区读上来的字节数 * NextBuffer:指向一个空的字符串 * index:索引值,指向当前DataBuffer这个目标字节数组的偏移量 * Example:串口结构体 * Databuffer:目标字节数组 */ //每一次解析一个数据包 private void DealRecvData(byte[] Data, ref string NextBuffer, ref int index, SerialToTextBox Example, ref byte[] DataBuffer) { string StartFlag = "SINGLE_START_S_S"; if (Data.Length == 0) { return; } else if (IsPageRead[Example.Port.PortName])//每个串口的接收数据的标志 { //发送过readpage CMD,解析接收到的数据,收到开始写入数据后将数据写入 if (ComDataStart[Example.Port.PortName]) { if (ComWriteNum[Example.Port.PortName] + Data.Length < ReadPageNum) //串口接收的数据没达到pagesize { Buffer.BlockCopy(Data, 0, DataBuffer, ComWriteNum[Example.Port.PortName], Data.Length); //追加 ComWriteNum[Example.Port.PortName] += Data.Length; //长度递增 } else if (ComWriteNum[Example.Port.PortName] + Data.Length == ReadPageNum) //如果达到pagesize则进行文件的写入 { Buffer.BlockCopy(Data, 0, DataBuffer, ComWriteNum[Example.Port.PortName], Data.Length); PageDataWrite(ComDataPath[Example.Port.PortName].FirstOrDefault(), DataBuffer); //串口对应的路径删除 ComDataPath[Example.Port.PortName].RemoveAt(0); //串口对应的当前写入长度置0 ComWriteNum[Example.Port.PortName] = 0; //串口对应的开始信号关闭 ComDataStart[Example.Port.PortName] = false; //串口对应的pageread的信号关闭 IsPageRead[Example.Port.PortName] = false; if (CmdList[Example.Port.PortName].Count == 0)//没有要发送的函数指令 { IsRecvSingle = false; //IsSendData[Example.Port.PortName] = false; } } else//此次接收完数据后,大于pagesize { int num = ReadPageNum - ComWriteNum[Example.Port.PortName];//剩余量 Buffer.BlockCopy(Data, 0, DataBuffer, ComWriteNum[Example.Port.PortName], num);//src,srcOffset,dst,dstOffset,count //写入文件,只写一个page的数据 PageDataWrite(ComDataPath[Example.Port.PortName].FirstOrDefault(), DataBuffer); //移除输出路径 ComDataPath[Example.Port.PortName].RemoveAt(0); //待写长度置0 ComWriteNum[Example.Port.PortName] = 0; //数据接收开始信号关闭 ComDataStart[Example.Port.PortName] = false; //发送pageread信号关闭 IsPageRead[Example.Port.PortName] = false; byte[] temp = new byte[Data.Length - num]; Buffer.BlockCopy(Data, num, temp, 0, Data.Length - num); NextBuffer += Encoding.ASCII.GetString(temp); RecvNextCmd(ref NextBuffer, Example); if (CmdList[Example.Port.PortName].Count == 0) { IsRecvSingle = false; //IsSendData[Example.Port.PortName] = false; } } } else { for (int i = 0; i < Data.Length; i++) { if (index == 16) { index = 0; ComDataStart[Example.Port.PortName] = true; //匹配到完整的StartFlag后,将接受数据写入文件的标志置为True int count = Data.Length - i > ReadPageNum ? ReadPageNum : Data.Length - i; Buffer.BlockCopy(Data, i, DataBuffer, 0, count); //只拷贝一个Page的数据到DataBuffer上 ComWriteNum[Example.Port.PortName] += count; if (count == ReadPageNum) { PageDataWrite(ComDataPath[Example.Port.PortName].FirstOrDefault(), DataBuffer); ComDataPath[Example.Port.PortName].RemoveAt(0); ComWriteNum[Example.Port.PortName] = 0; ComDataStart[Example.Port.PortName] = false; //串口读取数据标志置为0 IsPageRead[Example.Port.PortName] = false; //串口接收数据标志置为0 byte[] tmpByte = new byte[Data.Length - ComWriteNum[Example.Port.PortName] - i]; Buffer.BlockCopy(Data, ReadPageNum + i, tmpByte, 0, Data.Length - ReadPageNum - i); NextBuffer += Encoding.ASCII.GetString(tmpByte); if (CmdList[Example.Port.PortName].Count == 0) { IsRecvSingle = false; //IsSendData[Example.Port.PortName] = false; } } break; } if (Data[i] == Convert.ToByte(StartFlag[index])) { index++; } else { index = 0; } NextBuffer += (char)Data[i]; } RecvNextCmd(ref NextBuffer, Example); } } else//判断是否接收到下一个信号以及将数据委托主线程打印 { NextBuffer += Encoding.ASCII.GetString(Data); RecvNextCmd(ref NextBuffer, Example); } }