Visual C# 2010 Serial Port 設定
最近一下子太多案子都是要 Rs232,所以先寫一個標準的 RS232 設定,好讓所有的系統共用。
首先,構想是把 RS232 的各項設定值直接放在 Properties.Settings.settings 中 ,所以先在 Visual C# 2010 專案中的 Properties.Settings.settings 中加入:
serial_Port
serial_Baudrate
serial_Parity
serial_Databits
serial_Stopbit
為了方便,每個變數的型態都是 String,如果是數值變數讀進來時會先用 Int32.TryParse(String, out numValue) 測試 String 是否能轉成 Integer,如果 Parse 可以再執行 ToInt32。
整個程式如後:
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 WindowsFormsApplication1
{
public partial class Form1 : Form
{
private string RxString;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] SerialPorts = SerialPort.GetPortNames();
foreach (string port in SerialPorts)
{
}
}
private void button1_Click(object sender, EventArgs e)
{
if (!serialPort1.IsOpen)
{
serialPort1.PortName = Properties.Settings.Default.serial_Port;
int numValue;
if (Int32.TryParse(Properties.Settings.Default.serial_Baudrate, out numValue))
serialPort1.BaudRate = Convert.ToInt32(Properties.Settings.Default.serial_Baudrate);
switch (Properties.Settings.Default.serial_Parity)
{
case "無":
serialPort1.Parity = Parity.None;
break;
case "奇數":
serialPort1.Parity = Parity.Odd;
break;
case "偶數":
serialPort1.Parity = Parity.Even;
break;
}
switch (Properties.Settings.Default.serial_Stopbits)
{
case "0":
serialPort1.StopBits = StopBits.None;
break;
case "1":
serialPort1.StopBits = StopBits.One;
break;
case "2":
serialPort1.StopBits = StopBits.Two;
break;
}
serialPort1.StopBits = StopBits.One;
try
{
serialPort1.Open();
}
catch (Exception ex)
{
MessageBox.Show("Port 無法開啟 " + ex.Message);
}
finally
{
button1.Text = "關閉";
}
}
else
{
try
{
serialPort1.Close();
}
catch (Exception ex)
{
MessageBox.Show("Port 無法關閉 " + ex.Message);
}
finally
{
button1.Text = "開啟";
}
}
}
private void DisplayText(object sender, EventArgs e)
{
richTextBox1.AppendText(RxString);
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string tmpStr;
char[] tmpChar;
tmpStr = serialPort1.ReadExisting();
tmpChar = tmpStr.ToCharArray();
RxString = "";
foreach (char letter in tmpChar)
{
int value = Convert.ToInt32(letter);
string hexOut = String.Format("{0:x2}", value) + " ";
RxString += hexOut;
}
this.Invoke(new EventHandler(DisplayText));
}
private void button2_Click(object sender, EventArgs e)
{
bool test;
test = SendFc3((byte)0x01, 0x00, 0x16);
}
private void GetCRC(byte[] message, ref byte[] CRC)
{
//Function expects a modbus message of any length as well as a 2 byte CRC array in which to
//return the CRC values:
ushort CRCFull = 0xFFFF;
byte CRCHigh = 0xFF, CRCLow = 0xFF;
char CRCLSB;
for (int i = 0; i < (message.Length) - 2; i++)
{
CRCFull = (ushort)(CRCFull ^ message[i]);
for (int j = 0; j < 8; j++)
{
CRCLSB = (char)(CRCFull & 0x0001);
CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF);
if (CRCLSB == 1)
CRCFull = (ushort)(CRCFull ^ 0xA001);
}
}
CRC[1] = CRCHigh = (byte)((CRCFull >> 8) & 0xFF);
CRC[0] = CRCLow = (byte)(CRCFull & 0xFF);
}
private void BuildMessage(byte address, byte type, ushort start, ushort registers, ref byte[] message)
{
//Array to receive CRC bytes:
byte[] CRC = new byte[2];
message[0] = address;
message[1] = type;
message[2] = (byte)(start >> 8);
message[3] = (byte)start;
message[4] = (byte)(registers >> 8);
message[5] = (byte)registers;
GetCRC(message, ref CRC);
message[message.Length - 2] = CRC[0];
message[message.Length - 1] = CRC[1];
}
public bool SendFc3(byte address, ushort start, ushort registers)
{
//Ensure port is open:
if (serialPort1.IsOpen)
{
//Clear in/out buffers:
serialPort1.DiscardOutBuffer();
serialPort1.DiscardInBuffer();
//Function 3 request is always 8 bytes:
byte[] message = new byte[8];
//Build outgoing modbus message:
BuildMessage(address, (byte)3, start, registers, ref message);
//Send modbus message to Serial Port:
try
{
serialPort1.Write(message, 0, message.Length);
return true;
}
catch (Exception err)
{
MessageBox.Show("Error in read event: " + err.Message);
return false;
}
}
else
{
MessageBox.Show("Serial port not open");
return false;
}
}
private void serButton_Click(object sender, EventArgs e)
{
Form2 SerialSetup = new Form2();
SerialSetup.Show();
}
}
}
執行畫面:
首先,構想是把 RS232 的各項設定值直接放在 Properties.Settings.settings 中 ,所以先在 Visual C# 2010 專案中的 Properties.Settings.settings 中加入:
serial_Port
serial_Baudrate
serial_Parity
serial_Databits
serial_Stopbit
為了方便,每個變數的型態都是 String,如果是數值變數讀進來時會先用 Int32.TryParse(String, out numValue) 測試 String 是否能轉成 Integer,如果 Parse 可以再執行 ToInt32。
整個程式如後:
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 WindowsFormsApplication1
{
public partial class Form1 : Form
{
private string RxString;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] SerialPorts = SerialPort.GetPortNames();
foreach (string port in SerialPorts)
{
}
}
private void button1_Click(object sender, EventArgs e)
{
if (!serialPort1.IsOpen)
{
serialPort1.PortName = Properties.Settings.Default.serial_Port;
int numValue;
if (Int32.TryParse(Properties.Settings.Default.serial_Baudrate, out numValue))
serialPort1.BaudRate = Convert.ToInt32(Properties.Settings.Default.serial_Baudrate);
switch (Properties.Settings.Default.serial_Parity)
{
case "無":
serialPort1.Parity = Parity.None;
break;
case "奇數":
serialPort1.Parity = Parity.Odd;
break;
case "偶數":
serialPort1.Parity = Parity.Even;
break;
}
switch (Properties.Settings.Default.serial_Stopbits)
{
case "0":
serialPort1.StopBits = StopBits.None;
break;
case "1":
serialPort1.StopBits = StopBits.One;
break;
case "2":
serialPort1.StopBits = StopBits.Two;
break;
}
serialPort1.StopBits = StopBits.One;
try
{
serialPort1.Open();
}
catch (Exception ex)
{
MessageBox.Show("Port 無法開啟 " + ex.Message);
}
finally
{
button1.Text = "關閉";
}
}
else
{
try
{
serialPort1.Close();
}
catch (Exception ex)
{
MessageBox.Show("Port 無法關閉 " + ex.Message);
}
finally
{
button1.Text = "開啟";
}
}
}
private void DisplayText(object sender, EventArgs e)
{
richTextBox1.AppendText(RxString);
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string tmpStr;
char[] tmpChar;
tmpStr = serialPort1.ReadExisting();
tmpChar = tmpStr.ToCharArray();
RxString = "";
foreach (char letter in tmpChar)
{
int value = Convert.ToInt32(letter);
string hexOut = String.Format("{0:x2}", value) + " ";
RxString += hexOut;
}
this.Invoke(new EventHandler(DisplayText));
}
private void button2_Click(object sender, EventArgs e)
{
bool test;
test = SendFc3((byte)0x01, 0x00, 0x16);
}
private void GetCRC(byte[] message, ref byte[] CRC)
{
//Function expects a modbus message of any length as well as a 2 byte CRC array in which to
//return the CRC values:
ushort CRCFull = 0xFFFF;
byte CRCHigh = 0xFF, CRCLow = 0xFF;
char CRCLSB;
for (int i = 0; i < (message.Length) - 2; i++)
{
CRCFull = (ushort)(CRCFull ^ message[i]);
for (int j = 0; j < 8; j++)
{
CRCLSB = (char)(CRCFull & 0x0001);
CRCFull = (ushort)((CRCFull >> 1) & 0x7FFF);
if (CRCLSB == 1)
CRCFull = (ushort)(CRCFull ^ 0xA001);
}
}
CRC[1] = CRCHigh = (byte)((CRCFull >> 8) & 0xFF);
CRC[0] = CRCLow = (byte)(CRCFull & 0xFF);
}
private void BuildMessage(byte address, byte type, ushort start, ushort registers, ref byte[] message)
{
//Array to receive CRC bytes:
byte[] CRC = new byte[2];
message[0] = address;
message[1] = type;
message[2] = (byte)(start >> 8);
message[3] = (byte)start;
message[4] = (byte)(registers >> 8);
message[5] = (byte)registers;
GetCRC(message, ref CRC);
message[message.Length - 2] = CRC[0];
message[message.Length - 1] = CRC[1];
}
public bool SendFc3(byte address, ushort start, ushort registers)
{
//Ensure port is open:
if (serialPort1.IsOpen)
{
//Clear in/out buffers:
serialPort1.DiscardOutBuffer();
serialPort1.DiscardInBuffer();
//Function 3 request is always 8 bytes:
byte[] message = new byte[8];
//Build outgoing modbus message:
BuildMessage(address, (byte)3, start, registers, ref message);
//Send modbus message to Serial Port:
try
{
serialPort1.Write(message, 0, message.Length);
return true;
}
catch (Exception err)
{
MessageBox.Show("Error in read event: " + err.Message);
return false;
}
}
else
{
MessageBox.Show("Serial port not open");
return false;
}
}
private void serButton_Click(object sender, EventArgs e)
{
Form2 SerialSetup = new Form2();
SerialSetup.Show();
}
}
}
執行畫面:
留言
張貼留言
請多指教