全是我个人理解,不对的请大神指教
流量计说明书:
实现UI界面:
添加using:
using System.IO.Ports; using INIFILE; using System.Text.RegularExpressions; using System.IO; using Microsoft.Office; using System.Reflection;
//实例化串口
SerialPort sp1 = new SerialPort();
窗体加载时:
private void Form1_Load(object sender, EventArgs e) { INIFILE.Profile.LoadProfile();//加载所有 // 预置波特率 switch (Profile.G_BAUDRATE) { case "300": cbBaudRate.SelectedIndex = 0; break; case "600": cbBaudRate.SelectedIndex = 1; break; case "1200": cbBaudRate.SelectedIndex = 2; break; case "2400": cbBaudRate.SelectedIndex = 3; break; case "4800": cbBaudRate.SelectedIndex = 4; break; case "9600": cbBaudRate.SelectedIndex = 5; break; case "19200": cbBaudRate.SelectedIndex = 6; break; case "38400": cbBaudRate.SelectedIndex = 7; break; case "115200": cbBaudRate.SelectedIndex = 8; break; default: { MessageBox.Show("波特率预置参数错误。"); return; } } //预置波特率 switch (Profile.G_DATABITS) { case "5": cbDataBits.SelectedIndex = 0; break; case "6": cbDataBits.SelectedIndex = 1; break; case "7": cbDataBits.SelectedIndex = 2; break; case "8": cbDataBits.SelectedIndex = 3; break; default: { MessageBox.Show("数据位预置参数错误。"); return; } } //预置停止位 switch (Profile.G_STOP) { case "1": cbStop.SelectedIndex = 0; break; case "1.5": cbStop.SelectedIndex = 1; break; case "2": cbStop.SelectedIndex = 2; break; default: { MessageBox.Show("停止位预置参数错误。"); return; } } //预置校验位 switch(Profile.G_PARITY) { case "NONE": cbParity.SelectedIndex = 0; break; case "ODD": cbParity.SelectedIndex = 1; break; case "EVEN": cbParity.SelectedIndex = 2; break; default: { MessageBox.Show("校验位预置参数错误。"); return; } } //检查是否含有串口 string[] str = SerialPort.GetPortNames(); if (str == null) { MessageBox.Show("本机没有串口!", "Error"); return; } //添加串口项目 foreach (string s in System.IO.Ports.SerialPort.GetPortNames()) {//获取有多少个COM口 //System.Diagnostics.Debug.WriteLine(s); cbSerial.Items.Add(s); } //串口设置默认选择项 cbSerial.SelectedIndex = 1; //note:获得COM9口,但别忘修改 //cbBaudRate.SelectedIndex = 5; // cbDataBits.SelectedIndex = 3; // cbStop.SelectedIndex = 0; // cbParity.SelectedIndex = 0; sp1.BaudRate = 9600; Control.CheckForIllegalCrossThreadCalls = false; //这个类中我们不检查跨线程的调用是否合法(因为.net 2.0以后加强了安全机制,,不允许在winform中直接跨线程访问控件的属性) sp1.DataReceived += new SerialDataReceivedEventHandler(sp1_DataReceived); //sp1.ReceivedBytesThreshold = 1; radio1.Checked = true; //单选按钮默认是选中的 rbRcvStr.Checked = true; //准备就绪 sp1.DtrEnable = true; sp1.RtsEnable = true; //设置数据读取超时为1秒 sp1.ReadTimeout = 1000; sp1.Close(); }定义缓冲器和excel实例:
List<byte> buffer = new List<byte>(4096); Microsoft.Office.Interop.Excel.Application excelApp = null; // 定义Application 对象,此对象表示整个Excel 程序 Microsoft.Office.Interop.Excel.Workbook workBook=null;// 定义Workbook对象,此对象代表工作薄 //Microsoft.Office.Interop.Excel.Worksheet ws = new Microsoft.Office.Interop.Excel.Worksheet(); // 定义Worksheet 对象,此对象表示Execel 中的一张工作表 Microsoft.Office.Interop.Excel.Worksheet ws = null;用p表示存储位置
private int p = 2;//存储位置指针;
写入excel的方法:
private void wrExcel(string AccFlowdata,string Flowdata) { string time = System.DateTime.Now.ToLongTimeString().ToString(); ws.Cells[p, 1] = time; ws.Cells[p, 2] = AccFlowdata.ToString(); ws.Cells[p, 3] = Flowdata.ToString(); p = p + 1; }
串口接收事件
void sp1_DataReceived(object sender, SerialDataReceivedEventArgs e) { if (sp1.IsOpen) //此处可能没有必要判断是否打开串口,但为了严谨性,我还是加上了 { //输出当前时间 // DateTime dt = DateTime.Now; // txtReceive.Text += dt.GetDateTimeFormats('f')[0].ToString() + "\r\n"; txtReceive.SelectAll(); txtReceive.SelectionColor = Color.Blue; //改变字体的颜色 byte[] byteRead = new byte[sp1.BytesToRead]; //BytesToRead:sp1接收的字符个数 System.Threading.Thread.Sleep(100); //在接收之前加一个延时,给计算机时间接收数据,不然会导致接收的数据显示不全。 if (rdSendStr.Checked) //'发送字符串'单选按钮 { txtReceive.Text += sp1.ReadLine() + "\r\n"; //注意:回车换行必须这样写,单独使用"\r"和"\n"都不会有效果 sp1.DiscardInBuffer(); //清空SerialPort控件的Buffer } else //'发送16进制按钮' { try { Byte[] receivedData = new Byte[sp1.BytesToRead]; //创建接收字节数组 sp1.Read(receivedData, 0, receivedData.Length); //读取数据 //string text = sp1.Read(); //Encoding.ASCII.GetString(receivedData); sp1.DiscardInBuffer(); //清空SerialPort控件的Buffer //这是用以显示字符串 // string strRcv = null; // for (int i = 0; i < receivedData.Length; i++ ) // { // strRcv += ((char)Convert.ToInt32(receivedData[i])) ; // } // txtReceive.Text += strRcv + "\r\n"; //显示信息 //} int 字节数组大小 = receivedData.Length; txtReceive.Text += "收到" + 字节数组大小 + "字节" + "\r\n"; buffer.AddRange(receivedData); if (buffer.Count == 17) { byte[] AccFlowCODint = new byte[4] {buffer[3], buffer[4], buffer[5], buffer[6] };//累积流量整数部分放在一个字节数组中 AccFlowCODint = AccFlowCODint.Reverse().ToArray(); //转换顺序 AccFlow_int = BitConverter.ToInt32(AccFlowCODint, 0);//转换成整数 byte[] AccFlowCODdec = new byte[4] { buffer[7], buffer[8], buffer[9], buffer[10] };//累积流量小数部分放在一个字节数组中 AccFlowCODdec = AccFlowCODdec.Reverse().ToArray(); //转换顺序 AccFlow_dec = BitConverter.ToSingle(AccFlowCODdec, 0); //转换成小数 byte[] FlowCOD = new byte[4] { buffer[11], buffer[12], buffer[13], buffer[14] };//瞬时流量放在一个字节数组中 FlowCOD = FlowCOD.Reverse().ToArray(); //转换顺序 Flow = BitConverter.ToSingle(FlowCOD, 0);//转换成小数 AccFlow = AccFlow_int + AccFlow_dec; txtReceive.Text += "累积流量为:" + AccFlow + "\r\n"; txtAccFlow.Text = AccFlow.ToString(); txtFlow.Text = Flow.ToString(); if (wsd==true ) { wrExcel(AccFlow.ToString(), Flow.ToString()); } buffer.Clear(); } string strRcv = null; //int decNum = 0;//存储十进制 for (int i = 0; i < receivedData.Length; i++) //窗体显示 { strRcv += receivedData[i].ToString("X2"); //16进制显示 } txtReceive.Text += strRcv + "\r\n"; } catch (System.Exception ex) { MessageBox.Show(ex.Message, "出错提示"); txtSend.Text = ""; } } } else { MessageBox.Show("请打开某个串口", "错误提示"); } }
打开串口按钮
private void btnSwitch_Click(object sender, EventArgs e) { //serialPort1.IsOpen if (!sp1.IsOpen) { try { //设置串口号 string serialName = cbSerial.SelectedItem.ToString(); sp1.PortName = serialName; //设置各“串口设置” string strBaudRate = cbBaudRate.Text; string strDateBits = cbDataBits.Text; string strStopBits = cbStop.Text; Int32 iBaudRate = Convert.ToInt32(strBaudRate); Int32 iDateBits = Convert.ToInt32(strDateBits); sp1.BaudRate = iBaudRate; //波特率 sp1.DataBits = iDateBits; //数据位 switch (cbStop.Text) //停止位 { case "1": sp1.StopBits = StopBits.One; break; case "1.5": sp1.StopBits = StopBits.OnePointFive; break; case "2": sp1.StopBits = StopBits.Two; break; default: MessageBox.Show("Error:参数不正确!", "Error"); break; } switch (cbParity.Text) //校验位 { case "无": sp1.Parity = Parity.None; break; case "奇校验": sp1.Parity = Parity.Odd; break; case "偶校验": sp1.Parity = Parity.Even; break; default: MessageBox.Show("Error:参数不正确!", "Error"); break; } if (sp1.IsOpen == true)//如果打开状态,则先关闭一下 { sp1.Close(); } //状态栏设置 tsSpNum.Text = "串口号:" + sp1.PortName + "|"; tsBaudRate.Text = "波特率:" + sp1.BaudRate + "|"; tsDataBits.Text = "数据位:" + sp1.DataBits + "|"; tsStopBits.Text = "停止位:" + sp1.StopBits + "|"; tsParity.Text = "校验位:" + sp1.Parity + "|"; //设置必要控件不可用 cbSerial.Enabled = false; cbBaudRate.Enabled = false; cbDataBits.Enabled = false; cbStop.Enabled = false; cbParity.Enabled = false; sp1.Open(); //打开串口 btnSwitch.Text = "关闭串口"; } catch (System.Exception ex) { MessageBox.Show("Error:" + ex.Message, "Error"); tmSend.Enabled = false; return; } } else { //状态栏设置 tsSpNum.Text = "串口号:未指定|"; tsBaudRate.Text = "波特率:未指定|"; tsDataBits.Text = "数据位:未指定|"; tsStopBits.Text = "停止位:未指定|"; tsParity.Text = "校验位:未指定|"; //恢复控件功能 //设置必要控件不可用 cbSerial.Enabled = true; cbBaudRate.Enabled = true; cbDataBits.Enabled = true; cbStop.Enabled = true; cbParity.Enabled = true; sp1.Close(); //关闭串口 btnSwitch.Text = "打开串口"; tmSend.Enabled = false; //关闭计时器 } }
开始保存按钮,其实是创建Excel文档,用wsd这个布尔量判断是否创建好文档
private void cbStartSave_CheckedChanged(object sender, EventArgs e) { if (cbStartSave.Checked == true) { cbStartSave.Text = "停止保存"; try { //初始化 Application 对象 excelApp excelApp = new Microsoft.Office.Interop.Excel.Application(); //在工作薄的第一个工作表上创建任务列表 workBook = excelApp.Workbooks.Add(Type.Missing); //workBook = excelApp.Workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet); ws = (Microsoft.Office.Interop.Excel.Worksheet)workBook.Worksheets[1]; ws.Name = "文件名称"; // 居中 ws.Rows.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter; // 单元格的宽度 ((Microsoft.Office.Interop.Excel.Range)ws.Columns["B", Type.Missing]).ColumnWidth = 17; ((Microsoft.Office.Interop.Excel.Range)ws.Columns["C", Type.Missing]).ColumnWidth = 17; ((Microsoft.Office.Interop.Excel.Range)ws.Columns["D", Type.Missing]).ColumnWidth = 17; ((Microsoft.Office.Interop.Excel.Range)ws.Columns["E", Type.Missing]).ColumnWidth = 17; ((Microsoft.Office.Interop.Excel.Range)ws.Columns["F", Type.Missing]).ColumnWidth = 17; ((Microsoft.Office.Interop.Excel.Range)ws.Columns["G", Type.Missing]).ColumnWidth = 17; ws.Cells[1, 1] = "时间"; ws.Cells[1, 2] = "累积流量"; ws.Cells[1, 3] = "瞬时流量"; wsd = true; } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } else { cbStartSave.Text = "开始保存"; wsd = false; string path = ""; string time = System.DateTime.Now.ToLongTimeString().ToString(); time = time.Replace(":", "-"); path = @"G:\" + time; ws.SaveAs(path + ".xls", Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value); //保存后是否打开 Excel excelApp.Visible = true; //excelApp.Quit();// 去掉 任务管理器的进程 workBook = null; p = 2; } }