原文載自:https://www.cnblogs.com/shuaiheng/p/7443992.html
主要用於學習記錄
下面圖片是利用窗口控件所設計的界面。主要就是了解一下串口通信的機制。主要能夠實現發送數據和接收數據的功能。控件不熟悉的就去網上查找和學習。
下面是源代碼:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace SerialPortTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
SerialPort sp1 = new SerialPort(); //這個是定義的全局變量;
private void Form1_Load(object sender, EventArgs e) //窗體加載
{
string[] str = SerialPort.GetPortNames();//檢查是否含有串口
if (str == null)
{
MessageBox.Show("本機沒有串口!", "Error");
return;
}
foreach (string s in System.IO.Ports.SerialPort.GetPortNames()) //添加串口
{
cbSerial.Items.Add(s); //獲取有多少個COM口,添加到控件里
}
cbBaudRate.Items.Add("9600"); //對波特率,數據位,停止偉這幾個控件里面的值進行初始化顯示 這樣就可以避免我們調試時反復的對他們進行輸入
cbDataBits.Items.Add("8");
cbStop.Items.Add("1");
cbParity.Items.Add("無");
cbSerial.SelectedIndex = 0; //獲取或是指當前選定項的索引//串口設置默認選擇項
cbBaudRate.SelectedIndex = 0;
cbDataBits.SelectedIndex = 0;
cbStop.SelectedIndex = 0;
cbParity.SelectedIndex = 0;
radio1.Checked = true; //發送數據的“16進制”單選按鈕
rbRcvStr.Checked = true;
Control.CheckForIllegalCrossThreadCalls = false;
sp1.DataReceived += new SerialDataReceivedEventHandler(sp1_DataReceived); //訂閱委托
}
private void btnSwitch_Click(object sender, EventArgs e)
{
//SerialPort sp1 = new SerialPort();
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");
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 = "打開串口";
}
}
private void btnSend_Click(object sender, EventArgs e) //等待修改
{
if (!sp1.IsOpen) //如果沒打開
{
MessageBox.Show("請先打開串口!", "Error");
return;
}
String strSend = txtSend.Text;
if (radio1.Checked == true) //“16進制發送” 按鈕
{
//處理數字轉換,目的是將輸入的字符按空格、“,”等分組,以便發送數據時的方便(此處轉的比較麻煩,有高見者,請指點!)
string sendBuf = strSend;
string sendnoNull = sendBuf.Trim();
string sendNOComma = sendnoNull.Replace(',', ' '); //去掉英文逗號
string sendNOComma1 = sendNOComma.Replace(',', ' '); //去掉中文逗號
string strSendNoComma2 = sendNOComma1.Replace("0x", ""); //去掉0x
strSendNoComma2.Replace("0X", ""); //去掉0X
string[] strArray = strSendNoComma2.Split(' ');
int byteBufferLength = strArray.Length;
for (int i = 0; i <strArray.Length;i++)
{
if (strArray[i]=="")
{
byteBufferLength--;
}
}
byte[] byteBuffer = new byte[byteBufferLength];
int ii = 0;
for (int i = 0; i < strArray.Length; i++) //對獲取的字符做相加運算
{
Byte[] bytesOfStr = Encoding.Default.GetBytes(strArray[i]);
int decNum = 0;
if (strArray[i] == "")
{
continue;
}
else
{
decNum = Convert.ToInt32(strArray[i], 16); //strArray[i] == 12時,temp == 18
}
try //防止輸錯,使其只能輸入一個字節的字符,即只能在txtSend里輸入 “eb 90”等字符串,不能輸入“123 2345”等超出字節范圍的數字
{
byteBuffer[ii] = Convert.ToByte(decNum);
}
catch (System.Exception ex)
{
MessageBox.Show("字節越界,請逐個字節輸入!", "Error");
return;
}
ii++;
}
sp1.Write(byteBuffer, 0, byteBuffer.Length);
}
else //以字符串形式發送時
{
sp1.WriteLine(txtSend.Text); //寫入數據
}
}
void sp1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (sp1.IsOpen) //嚴謹性
{
byte[] byteRead = new byte[sp1.BytesToRead]; //BytesToRead:sp1接收的字符個數
if (radio2.Checked) //'發送字符串'單選按鈕
{
txtRcv.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); //讀取數據
sp1.DiscardInBuffer(); //清空SerialPort控件的Buffer
string strRcv = null;
for (int i = 0; i < receivedData.Length; i++) //窗體顯示
{
strRcv += receivedData[i].ToString("X2"); //16進制顯示
}
txtRcv.Text += strRcv + "\r\n";
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message, "出錯提示");
txtSend.Text = "";
}
}
}
else
{
MessageBox.Show("請打開某個串口", "錯誤提示");
}
DateTime dt = DateTime.Now;
//txtRcv.Text += dt.GetDateTimeFormats('f')[0].ToString() + "\r\n";
//txtRcv.SelectAll();
//txtRcv.SelectionColor = Color.Blue; //改變字體的顏色
}
private void btnClear_Click(object sender, EventArgs e)
{
//comboBox1.Items.Clear();
txtRcv.Clear();
// foreach (Control ctrl in Controls)//或為groupBox1.Controls/panel1.Controls 可以做判斷
//{
// if (ctrl is TextBox)
// ctrl.Text = "";
//}
}
private void btnExit_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}