由于公司需求所以就查了一些资料写了个串口和设备通讯的
话说现在用串口的应该比较少了吧。
先上一张程序UI图
简单串口通讯必备的东西都在这里了。个人建议使用的时候先短接2-3口进行测试以免线都不通。
下面直接上源码,注释写的还是比较详细的相信还是很容易懂的。
(PS:我这里数据接收的结束符为16)
/// <summary>
/// 创建串口对象
/// </summary>
private SerialPort port = new SerialPort();
/// <summary>
/// 接受消息
/// </summary>
private StringBuilder MsgStr = new StringBuilder();
/// <summary>
/// 构造函数
/// </summary>
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false; //防止跨线程访问出错,好多地方会用到
}
/// <summary>
/// 窗口加载函数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{
///获取窗口列表
string[] ports = SerialPort.GetPortNames();
if (ports.Length > 0)
{
///添加可选通讯口
com.Items.AddRange(ports);
///设置默认选择
com.SelectedIndex = 0;
bot.SelectedIndex = 0;
databit.SelectedIndex = 0;
stopbit.SelectedIndex = 0;
jy.SelectedIndex = 0;
}
else
{
MessageBox.Show("没有可用的串口!");
}
}
/// <summary>
/// 确认按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
try
{
///检测串口是否开着
if (!port.IsOpen)
{
///设置串口名称
port.PortName = com.SelectedItem.ToString();
///设置波特率
port.BaudRate = Convert.ToInt32(bot.Text);
///数据位
port.DataBits = Convert.ToInt32(databit.Text);
///设置无协议
port.Handshake = Handshake.None;
///设置读取不超时
port.ReadTimeout = -1;
//port.WriteTimeout = -1;
///设置停止位
port.StopBits = GetStopBits(stopbit.SelectedIndex + 1);
port.DtrEnable = true;
///无校验
port.Parity = GetParity(jy.SelectedIndex);
///设置数据接收事件
port.DataReceived += ReciveData;
///打开串口
port.Open();
open.Text = "关闭串口";
UpdateStutas();
}
else
{
///关闭串口
port.Close();
port.DataReceived -= ReciveData;
open.Text = "打开串口";
}
}
catch (Exception ex)
{
MessageBox.Show("端口设置错误!");
}
finally
{
UpdateStutas();
}
}
/// <summary>
/// 数据接收事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void ReciveData(object sender, SerialDataReceivedEventArgs e)
{
///是否接受完整
bool isStop = false;
///数据长度
int count = port.BytesToRead;
string msg = null;
//{
byte[] buff = new byte[count];
///接收数据
port.Read(buff, 0, count);
///将比特数据转换为字符串
foreach(byte buf in buff)
{
try
{
msg = Convert.ToString(buf, 16);
if (msg.Length == 1)
{
msg = "0" + msg;
}
if (msg == "16")
isStop = true;
MsgStr.Append(msg + " ");
}
catch (Exception)
{
MessageBox.Show("设备返回不支持的数据!");
}
}
if (!isStop)
return;
///显示数据
data.Text += "----------------------------\n";
data.Text += DateTime.Now.ToString() + ":---->" + MsgStr + '\n';
data.Text += "----------------------------\n";
MsgStr.Clear();
}
/// <summary>
/// 发送信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void send_Click(object sender, EventArgs e)
{
SendMsg(massage.Text);
}
/// <summary>
/// 获取串口状态
/// </summary>
/// <returns></returns>
private void UpdateStutas()
{
if (!port.IsOpen)
return;
string stuta = port.PortName + ": " + port.IsOpen.ToString()
+ " DSR:" + port.DsrHolding + " CDH:" + port.CDHolding +
" CTS:" + port.CtsHolding;
stutas.Text = stuta;
}
/// <summary>
/// 发信
/// </summary>
/// <param name="newmsg"></param>
private void SendMsg(string newmsg)
{
if (!port.IsOpen)
{
MessageBox.Show("端口已被关闭!");
return;
}
UpdateStutas();
///清理残余的缓冲区
port.DiscardInBuffer();
port.DiscardOutBuffer();
///分割要发送的消息
string[] sendbuff = newmsg.Split(' ');
///发送数据
List<byte> buf = new List<byte>();//填充到这个临时列表中
foreach (string msg in sendbuff)
{
try
{
buf.Add(byte.Parse(msg, System.Globalization.NumberStyles.HexNumber));
}
catch (Exception)
{
MessageBox.Show(msg + "不是有效的十六进制数字");
return;
}
}
//转换列表为数组后发送
port.Write(buf.ToArray(), 0, buf.Count);
//记录发送的字节数
sendnum.Text = "发送字节数:" + buf.Count;
}
/// <summary>
/// 获取停止位
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
private StopBits GetStopBits(int num)
{
foreach(StopBits bit in Enum.GetValues(typeof(StopBits)))
{
if((int)bit == num)
{
return bit;
}
}
return StopBits.None;
}
/// <summary>
/// 获取校验
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
private Parity GetParity(int num)
{
foreach (Parity bit in Enum.GetValues(typeof(Parity)))
{
if ((int)bit == num)
{
return bit;
}
}
return Parity.None;
}
源文件地址
(ps: DataReceived函数接收的数据不是完整的只要有数据传过来就会产生这个事件,所以最好有自定义的结束符作为标识)