Winform程序实现COM口通信

故事背景:公司生产线上新购一台机台(原本有两台同型号的老机器),结果原本的用VB写的测试电压的程序在新机器上无法使用,读取不到电脑COM口上机台返回的数据;最郁闷的是电话问厂商人家说新的机器没有改变什么(最坑的就是这句话了),只是比老机器效率高点,然后就没了,没办法,已经付过钱了,人家吊的不行。万般无奈之下,只有自己找原因了;于是乎,上网找各种资料,自己写了一个Winform的测试COM通信的程序,写完后结果和VB程序 一样的问题,读取不到COM口数据,经过两天的研究终于搞定了,原因是新设备中的通信协议中的握手协议改了。废话不多说,上图片和代码:

1.Winform界面如下:

其中:波特率的的Items包括

300
600
1200
2400
4800
9600
19200
38400
43000
56000
57600
115200

数据位的Items有:

1
2
4
8

停止位的Items有:

1
1.5
2

校验位的Items有:


奇校验
偶校验

备注:界面上的toolStrip可以改为StatusStrip更好些,发送数据的两个RadioButton的名字可以改下(因为这个是在度娘里找的,懒的改代码里的名字,所以我也就没改)

2.上代码(已运行过的代码,可直接使用;由于我只要测试COM的通信,所以定制发送数据和保存设置的功能没写,可根据需求自行添加)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;

namespace TestCOM
{
    public partial class Form1 : Form
    {
        SerialPort sp1 = new SerialPort();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
            sp1.DataReceived+=new SerialDataReceivedEventHandler(sp1_DataReceived);

            string[] str = SerialPort.GetPortNames();
            if (str == null)
            {
                MessageBox.Show("本机没有串口!", "Error");
                return;
            }

            //添加串口项目
            foreach (string s in System.IO.Ports.SerialPort.GetPortNames())
            {//获取有多少个COM口
                cbSerial.Items.Add(s);
            }

            //串口设置默认选择项
            cbSerial.SelectedIndex = 0;         //设置cbSerial的默认选项
            cbBaudRate.SelectedIndex = 5;
            cbDataBits.SelectedIndex = 3;
            cbStop.SelectedIndex = 0;
            cbParity.SelectedIndex = 0;
            radio2.Checked = true;  //发送数据的“16进制”单选按钮
            rbRcvStr.Checked = true;
        }

