//前提需要
//需要一個 serialPort 工具 可在vs自帶的工具列中獲得
//源代碼加串口工具地址:
//鏈接:https://pan.baidu.com/s/1YbfvdXEmfsJX87D-Jxljyg 提取碼:d32x
//記錄用戶打開的串口號 可改為泛型模式
string serialPortName;
//一般電腦是沒有串口號的,所以要用個軟體創建虛擬串口號
//軟體名 - Configure Virtual Serial Port Driver
波特率設定的值為 1382400,921600,460800,256000,230400,128000,115200,76800,57600,
43000,38400,19200,14400,9600,4800,1200
停止位設定的值為:1,1.5,2
資料位設定的值為:8,7,6,5
校驗位設定的值為:無,奇校驗,偶校驗
步驟:
1.設定串口的基本資料 (串口號,波特率,資料位,停止位,校驗位)
2.使用Open打開串口
3.使用串口工具的DataReceived()事件進行資料的接收
4.創建發送資料 Write() ,一般發送的是byte陣列
5.使用Close關閉串口
界面:

?
//一
//在視窗Load事件中,設定串口基本資料的默認值
//1.拿到電腦上可以使用的串口號,并賦值給視窗的串口下拉串列中,默認選項索引為0
string[] prots = System.IO.Ports.SerialPort.GetPortNames();
this.cbPort.Items.AddRange(prots);
this.cbPort.SelectedIndex = this.cbPort.Items.Count > 0 ? 0 : -1;
//2.設定波特率,停止位,資料位,校驗位的默認值,
this.cbBaud.Text = "115200";
this.cbStopBit.Text = "1";
this.cbDataBit.Text = "8";
this.cbComparable.Text = "無";
//二
//設定打開串口和關閉串口按鈕的單擊事件
//為串口拿到基本資料
serialPort .PortName = this.cbPort.Text;//串口號
serialPortName = this.cbPort.Text;//記錄用戶打開的串口號
serialPort.BaudRate = int.Parse(this.cbBaud.Text);//波特率
serialPort.DataBits = int.Parse(this.cbDataBit.Text);//資料位
//設定停止位
if (this.cbStopBit.Text == "1") { serialPort.StopBits = StopBits.One; }
else if (this.cbStopBit.Text == "1.5") { serialPort.StopBits = StopBits.OnePointFive; }
else if (this.cbStopBit.Text == "2") { serialPort.StopBits = StopBits.Two; }
//設定奇偶校驗
if (this.cbComparable.Text == "無") { serialPort.Parity = Parity.None; }
else if (this.cbComparable.Text == "奇校驗") { serialPort.Parity = Parity.Odd; }
else if (this.cbComparable.Text == "偶校驗") { serialPort.Parity = Parity.Even; }
//打開串口 只需要使用Open打開串口
serialPort1.Open();
this.btnOpenStat.Text = "關閉串口";
//如果按鈕的Text為 關閉串口的話
serialPort.Close();//Close() - 關閉串口
//三 本次串口的簡單資料協議 1 - 字串 bp - 醫療資料 2 - 檔案
//通過串口工具自帶的DataReceived事件進行串口的資料接收
//這次的是自己定義的資料協議,一般都是用公司默認的協議 或者RS232和RS485
//獲取可以讀取的位元組數 默認最大值是4096 如果想要更改可以直接改變串口的ReadBufferSize屬性
int len = serialPort.BytesToRead;
if(len == serialPort.ReadBufferSize){
MessageBox.Show("程式最多只能接受"+serialPort1.ReadBufferSize+"位元組的資料!","提示");
return;
}
//拿到資料,Read()
byte[] buff = new byte[len];
serialPort.Read(buff,0,len);
//如果選中了顯示時間就賦值,沒有就算
string DateNow = string.Empty;
//根據協議進行判斷
if(buff[0]==1){
//拿出原來的資料并去除協議部分 然后放入另一個byte[]陣列中
byte[] result = new byte[len];
Buffer.BlockCopy(buff,1,result,0,buff.Length-1);
//將byte陣列保存可讀string 根據自己的編碼格式進行轉碼
string str = Encoding.Default.GetString(result);
//將資料分割為string[] 判斷是否為醫療資料
string[] strPle = str.Split(',');
if(strPle[0]=="bp"){
//放入方法中,重新拼裝成可用資料
str = RecHBpData(strPle);
}
//由于我們的接收資料的事件是在一個子執行緒里面的,
//所以需要Invoke才能給我們主執行緒創建的控制元件賦值
//當然你也可以使用InvokeRequired()來判斷是否為主執行緒創建的控制元件,我這里就沒使用了
Invoke(new Action(() => {
//是否顯示時間
if(this.ckDateTime.Checked){
DateNow = "\r\n" + DateTime.Now.ToString();
}
//是否為16進制顯示
if(this.checkBox1.Checked){
this.txtMsg.AppendText(DateNow + "\r\n" + byteToHexStr(buff));
}
//默認是使用字串顯示
else{
this.txtMsg.AppendText(DateNow + "\r\n" + str);
}
})));
}
//如果傳送的檔案的話
else if(buff[0]==2){
ProcessRecieveFile(buff);
}
//一般呢,這些方法是放在一個方法類別庫里面,但是我懶得放就在一個類里面了
#region 封裝的方法
/// <summary>
/// 傳輸的是檔案就進行檔案的操作
/// </summary>
/// <param name="data">資料流</param>
public void ProcessRecieveFile(byte[] data)
{
using (SaveFileDialog dialog = new SaveFileDialog())
{
dialog.DefaultExt = "txt";
dialog.Filter = "文本檔案(*.txt)|*.txt|所有檔案(*.*)|*.*";
//由于大部分可能不是主執行緒,所以我們要加this,不然不會彈出保存框
if (dialog.ShowDialog(this) != DialogResult.OK)
{
return;
}
byte[] result = new byte[data.Length - 1];
Buffer.BlockCopy(data, 1, result, 0, data.Length - 1);
File.WriteAllBytes(dialog.FileName, result);
}
}
#region 封裝 資料定義的協議
public static string RecHBpData(string[] strPle)
{
string str = string.Empty;
//判斷儀器
str += $"{StaticConstant.DicMedicalnoun[strPle[1]]} ";
//增加時間
str += " " + strPle[2] + " " + strPle[3] + "\r\n";
//增加具體資料
str += $"{StaticConstant.DicMedicalnoun[strPle[4]]}: {strPle[5].TrimStart('0')} \r\n{StaticConstant.DicMedicalnoun[strPle[6]]}: {strPle[7].TrimStart('0')}";
return str;
}
#endregion
/// <summary>
/// 位元組陣列轉16進制字串
/// </summary>
/// <param name="bytes">byte陣列</param>
/// <returns>16進制顯示形式</returns>
public static string byteToHexStr(byte[] bytes)
{
string retuenStr = "";
try
{
if (bytes != null)
{
for (int i = 0; i < bytes.Length; i++)
{
retuenStr += bytes[i].ToString("X2") + " ";//變成16進制,兩個中間用空格隔開
}
}
return retuenStr;
}
catch (Exception ex)
{
return retuenStr;
}
}
/// <summary>
/// 字串轉16進制格式,不夠自動前面補0
/// </summary>
/// <param name="hexString"></param>
/// <returns></returns>
public static byte[] strToHexByte(string hexString)
{
int i;
if ((hexString.Length % 2) != 0)
{//奇數個
byte[] returnBytes = new byte[(hexString.Length + 1) / 2];
try
{
for (i = 0; i < hexString.Length - 1; i++)
{
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
i = i * 2;
}
returnBytes[returnBytes.Length - 1] = Convert.ToByte(hexString.Substring(hexString.Length - 1, 1).PadLeft(2, '0'), 16);
}
catch (Exception)
{
MessageBox.Show("含有非16進制字符", "提示");
return null;
}
return returnBytes;
}
else
{
byte[] returnBytes = new byte[(hexString.Length) / 2];
try
{
for (i = 0; i < hexString.Length; i++)
{
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
}
}
catch (Exception)
{
MessageBox.Show("含有非16進制字符", "提示");
return null;
}
return returnBytes;
}
}
#endregion
//我的醫療資料的封裝是放在組態檔中,一般我們都是放在資料庫中,不過我就做個小學習工具就 //沒做到資料庫里面了
//四 發送資料
//發送資料,我這邊分為發送檔案和發送字串
//1.發送字串
string str = this.txtSendMsg.Text.Trim().Tostring();
try{
if(str.Length > 0){
//16進制發送
if(this.ckSend.Checked){
byte[] byt = strToHexBytes(str);
byte[] result = new byte[byt.Length+1];
//加上資料協議
result[0] = 1;
//資料轉移
Buffer.BlockCopy(byt,0,result,1,byt.Lengt);
//發送資料,byte形式發送
serialPort.Write(result,0,result.Length);
}
//默認字串發送
else{
//根據自己的編碼格式編碼
byte[] dataByte = Encoding.Default.GetBytes(str);
byte[] result = new byte[dataByte.Length + 1];
//加上資料協議
result[0] = 1;
Buffer.BlockCopy(dataByte ,0,result,1,dataByte .Lengt);
//發送資料,byte形式發送
serialPort.Write(result,0,result.Length);
}
}
}catch(Exception ex){}
//2.發送檔案
try{
using(OpenFileDialog dialog = new OpenFileDialog()){
if(dialog.ShowDialog(this) != DialogResult.OK){
return;
}
byte[] data = https://www.cnblogs.com/namelessblog/p/File.ReadAllBytes(dialog.FileName);
byte[] result = new byte[data.Length + 1];
result[0] = 2;
Buffer.BlockCopy(data,0,result,1,data.Length);
serialPort.Write(result,0,result.Lenght);
}
}catch(Exception ex){
MessageBox.Show(ex.Message);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/9637.html
標籤:C#
