一、串口通信簡介
? ??? ?串行接口(串口)是一種可以將接受來自CPU的并行數據字符轉換為連續的串行數據流發送出去,同時可將接受的串行數據流轉換為并行的數據字符供給CPU的器件。一般完成這種功能的電路,我們稱為串行接口電路。
? ? ? ?串口通信(Serial Communications)的概念非常簡單,串口按位(bit)發送和接收字節。盡管比按字節(byte)的并行通信慢,但是串口可以在使用一根線發送數據的同時用另一根線接收數據。串口通信最重要的參數是波特率、數據位、停止位和奇偶校驗。對于兩個進行通信的端口,這些參數必須匹配。
??1. 波特率:這是一個衡量符號傳輸速率的參數。指的是信號被調制以后在單位時間內的變化,即單位時間內載波參數變化的次數,如每秒鐘傳送960個字符,而每個字符格式包含10位(1個起始位,1個停止位,8個數據位),這時的波特率為960Bd,比特率為10位*960個/秒=9600bps。
??2. 數據位:這是衡量通信中實際數據位的參數。當計算機發送一個信息包,實際的數據往往不會是8位的,標準的值是6、7和8位。標準的ASCII碼是0~127(7位),擴展的ASCII碼是0~255(8位)。
??3. 停止位:用于表示單個包的最后幾位。典型的值為1,1.5和2位。由于數據是在傳輸線上定時的,并且每一個設備有其自己的時鐘,很可能在通信中兩臺設備間出現了小小的不同步。因此停止位不僅僅是表示傳輸的結束,并且提供計算機校正時鐘同步的機會。
??4. 校驗位:在串口通信中一種簡單的檢錯方式。有四種檢錯方式:偶、奇、高和低。當然沒有校驗位也是可以的。
二、C#串口編程類
? ? ? ?從.NET Framework 2.0開始,C#提供了SerialPort類用于實現串口控制。命名空間:System.IO.Ports。其中詳細成員介紹參看MSDN文檔。下面介紹其常用的字段、方法和事件。
? 1. 常用字段:
名稱 | 說明 |
PortName | 獲取或設置通信端口 |
BaudRate | 獲取或設置串行波特率 |
DataBits | 獲取或設置每個字節的標準數據位長度 |
Parity | 獲取或設置奇偶校驗檢查協議 |
StopBits | 獲取或設置每個字節的標準停止位數 |
2. 常用方法:
名稱 | 說明 |
Close | 關閉端口連接,將?IsOpen?屬性設置為?false,并釋放內部?Stream?對象 |
GetPortNames | 獲取當前計算機的串行端口名稱數組 |
Open | 打開一個新的串行端口連接 |
Read | 從?SerialPort?輸入緩沖區中讀取 |
Write | ?將數據寫入串行端口輸出緩沖區 |
3. 常用事件:
名稱 | 說明 |
DataReceived | 表示將處理?SerialPort?對象的數據接收事件的方法 |
三、C#開發串口實例
前臺頁面:
?后臺代碼:
using System;
using System.IO.Ports;
using System.Text;
using System.Windows.Forms;
namespace SerialPort
{
? ? public partial class SerialPort : Form
? ? {
? ? ? ? String serialPortName;
? ? ? ? public SerialPort()
? ? ? ? {
? ? ? ? ? ? InitializeComponent();
? ? ? ? }
? ? ? ? private void Form1_Load(object sender, EventArgs e)
? ? ? ? {
? ? ? ? ? ? string[] ports = System.IO.Ports.SerialPort.GetPortNames();//獲取電腦上可用串口號
? ? ? ? ? ? comboBox1.Items.AddRange(ports);//給comboBox1添加數據
? ? ? ? ? ? comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;//如果里面有數據,顯示第0個
? ? ? ? ? ? comboBox2.Text = "115200";/*默認波特率:115200*/
? ? ? ? ? ? comboBox3.Text = "1";/*默認停止位:1*/
? ? ? ? ? ? comboBox4.Text = "8";/*默認數據位:8*/
? ? ? ? ? ? comboBox5.Text = "無";/*默認奇偶校驗位:無*/
? ? ? ? }
? ? ? ? private void button1_Click(object sender, EventArgs e)
? ? ? ? {
? ? ? ? ? ? if (button1.Text == "打開串口"){//如果按鈕顯示的是打開
? ? ? ? ? ? ? ? try{//防止意外錯誤
? ? ? ? ? ? ? ? ? ? serialPort1.PortName = comboBox1.Text;//獲取comboBox1要打開的串口號
? ? ? ? ? ? ? ? ? ? serialPortName = comboBox1.Text;
? ? ? ? ? ? ? ? ? ? serialPort1.BaudRate = int.Parse(comboBox2.Text);//獲取comboBox2選擇的波特率
? ? ? ? ? ? ? ? ? ? serialPort1.DataBits = int.Parse(comboBox4.Text);//設置數據位
? ? ? ? ? ? ? ? ? ? /*設置停止位*/
? ? ? ? ? ? ? ? ? ? if (comboBox3.Text == "1") { serialPort1.StopBits = StopBits.One; }
? ? ? ? ? ? ? ? ? ? else if (comboBox3.Text == "1.5") { serialPort1.StopBits = StopBits.OnePointFive; }
? ? ? ? ? ? ? ? ? ? else if (comboBox3.Text == "2") { serialPort1.StopBits = StopBits.Two; }
? ? ? ? ? ? ? ? ? ? /*設置奇偶校驗*/
? ? ? ? ? ? ? ? ? ? if (comboBox5.Text == "無") { serialPort1.Parity = Parity.None; }
? ? ? ? ? ? ? ? ? ? else if (comboBox5.Text == "奇校驗") { serialPort1.Parity = Parity.Odd; }
? ? ? ? ? ? ? ? ? ? else if (comboBox5.Text == "偶校驗") { serialPort1.Parity = Parity.Even; }
? ? ? ? ? ? ? ? ? ? serialPort1.Open();//打開串口
? ? ? ? ? ? ? ? ? ? button1.Text = "關閉串口";//按鈕顯示關閉串口
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? catch (Exception err)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? MessageBox.Show("打開失敗"+ err.ToString(), "提示!");//對話框顯示打開失敗
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? else{//要關閉串口
? ? ? ? ? ? ? ? try{//防止意外錯誤
? ? ? ? ? ? ? ? ? ? serialPort1.Close();//關閉串口
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? catch (Exception){}
? ? ? ? ? ? ? ? button1.Text = "打開串口";//按鈕顯示打開
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? protected override void WndProc(ref Message m)
? ? ? ? {
? ? ? ? ? ? if (m.Msg == 0x0219){//設備改變
? ? ? ? ? ? ? ? if (m.WParam.ToInt32() == 0x8004){//usb串口拔出
? ? ? ? ? ? ? ? ? ? string[] ports = System.IO.Ports.SerialPort.GetPortNames();//重新獲取串口
? ? ? ? ? ? ? ? ? ? comboBox1.Items.Clear();//清除comboBox里面的數據
? ? ? ? ? ? ? ? ? ? comboBox1.Items.AddRange(ports);//給comboBox1添加數據
? ? ? ? ? ? ? ? ? ? if (button1.Text == "關閉串口"){//用戶打開過串口
? ? ? ? ? ? ? ? ? ? ? ? if (!serialPort1.IsOpen){//用戶打開的串口被關閉:說明熱插拔是用戶打開的串口
? ? ? ? ? ? ? ? ? ? ? ? ? ? button1.Text = "打開串口";
? ? ? ? ? ? ? ? ? ? ? ? ? ? serialPort1.Dispose();//釋放掉原先的串口資源
? ? ? ? ? ? ? ? ? ? ? ? ? ? comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;//顯示獲取的第一個串口號
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? else{
? ? ? ? ? ? ? ? ? ? ? ? ? ? comboBox1.Text = serialPortName;//顯示用戶打開的那個串口號
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? else{//用戶沒有打開過串口
? ? ? ? ? ? ? ? ? ? ? ? comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;//顯示獲取的第一個串口號
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else if (m.WParam.ToInt32() == 0x8000){//usb串口連接上
? ? ? ? ? ? ? ? ? ? string[] ports = System.IO.Ports.SerialPort.GetPortNames();//重新獲取串口
? ? ? ? ? ? ? ? ? ? comboBox1.Items.Clear();
? ? ? ? ? ? ? ? ? ? comboBox1.Items.AddRange(ports);
? ? ? ? ? ? ? ? ? ? if (button1.Text == "關閉串口"){//用戶打開過一個串口
? ? ? ? ? ? ? ? ? ? ? ? comboBox1.Text = serialPortName;//顯示用戶打開的那個串口號
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? else{
? ? ? ? ? ? ? ? ? ? ? ? comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;//顯示獲取的第一個串口號
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? base.WndProc(ref m);
? ? ? ? }
? ? ? ? private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
? ? ? ? {
? ? ? ? ? ? int len = serialPort1.BytesToRead;//獲取可以讀取的字節數
? ? ? ? ? ? byte[] buff = new byte[len];//創建緩存數據數組
? ? ? ? ? ? serialPort1.Read(buff, 0, len);//把數據讀取到buff數組
? ? ? ? ? ? Invoke((new Action(() =>{//C# 3.0以后代替委托的新方法
? ? ? ? ? ? ? ? ? ? textBox1.AppendText(Encoding.Default.GetString(buff));//對話框追加顯示數據
? ? ? ? ? ? })));
? ? ? ? }
? ? ? ? private void button2_Click(object sender, EventArgs e)
? ? ? ? {
? ? ? ? ? ? textBox1.Clear();//清除接收對話框顯示的數據
? ? ? ? }
? ? ? ? private void button3_Click(object sender, EventArgs e)
? ? ? ? {
? ? ? ? ? ? String Str = textBox2.Text.ToString();//獲取發送文本框里面的數據
? ? ? ? ? ? try
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (Str.Length > 0)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? serialPort1.Write(Str);//串口發送數據
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? catch (Exception){ }
? ? ? ? }
? ? ? ? private void button4_Click(object sender, EventArgs e)
? ? ? ? {
? ? ? ? ? ? textBox2.Clear();//清除發送文本框里面的內容
? ? ? ? }
? ? }
}