精华内容
下载资源
问答
  • C#串口通讯

    2018-06-14 17:48:46
    C#做的上位机 用于串口通讯,方便的与下位机进行通讯
  • C# 串口通讯

    万次阅读 热门讨论 2011-10-10 20:46:02
    本人做的一个C#串口上位机程序,最近有空就写了点感悟,见笑大方了。 一,软件概述 本上位机采用VisualC#2010编写,用于与单片机通信,发送并接收固定格式的数据包。 上位机每次点击“发送”按钮后将发送18字节...

     

    本人做的一个C#串口上位机程序,最近有空就写了点感悟,见笑大方了。

     

     

     

    一,软件概述

    本上位机采用Visual C# 2010编写,用于与单片机通信,发送并接收固定格式的数据包。

    上位机每次点击“发送”按钮后将发送18字节给下位机,发送包的格式为:

    包头:0xAA;命令号:0x01;帧长:0x0D;帧数据13字节,由界面上的选项决定(如发射频率6MHz,代表0x000600三字节),和校验1字节,包尾:0xa5;共18(3+13+2)字节。此18字节将在发送区中显示。具体的包格式就不说了,都是自己定义的。

    下位机接收到数据后,将发送5字节的数据,上位机接收到数据后可以判定数据是否正确,校验是否正确等。下位机发送的数据由上位机接收后将在接收区中显示

    二,具体实现核心代码

    1)。运行软件后,将自动显示本机的串口(如果有的话),并打开。FormLoad代码为:

    //列出本机所有串口

                string[] ports = SerialPort.GetPortNames();

                Array.Sort(ports);

                comboBoxPortSelect.Items.AddRange(ports);

    //默认选中第一个

                comboBoxPortSelect.SelectedIndex = 0;

    //打开本计算机的串口            

                if (mycomm.IsOpen) {

                    mycomm.Close();

                }

    mycomm.PortName = comboBoxPortSelect.Text;

                 mycomm.ReadTimeout = 32;

                mycomm.BaudRate = 9600;

                try  {

                    mycomm.Open();

                    btnOpen.Text = "关闭串口";//按钮打开

                    lblToolStripStatus.Text = "串口打开成功!";//状态栏

                }catch{

                    btnOpen.Text = "打开串口";

                    MessageBox.Show("没有发现串口或串口已被占用!");

                    lblToolStripStatus.Text = "串口打开失败!";

                }

                //添加事件注册

                mycomm.DataReceived += comm_DataReceived;          

    2)。点击发送按钮,发送18字节数据,代码为:

    //存放待发送的一包数据(包括帧头,命令号,帧长,帧数据,校验,帧尾)

                byte[] package = new byte[18]; int j = 0; int k = 3;

                package[0] = 0xAA;//帧头

                package[1] = 0x01;//命令号

                package[2] = 0x0D;//帧长            

                byte parity = 0x01+0x0d;//和校验:(命令号+帧长+帧数据)&7f。 

                //存放帧数据(13字节)

                byte[] realData = new byte[13];

                string data = getMode().Append(getTxFre(txtTxFre.Text).Append(getDuoPuLe(txtDuoFre.Text)).Append(    getBand()).Append(getTxPower()).Append(getRxFre(txtRxFre.Text)).Append(getRxBandAndDelay()).Append(getAGC())).ToString();//待发送的二进制数据,略。。。            

                for (int i = 0; i < data.Length; i += 8)

                {

                    //每八位截取,转为十进制的byte,再放入byte数组中 

                    realData[j++] = (byte)Convert.ToInt32(data.Substring(i, 8), 2);               

                }            

                foreach (byte b in realData) {           

                     parity += b;//校验码计算      

                     package[k++] = b; }

                parity &= 0x7F; //校验码计算完成          

                package[16] = parity;//和校验(1字节)

                package[17] = 0xa5;//帧尾

                if (!mycomm.IsOpen)

                {

                    MessageBox.Show("串口没有打开,请打开串口!");

                    return;

                }

                mycomm.Write(package, 0, 18);//向串口发送一包(18字节)的数据 

    3)。 接收数据的事件代码:

    private void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)

            {           

                int n = mycomm.BytesToRead;

                byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据        

                mycomm.Read(buf, 0, n);//读取缓冲数据

                builder.Clear();//清除字符串构造器的内容

                //因为要访问ui资源,所以需要使用invoke方式同步ui。

                this.Invoke((EventHandler)(delegate

                {    //依次的拼接出16进制字符串

                    foreach (byte b in buf)

                    {

                        builder.Append(b.ToString("X2") + " ");                   

                    }

                    //直接按ASCII规则转换成字符串

                    //builder.Append(Encoding.ASCII.GetString(buf));   

                    txtGet.Text = "";

                    txtGet.AppendText(builder.ToString());

                }));           

                //判断返回正确与否

                if (buf[3] == 0x00){

                    lblToolStripRxStatus.Text = "返回值正确!";

                }                             

                else if(buf[3] == 0x01){

                    lblToolStripRxStatus.Text = "返回值错误!";

                } 

                //判断校验是否正确

                byte rxParity;//接收校验和:(命令号+帧长+帧数据)&7f。

                rxParity = 0x01+0x01;

                rxParity += buf[3];

                rxParity &= 0x7F;

                if (rxParity != buf[4]) {

                    lblToolStripRxStatus.Text += "校验错误!";

                }  

            }

    三,总结

      总体上说,C#串口通信比较简单,发送数据用:

       byte[] package = new byte[18]{0};

       mycomm.Write(package, 0, 18);

    接收数据在串口的

     private void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)

      { 

    int n = mycomm.BytesToRead; 

    byte[] buf = new byte[n]; 

    comm.Read(buf, 0, n);

     }事件中。主要是Read/Write两个方法。

      需要注意的地方是每次接收到的数据未必是一个完整的包(尤其是包较长时),例如刚开始本人本机调试(本地收发)时收到的18字节经常是先收到9字节,再收到9字节,后者先2,再8,再8字节。导致接手区的数据不对(没有18字节,只有最开始的9或2字节),此时可以用一个缓冲数组保存接收到的数据,直到接收的长度正确或到包尾了再进行处理。

     

    以前好像忘记上传了,最近重写个。

    工程源码地址: http://download.csdn.net/detail/a379039233/8864605 ,不需要分。

    CSDN设置了分数,我也没办法。设置了共享链接:

    链接:https://pan.baidu.com/s/1dg_i5m4mV_ciXw_RlQLLKA 
    提取码:ly88

    展开全文
  • c#串口通讯

    2020-01-13 14:59:23
    } } /// /// 打开串口 /// /// 端口 /// 波特率 /// 奇偶校验检查协议 /// 每个字节的标准停止位数 public static SerialPort ConnectSerialPort(string portName, int baudRate, Parity parity, StopBits stopBits...
    using System;
    using System.IO.Ports;
    using System.Text;
    public class SerialPortHelper
        {
            public delegate void HanderInterfaceUpdataDelegate(string sendData);
            private static SerialPort _port;
            private static readonly object lockHelper = new object();
    
            public static SerialPort SerialPortIns
            {
                get
                {
                    if (_port == null)
                    {
                        lock (lockHelper)
                        {
                            _port = new SerialPort();
                        }
                    }
                    return _port;
                }
            }
    
            /// <summary>
            /// 打开串口
            /// </summary>
            /// <param name="portName">端口</param>
            /// <param name="baudRate">波特率</param>
            /// <param name="parity">奇偶校验检查协议</param>
            /// <param name="stopBits">每个字节的标准停止位数</param>
            public static SerialPort ConnectSerialPort(string portName, int baudRate, Parity parity, StopBits stopBits,int dataBits, Handshake handShake)
            {
                try
                {
                    _port = new SerialPort();
    
                    //端口
                    _port.PortName = portName;
                    //波特率
                    _port.BaudRate = baudRate;
                    //奇偶校验检查协议
                    _port.Parity = parity;
                    //每个字节的标准停止位数
                    _port.StopBits = stopBits;
                    //数据位
                    _port.DataBits = dataBits;
                    //握手协议
                    _port.Handshake = handShake;
    
                    //打开串口
                    if (!_port.IsOpen)
                    {
                        _port.Open();
                    }
    
                    return _port;
                }
                catch (System.Exception ex)
                {
                    return null;
                }
            }
    
            /// <summary>
            /// 关闭串口
            /// </summary>
            public static void CloseSerialPort(SerialPort port)
            {
                if (port.IsOpen)
                {
                    port.Close();
                }
                _port = null;
            }
    
            /// <summary>
            /// 接收数据
            /// </summary>
            /// <param name="port"></param>
            public static string ReceiveData(SerialPort port)
            {
                //Thread.Sleep(1000);
                var i = port.BytesToRead;
                byte[] bytes = new byte[i];
                port.Read(bytes, 0, i);
                string str = Encoding.Default.GetString(bytes);
                return str;
            }
    
            public static string ReceiveDataByLine(SerialPort port)
            {
                return port.ReadTo("\r\n");
            }
    
           
    
            /// <summary>
            /// 发送数据
            /// </summary>
            /// <param name="port"></param>
            /// <param name="text"></param>
            public static void SendBytesData(SerialPort port, string text)
            {
                port.Write(text);
            }
            
        }
    
    展开全文
  • c# 串口通讯和TCP通讯

    2018-08-15 11:21:40
    c# 串口通讯和TCP通讯。用途是根据串口通讯获得一起的准确数据,然后根据tcp发布出去,已经验证
  • C#串口通讯DEMO

    2019-07-16 17:03:49
    C#串口通讯demo,引用system.IO.Ports,SerialPort类,用ASCII发送接收,可接收汉字
  • C#串口通讯代码

    2018-09-10 10:28:49
    C#串口通讯代码 1)实时发送接收 2)自动获取端口 3)记录已发送命令,方便再次发送
  • C#串口通讯

    2017-11-28 16:32:23
    C#串口通讯类,基于System.IO.SerialPort类。内部默认处理了对串口操作中涉及的串口同步读取,按照协议解析数据等
  • C#串口通讯设计方法

    2020-08-20 14:41:08
    C# 串口通讯设计流程,如何进行通讯的设计,数据读写,解析,方法不重要重要的是思路,通讯协议数据部分只有字或字节的方式接收,所以最后读取截取的数据只能是字或字节的集合。
  • C#串口通讯实例

    2020-12-11 11:49:16
    文章目录C#串口通讯实例一、串口属性界面二、主界面特殊情况总结 C#串口通讯实例 本文参考《C#网络通信程序设计》(张晓明 编著) 程序界面如下图: 一、串口属性界面 参数设置界面代码如下: using System; using ...


    C#串口通讯实例

    本文参考《C#网络通信程序设计》(张晓明 编著)


    程序界面如下图:
    在这里插入图片描述

    一、串口属性界面

    参数设置界面代码如下:

    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 ComDemo
    {
        public partial class ComSet : Form
        {
            public ComSet()
            {
                InitializeComponent();
            }
    
            private void ComSet_Load(object sender, EventArgs e)
            {
                //串口
                string[] ports = SerialPort.GetPortNames();
                foreach (string port in ports)
                {
                    cmbPort.Items.Add(port);
                }
                cmbPort.SelectedIndex = 0;
    
                //波特率
                cmbBaudRate.Items.Add("110");
                cmbBaudRate.Items.Add("300");
                cmbBaudRate.Items.Add("1200");
                cmbBaudRate.Items.Add("2400");
                cmbBaudRate.Items.Add("4800");
                cmbBaudRate.Items.Add("9600");
                cmbBaudRate.Items.Add("19200");
                cmbBaudRate.Items.Add("38400");
                cmbBaudRate.Items.Add("57600");
                cmbBaudRate.Items.Add("115200");
                cmbBaudRate.Items.Add("230400");
                cmbBaudRate.Items.Add("460800");
                cmbBaudRate.Items.Add("921600");
                cmbBaudRate.SelectedIndex = 5;
    
                //数据位
                cmbDataBits.Items.Add("5");
                cmbDataBits.Items.Add("6");
                cmbDataBits.Items.Add("7");
                cmbDataBits.Items.Add("8");
                cmbDataBits.SelectedIndex = 3;
    
                //停止位
                cmbStopBit.Items.Add("1");
                cmbStopBit.SelectedIndex = 0;
    
                //佼验位
                cmbParity.Items.Add("无");
                cmbParity.SelectedIndex = 0;
            }
    
            private void bntOK_Click(object sender, EventArgs e)
            {
                //以下4个参数都是从窗体MainForm传入的
                MainForm.strProtName = cmbPort.Text;
                MainForm.strBaudRate = cmbBaudRate.Text;
                MainForm.strDataBits = cmbDataBits.Text;
                MainForm.strStopBits = cmbStopBit.Text;
                DialogResult = DialogResult.OK;
            }
    
            private void bntCancel_Click(object sender, EventArgs e)
            {
                DialogResult = DialogResult.Cancel;
            }
        }
    }
    

    二、主界面

    主界面代码如下:

    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;
    using System.IO;
    using System.Threading;
    
    namespace ComDemo
    {
        public partial class MainForm : Form
        {
            public MainForm()
            {
                InitializeComponent();
            }
            private Thread getRecevice;
            protected Boolean stop = false;
            protected Boolean conState = false;
            private StreamReader sRead;
            string strRecieve;
            bool bAccpet = false;
    
            SerialPort sp = new SerialPort();//实例化串口通讯类
            //以下定义4个公有变量,用于参数传递
            public static string strProtName = "";
            public static string strBaudRate = "";
            public static string strDataBits = "";
            public static string strStopBits = "";
    
            private void MainForm_Load(object sender, EventArgs e)
            {
                groupBox1.Enabled = false;
                groupBox2.Enabled = false;
                this.toolStripStatusLabel1.Text = "端口号:端口未打开 | ";
                this.toolStripStatusLabel2.Text = "波特率:端口未打开 | ";
                this.toolStripStatusLabel3.Text = "数据位:端口未打开 | ";
                this.toolStripStatusLabel4.Text = "停止位:端口未打开 | ";
                this.toolStripStatusLabel5.Text = "";
            }
            //串口设计
            private void btnSetSP_Click(object sender, EventArgs e)
            {
                timer1.Enabled = false;
                sp.Close();
                ComSet dlg = new ComSet();
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    sp.PortName = strProtName;//串口号
                    sp.BaudRate = int.Parse(strBaudRate);//波特率
                    sp.DataBits = int.Parse(strDataBits);//数据位
                    sp.StopBits = (StopBits)int.Parse(strStopBits);//停止位
                    sp.ReadTimeout = 500;//读取数据的超时时间,引发ReadExisting异常
                }
            }
            //打开/关闭串口
            private void bntSwitchSP_Click(object sender, EventArgs e)
            {
                if (bntSwitchSP.Text == "打开串口")
                {
                    if (strProtName != "" && strBaudRate != "" && strDataBits != "" && strStopBits != "")
                    {
                        try
                        {
                            if (sp.IsOpen)
                            {
                                sp.Close();
                                sp.Open();//打开串口
                            }
                            else
                            {
                                sp.Open();//打开串口
                            }
                            bntSwitchSP.Text = "关闭串口";
                            groupBox1.Enabled = true;
                            groupBox2.Enabled = true;
                            this.toolStripStatusLabel1.Text = "端口号:" + sp.PortName + " | ";
                            this.toolStripStatusLabel2.Text = "波特率:" + sp.BaudRate + " | ";
                            this.toolStripStatusLabel3.Text = "数据位:" + sp.DataBits + " | ";
                            this.toolStripStatusLabel4.Text = "停止位:" + sp.StopBits + " | ";
                            this.toolStripStatusLabel5.Text = "";
    
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show("错误:" + ex.Message, "C#串口通信");
                        }
                    }
                    else
                    {
                        MessageBox.Show("请先设置串口!", "RS232串口通信");
                    }
                }
                else
                {
                    timer1.Enabled = false;
                    timer2.Enabled = false;
                    bntSwitchSP.Text = "打开串口";
                    if (sp.IsOpen)
                        sp.Close();
                    groupBox1.Enabled = false;
                    groupBox2.Enabled = false;
                    this.toolStripStatusLabel1.Text = "端口号:端口未打开 | ";
                    this.toolStripStatusLabel2.Text = "波特率:端口未打开 | ";
                    this.toolStripStatusLabel3.Text = "数据位:端口未打开 | ";
                    this.toolStripStatusLabel4.Text = "停止位:端口未打开 | ";
                    this.toolStripStatusLabel5.Text = "";
                }
            }
            //发送数据
            private void bntSendData_Click(object sender, EventArgs e)
            {
                if (sp.IsOpen)
                {
                    try
                    {
                        sp.Encoding = System.Text.Encoding.GetEncoding("GB2312");
                        sp.Write(txtSend.Text);//发送数据
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("错误:" + ex.Message);
                    }
                }
                else
                {
                    MessageBox.Show("请先打开串口!");
                }
            }
            //选择文件
            private void btnOpenFile_Click(object sender, EventArgs e)
            {
                OpenFileDialog open = new OpenFileDialog();
                open.InitialDirectory = "c\\";
                open.RestoreDirectory = true;
                open.FilterIndex = 1;
                open.Filter = "txt文件(*.txt)|*.txt";
                if (open.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        if (open.OpenFile() != null)
                        {
                            txtFileName.Text = open.FileName;
                        }
                    }
                    catch (Exception err1)
                    {
                        MessageBox.Show("文件打开错误!  " + err1.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                }
            }
            //发送文件内容
            private void bntSendFile_Click(object sender, EventArgs e)
            {
                string fileName = txtFileName.Text.Trim();
                if (fileName == "")
                {
                    MessageBox.Show("请选择要发送的文件!", "Error");
                    return;
                }
                else
                {
                    //sRead = new StreamReader(fileName);
                    sRead = new StreamReader(fileName,Encoding.Default);//解决中文乱码问题
                }
                timer1.Start();
            }
            //发送文件时钟
            private void timer1_Tick(object sender, EventArgs e)
            {
                string str1;
                str1 = sRead.ReadLine();
                if (str1 == null)
                {
                    timer1.Stop();
                    sRead.Close();
                    MessageBox.Show("文件发送成功!", "C#串口通讯");
                    this.toolStripStatusLabel5.Text = "";
                    return;
                }
                byte[] data = Encoding.Default.GetBytes(str1);
                sp.Write(data, 0, data.Length);
                this.toolStripStatusLabel5.Text = "   文件发送中...";
            }
            //接收数据
            private void btnReceiveData_Click(object sender, EventArgs e)
            {
                if (btnReceiveData.Text == "接收数据")
                {
                    sp.Encoding = Encoding.GetEncoding("GB2312");
                    if (sp.IsOpen)
                    {
                        //timer2.Enabled = true; //使用主线程进行
    
                        //使用委托以及多线程进行
                        bAccpet = true;
                        getRecevice = new Thread(new ThreadStart(testDelegate));
                        //getRecevice.IsBackground = true;
                        getRecevice.Start();
                        btnReceiveData.Text = "停止接收";
                    }
                    else
                    {
                        MessageBox.Show("请先打开串口");
                    }
                }
                else
                {
                    //timer2.Enabled = false;
                    bAccpet = false;
                    try
                    {   //停止主监听线程
                        if (null != getRecevice)
                        {
                            if (getRecevice.IsAlive)
                            {
                                if (!getRecevice.Join(100))
                                {
                                    //关闭线程
                                    getRecevice.Abort();
                                }
                            }
                            getRecevice = null;
                        }
                    }
                    catch { }
                    btnReceiveData.Text = "接收数据";
                }
            }
            private void testDelegate()
            {
                reaction r = new reaction(fun);
                r();
            }
            //用于接收数据的定时时钟
            private void timer2_Tick(object sender, EventArgs e)
            {
                string str = sp.ReadExisting();
                string str2 = str.Replace("\r", "\r\n");
                txtReceiveData.AppendText(str2);
                txtReceiveData.ScrollToCaret();
            }
            //下面用到了接收信息的代理功能,此为设计的要点之一
            delegate void DelegateAcceptData();
            void fun()
            {
                while (bAccpet)
                {
                    AcceptData();
                }
            }
    
            delegate void reaction();
            void AcceptData()
            {
                if (txtReceiveData.InvokeRequired)
                {
                    try
                    {
                        DelegateAcceptData ddd = new DelegateAcceptData(AcceptData);
                        this.Invoke(ddd, new object[] { });
                    }
                    catch { }
                }
                else
                {
                    try
                    {
                        strRecieve = sp.ReadExisting();
                        txtReceiveData.AppendText(strRecieve);
                    }
                    catch (Exception ex) { }
                }
            }
    
            private void bntClear_Click(object sender, EventArgs e)
            {
                txtReceiveData.Text = "";
            }
    
            private void button3_Click(object sender, EventArgs e)
            {
                try
                {
                    string path = Directory.GetCurrentDirectory() + @"\output.txt";
                    string content = this.txtReceiveData.Text;
                    FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
                    StreamWriter write = new StreamWriter(fs);
                    write.Write(content);
                    write.Flush();
                    write.Close();
                    fs.Close();
                    MessageBox.Show("接收信息导出在:" + path);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }
    }
    

    特殊情况

    如果处于接收数据的时候,直接关闭程序,会有残余线程。可不可以把线程设置为background线程,或者在private override OnClosing里进行一下线程结束确认?我改成用BackgroundWorker了。

    private void bwReceive_DoWork(object obj, DoWorkEventArgs e)
    {
        while (true)
        {
            if(bwReceive.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
            Thread.Sleep(100);
            bwReceive.ReportProgress(0);
        }
    }
     
    private void bwReceive_ProgressChanged(object obj, ProgressChangedEventArgs e)
    {
        strReceive = sp.ReadExisting();
        txtReceiveData.AppendText(strReceive);
    }
     
    private void bwReceive_RunWorkerCompleted(object obj, RunWorkerCompletedEventArgs e)
    {
        if(e.Error!=null)
        {
            MessageBox.Show("Error: " + e.Error.Message, "C#通讯示例");
        }
        else if(e.Cancelled)
        {
            MessageBox.Show("停止接收数据!", "C#通讯示例");
        }
        else
        {
            MessageBox.Show("Task Completed!");
        }
    }
    

    总结

    提示:以上全是整合资源。

    展开全文
  • 串口通讯模块C串口串口通讯模块C#串口通讯模块C#讯模块C##串口通讯模块C#
  • C# 串口通讯Demo(VS2010)

    千次下载 热门讨论 2015-07-03 10:24:23
    一个简单的C# 串口通讯Demo,可收发数据。
  • C#串口通讯,项目实战分享,此文件主要是使用C#语言通过串口485与设备通讯控制;后期继续更新与优化。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 871
精华内容 348
关键字:

c#串口通讯

c# 订阅