        private void btnSwitch_Click(object sender, EventArgs e)
        {

            if (!sp1.IsOpen)
            {
                try
                {
                    string serialName = cbSerial.SelectedItem.ToString();
                    sp1.PortName = serialName;
                    string strBaudRate = cbBaudRate.Text;
                    string strDateBits = cbDataBits.Text;

                    string strStopBits = cbStop.Text;
                    Int32 iBaudRate = Convert.ToInt32(strBaudRate);
                    Int32 iDateBits = Convert.ToInt32(strDateBits);

                    sp1.BaudRate = iBaudRate;
                    sp1.DataBits = iDateBits;
                    switch (cbStop.Text)
                    {
                        case "1":
                            sp1.StopBits = StopBits.One;
                            break;
                        case "1.5":
                            sp1.StopBits = StopBits.OnePointFive;
                            break;
                        case "2":
                            sp1.StopBits = StopBits.Two;
                            break;
                        default:
                            MessageBox.Show("Error:参数不正确!", "Error");
                            break;
                    }

                    switch (cbParity.Text)
                    {
                        case "无":
                            sp1.Parity = Parity.None;
                            break;
                        case "奇校验":
                            sp1.Parity = Parity.Odd;
                            break;
                        case "偶校验":
                            sp1.Parity = Parity.Even;
                            break;
                        default:
                            MessageBox.Show("Error:参数不正确!", "Error");
                            break;
                    }
                    //sp1.ReceivedBytesThreshold = 1;
                    //sp1.Handshake = Handshake.RequestToSend;//握手协议:RTS硬件流控制
                    //我遇到的问题就是这里的问题,Handshake默认是None,但是有些设备的Handshake可能就不是这个,所以要根据连接的设备而定;如果是用跳线测试电脑COM通信的话这里就用默认的,改成RTS的话是不行的

                    if (sp1.IsOpen == true)
                    {
                        sp1.Close();
                    }
                    //状态栏设置
                    tsSpNUM.Text = "串口号:" + sp1.PortName + "|";
                    tsBaudRate.Text = "波特率:" + sp1.BaudRate + "|";
                    tsDataBits.Text = "数据位:" + sp1.DataBits + "|";
                    tsStopBits.Text = "停止位:" + sp1.StopBits + "|";
                    tsParity.Text = "校验位:" + sp1.Parity + "|";

                    cbSerial.Enabled = false;
                    cbBaudRate.Enabled = false;
                    cbDataBits.Enabled = false;
                    cbStop.Enabled = false;
                    cbParity.Enabled = false;

                    sp1.Open();
                    btnSwitch.Text = "关闭串口";

                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error:" + ex.Message + "Error");
                    return;
                }
            }
            else
            {
                tsSpNUM.Text = "串口号:未指定|";
                tsBaudRate.Text = "波特率:未指定|";
                tsDataBits.Text = "数据位:未指定|";
                tsStopBits.Text = "停止位:未指定|";
                tsParity.Text = "校验位:未指定|";

                cbSerial.Enabled = true;
                cbBaudRate.Enabled = true;
                cbDataBits.Enabled = true;
                cbStop.Enabled = true;
                cbParity.Enabled = true;

                sp1.Close();
                btnSwitch.Text = "打开串口";
            }
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (!sp1.IsOpen)
            {
                MessageBox.Show("请先打开串口", "Error");
                return;
            }
            string strSend = txtSend.Text;
            if (radio1.Checked == true)
            {
                string sendBuf = strSend;
                string sendnoNull = sendBuf.Trim();
                string sendNOComma = sendnoNull.Replace(‘,‘, ‘ ‘);
                string sendNOComma1 = sendNOComma.Replace(‘,‘, ‘ ‘);
                string strSendNoComma2 = sendNOComma1.Replace("0x", "");
                strSendNoComma2.Replace("0X", "");
                string[] strArray = strSendNoComma2.Split(‘ ‘);

                int byteBufferLength = strArray.Length;
                for (int i = 0; i < strArray.Length; i++)
                {
                    if (strArray[i] == "")
                    {
                        byteBufferLength--;
                    }
                }

                byte[] byteBuffer = new byte[byteBufferLength];
                int ii = 0;
                for (int i = 0; i < strArray.Length; i++)
                {
                    Byte[] bytesOfStr = Encoding.Default.GetBytes(strArray[i]);

                    int decNum = 0;
                    if (strArray[i] == "")
                    {
                        continue;
                    }
                    else
                    {
                        decNum = Convert.ToInt32(strArray[i],16);
                    }
                    try
                    {
                        byteBuffer[ii] = Convert.ToByte(decNum);
                    }
                    catch (Exception)
                    {

                        MessageBox.Show("字节越界,请逐个字节输入!","Error");
                        return;
                    }
                    ii++;
                }
                sp1.Write(byteBuffer,0,byteBuffer.Length);

            }
            else
            {
                sp1.WriteLine(txtSend.Text);
            }

        }

        private void sp1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (sp1.IsOpen)
            {
                byte[] byteRead = new byte[sp1.BytesToRead];
                if (rbRcvStr.Checked)
                {
                    txtRcv.Text += sp1.ReadLine() + "\r\n";
                    sp1.DiscardInBuffer();
                }
                else
                {
                    try
                    {
                        Byte[] receivedData = new Byte[sp1.BytesToRead];
                        sp1.Read(receivedData, 0, receivedData.Length);
                        sp1.DiscardInBuffer();
                        string strRcv = null;
                        for (int i = 0; i < receivedData.Length; i++)
                        {
                            strRcv += receivedData[i].ToString("X2");
                        }
                        txtRcv.Text += strRcv + "\r\n";
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message,"出错提示");
                        txtSend.Text = "";
                    }
                }
            }
            else
            {
                MessageBox.Show("请打开某个串口","错误提示");
            }
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            txtRcv.Text = string.Empty;
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

    }
}

备注:我处理的这个机台的Handshake的方式就是RTS,但是应该有很多设备的Handshake是None的(默认的),所以要根据具体的设备(设备的说明书上应该有说的)。

时间: 2024-09-26 22:29:47

Winform程序实现COM口通信的相关文章

基于C# Winform的简易聊天程序[第一篇-两端通信]

程序简介 本聊天程序支持局域网内部客户端与服务端之间的互相通信. 原理 启动服务端后,服务端通过持续监听客户端发来的请求,一旦监听到客户端传来的信息后,两端便可以互发信息了.服务端需要绑定一个IP,用于客户端在网络中寻找并建立连接.信息发送原理:将手动输入字符串信息转换成机器可以识别的字节数组,然后调用套接字的Send()方法将字节数组发送出去.信息接收原理:调用套接字的Receive()方法,获取对端传来的字节数组,然后将其转换成人可以读懂的字符串信息. 界面设计 - 服务端 IP文本框 na

