http://blog.sina.com.cn/s/blog_6c67dab30101p3vn.html
-------------------------------------------------------------------------------
public partial class Form1 : Form
{
int k = 0;
int[] crc_data1 = { 0, 0 };
int[] crc_data2 = { 0, 0, 0, 0, 0 };
int[] crc_data3 = { 0, 0, 0, 0, 0 };
int x = 0;
short qtemp;
byte[] new_byte1 = { 0, 0, 0, 0, 0, 0, 0 };
SolidBrush bush1 = new SolidBrush(Color.Red);
SolidBrush bush2 = new SolidBrush(Color.Green);
public Form1()
{
InitializeComponent();
}
//串口初始化
private void Form1_Load(object sender, EventArgs e)
{
serialPort1.PortName = "COM3";
serialPort1.BaudRate = 9600;
serialPort1.DataBits = 8;
serialPort1.StopBits = System.IO.Ports.StopBits.One;
serialPort1.Parity = System.IO.Ports.Parity.None;
serialPort1.Open();
}
//向水浸傳感器發送讀指令
private void timer1_Tick(object sender, EventArgs e)
{
byte[] boutdata1 = { 0x01, 0x04, 0x01, 0xE3 };
serialPort1.Write(boutdata1, 0, 4);
}
//觸發事件,讀取溫度傳感器返回數據
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
System.Threading.Thread.Sleep(100);
int byte_num1 = serialPort1.Read(new_byte1, 0, 7);
this.Invoke(new EventHandler(DisplayText));
}
private void DisplayText(object sender, EventArgs e)
{
if (new_byte1[0] == 1) //水浸傳感器
{
for (int i = 0; i < 2; i++)
crc_data1[i] = (int)new_byte1[i];
int[] crc1 = crc16(crc_data1);
if (crc1[0] == new_byte1[2] && crc1[1] == new_byte1[3]) //校驗CRC
alarm1(); //顯示,紅燈報警,綠燈正常
else
MessageBox.Show("校驗碼錯誤,數據無效!", "");
byte[] boutdata2 = { 0x02, 0x03, 0x00, 0x01, 0x00, 0x01, 0xD5, 0xF9 }; //發送溫度傳感器數據
serialPort1.Write(boutdata2, 0, 8);
}
if (new_byte1[0] == 2 && new_byte1[1] == 3) //溫度傳感器
{
for (int i = 0; i < 5; i++)
crc_data2[i] = (int)new_byte1[i];
int[] crc2 = crc16(crc_data2);
if (crc2[0] == new_byte1[5] && crc2[1] == new_byte1[6])
DisplayText2(); //顯示溫度並畫出溫度曲線
else
MessageBox.Show("校驗碼錯誤,數據無效!", "");
byte[] boutdata3 = { 0x50, 0x03, 0x00, 0x03, 0x00, 0x01, 0x79, 0x8B }; //發送煙感傳感器數據
serialPort1.Write(boutdata3, 0, 8);
}
if (new_byte1[0] == 80 && new_byte1[1] == 3) //煙感傳感器
{
for (int i = 0; i < 5; i++)
crc_data3[i] = (int)new_byte1[i];
int[] crc3 = crc16(crc_data3);
if (crc3[0] == new_byte1[5] && crc3[1] == new_byte1[6])
alarm3(); //顯示,紅燈報警,綠燈正常
else
MessageBox.Show("校驗碼錯誤,數據無效!", "");
}
}
//關閉串口,退出程序
private void button1_Click(object sender, EventArgs e)
{
serialPort1.Close();
Close();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (serialPort1.IsOpen) serialPort1.Close();
}
}
-----------------------------------------------------------------------------------
其實這是很簡單的工作,只是我初次接觸而已,做做筆記,方便以后使用時調用~
.PortName 串口名稱,COM1, COM2等。
.BaudRate 波特率,也就是串口通訊的速度,進行串口通訊的雙方其波特率需要相同,如果用PC連接其他非PC系統,一般地,波特率由非PC系統決定。
.Parity 奇偶校驗。可以選取枚舉Parity中的值
.DataBits 數據位
.StopBits 停止位,可以選取枚舉StopBits中的值
.Handshake 握手方式,也就是數據流控制方式,可以選取枚舉Handshake中的值。
| Close |
關閉端口連接,將 IsOpen 屬性設置為False,並釋放內部 Stream 對象 |
| Open |
打開一個新的串行端口連接 |
| Read |
從 SerialPort 輸入緩沖區中讀取數據字節數 |
| ReadByte |
從 SerialPort 輸入緩沖區中同步讀取一個字節 |
| ReadChar |
從 SerialPort 輸入緩沖區中同步讀取一個字符 |
| ReadLine |
一直讀取到輸入緩沖區中的 NewLine 值 |
| ReadTo |
一直讀取到輸入緩沖區中指定 value 的字符串 |
| Write |
已重載。將數據寫入串行端口輸出緩沖區 |
| WriteLine |
將指定的字符串和 NewLine 值寫入輸出緩沖區 |
| DiscardInBuffer DiscardOutBuffer |
清空接收緩沖區數據 清空輸出緩沖去數據 |
屬性說明
| 名 稱 |
說 明 |
| BaseStream |
獲取 SerialPort 對象的基礎 Stream 對象 |
| BaudRate |
獲取或設置串行波特率 |
| BreakState |
獲取或設置中斷信號狀態 |
| BytesToRead |
獲取接收緩沖區中數據的字節數 |
| BytesToWrite |
獲取發送緩沖區中數據的字節數 |
| CDHolding |
獲取端口的載波檢測行的狀態 |
| CtsHolding |
獲取“可以發送”行的狀態 |
| DataBits |
獲取或設置每個字節的標准數據位長度 |
| DiscardNull |
獲取或設置一個值,該值指示 Null 字節在端口和接收緩沖區之間傳輸時是否被忽略 |
| DsrHolding |
獲取數據設置就緒 (DSR) 信號的狀態 |
| DtrEnable |
獲取或設置一個值,該值在串行通信過程中啟用數據終端就緒 (DTR) 信號 |
| Encoding |
獲取或設置傳輸前后文本轉換的字節編碼 |
| Handshake |
獲取或設置串行端口數據傳輸的握手協議 |
| IsOpen |
獲取一個值,該值指示 SerialPort 對象的打開或關閉狀態 |
| NewLine |
獲取或設置用於解釋 ReadLine( )和WriteLine( )方法調用結束的值 |
| Parity |
獲取或設置奇偶校驗檢查協議 |
| ParityReplace |
獲取或設置一個字節,該字節在發生奇偶校驗錯誤時替換數據流中的無效字節 |
| PortName |
獲取或設置通信端口,包括但不限於所有可用的 COM 端口 |
| ReadBufferSize |
獲取或設置 SerialPort 輸入緩沖區的大小 |
| ReadTimeout |
獲取或設置讀取操作未完成時發生超時之前的毫秒數 |
| ReceivedBytesThreshold |
獲取或設置 DataReceived 事件發生前內部輸入緩沖區中的字節數 |
| RtsEnable |
獲取或設置一個值,該值指示在串行通信中是否啟用請求發送 (RTS) 信號 |
| StopBits |
獲取或設置每個字節的標准停止位數 |
| WriteBufferSize |
獲取或設置串行端口輸出緩沖區的大小 |
| WriteTimeout |
獲取或設置寫入操作未完成時發生超時之前的毫秒數 |
雙方通訊時,一般都需要定義通訊協議,即使最簡單的通過串口發送文本聊天的程序。
通常是在當一方按下回車時,將其所數據的文本連同換行符發給另一方。在這個通訊事例中,協議楨是通過換行符界定的,每一楨數據都被換行符隔開,這樣就很容易識別出通訊雙發發送的信息。
在以上的例子中,可以用WriteLine()來發送數據,用ReadLine()來讀取數據。WriteLine發送完數據后,會將換行符作為數據也發送給對方。ReadLine()讀取數據時,直至遇到一個換行符,然后返回一個字符串代表一行信息。換行符可以通過SerialPort 的屬性NewLine來設置。一般地,Windows將CrLn作為換行符,而在Linux下,換行符則只用一個Ln表示。
ReadLine()方法是阻塞的,直至遇到一個換行符后返回。在讀取數據時,如果一直沒有遇到換行符,那么在等待ReadTimeout時間后,拋出一個TimeoutException。默認情況下,ReadTimeout為InfiniteTimeout。這樣,ReadLine一直處於阻塞狀態,直至有新一行數據到達。
WriteLine()方法也是阻塞的,如果另一方不能及時接收數據,就會引起TimeoutException異常。
由於ReadLine()和WriteLine()方法都是阻塞式的,在程序使用SerialPort 進行串口通訊時,一般應該把讀寫操作交由其他線程處理,避免因為阻塞而導致程序不響應。
讀寫字節或字符數據
對於字節或字符數據,用Read()方法來讀數據,該方法需要一個字節或字符數組作為參數來保存讀取的數據,結果返回實際讀取的字節或字符數。寫數據使用Write()方法,該方法可以將字節數組、字符數據或字符串發送給另一方。
如果通訊雙方交換的數據位字節流數據,要構建一個使用的串口通訊程序,那么雙方應該定義數據楨格式。通常數據楨由楨頭和楨尾來界定。
發送數據比較簡單,只需要將構造好的數據用Write()方法發送出去即可。
接收數據則比較復雜,通訊是以字節流的形式到達的,通過調用一次Read()方法並不能確保所讀取的數據就是完整一楨。因此需要將每次讀取的數據整合在一起,對整合后的數據進行分析,按照定義的楨格式,通過楨頭和楨尾,將楨信息從字節流中抽取出來,這樣才能獲取有意義的信息。
除了利用Read()方法來讀數據,還可以使用ReadExisting()方法來讀取數據。該方法讀取當前所能讀到的數據,以字符串的形式返回。