C#Winform程序如何发布并自动升级(图解)

有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布 关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解) 其实打包是打包,发布是发布两者是没有任何关系的,只是有些同志会分不清楚.混在一起了. 下在面大家就和我一起来做一个发布并升级的程序吧. 首先我们准备几个工作 1.新建一个存储发布后程序的目录比如D:\iis\textWinform  以下简称-- 发布目录 2.在IIS新建一个网站并指向目录D:\iis\auto

基于DevExpress的Winform程序安装包的制作

在我们做系统开发的时候,都会面临一个安装包制作的问题,如何把我们做好的系统,通过安装包工具整合成一个安装包给客户进行安装.安装包的优势就是一步步安装就可以了,不用复制一大堆文件给客户,还怕缺少那个文件导致系统运行出错.本文主要介绍基于DevExpress的Winform程序安装包的制作内容,包括VS2010和VS2013/V2105的不同处理方式. 我们知道,VS2010是最后一个可以使用微软安装包制作工具的VS版本了,所以后面VS2012/2013/2015版本都需要使用第三方安装包制作工具,

winform程序静音

using System.Runtime.InteropServices;    //命名空间 const uint WM_APPCOMMAND = 0x319; const uint APPCOMMAND_VOLUME_UP = 0x0a; const uint APPCOMMAND_VOLUME_DOWN = 0x09; const uint APPCOMMAND_VOLUME_MUTE = 0x08; [DllImport("user32.dll", CharSet = Char

Halcon的HWindowControl控件在WinForm程序中的使用介绍(重点解决图片缩放的问题)

 Halcon的HWindowControl控件在WinForm程序中的使用介绍(重点解决图片缩放的问题) 2016-12-04 20:11 362人阅读 评论(4) 收藏 举报  分类: Halcon 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] HWindowControl控件初步使用 最近在学习新的视觉处理工具–Halcon软件包,本人学习的主要是HDevelop.Halcon与C#混编以及Halcon与C++混编.这里再多缀一句:11版本后C++编程,包含的是h

吉特仓库管理系统(开源)-如何在网页端启动WinForm 程序

原文:吉特仓库管理系统(开源)-如何在网页端启动WinForm 程序 在逛淘宝或者使用QQ相关的产品的时候,比如淘宝我要联系店家点击旺旺图标的时候能够自动启动阿里旺旺进行聊天.之前很奇怪为什么网页端能够自动启动客户端程序,最近在开发吉特仓储管理系统的时候也遇到一个类似的问题,因为使用网页端的打印效果并不是太好,之前也写过关于打印相关的文章可以查阅,我需要使用WinForm客户端来驱动打印,但是我又不想重新开发Winform客户端的所有功能,只要能够使用winform驱动打印即可.我就需要一个类似

C#中WinForm程序退出方法技巧总结(转)

本文实例总结了C#中WinForm程序退出方法技巧.分享给大家供大家参考.具体分析如下: 在c#中退出WinForm程序包括有很多方法,如:this.Close(); Application.Exit();Application.ExitThread(); System.Environment.Exit(0); 等他们各自的方法不一样,下面我们就来详细介绍一下. 1.this.Close();   只是关闭当前窗口,若不是主窗体的话,是无法退出程序的,另外若有托管线程(非主线程),也无法干净地退

在Winform程序中设置管理员权限及为用户组添加写入权限

在我们一些Winform程序中,往往需要具有一些特殊的权限才能操作系统文件,我们可以设置运行程序具有管理员权限或者设置运行程序的目录具有写入的权限,如果是在操作系统里面,我们可以设置运行程序以管理员身份运行,或者设置Users用户组在运行目录中具有写入权限都可以解决问题,不过如果我们想通过C#代码进行自动的处理,那么应该如何实现呢? 1.系统设置管理员权限或者目录写入权限 如果我们需要让程序以管理员身份运行,那么可以通过设置快捷方式的属性或者应用程序的属性为[以管理员身份运行此程序]即可实现,如

WinForm 程序加管理员权限

在Vista 和 Windows 7 及更新版本的操作系统,增加了 UAC(用户账户控制) 的安全机制,如果 UAC 被打开,用户即使以管理员权限登录,其应用程序默认情况下也无法对系统目录.系统注册表等可能影响系统正常运行的设置进行写操作.这个机制大大增强了系统的安全性,但对应用程序开发者来说,我们不能强迫用户去关闭UAC,但有时我们开发的应用程序又需要以 Administrator 的方式运行,如何实现这样的功能呢?下面演示 C# 程序如何实现提示用户以管理员权限运行. 本例以WinForm程