C#上位机——串口助手高级02

C#上位机——串口助手高级

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

namespace 串口助手
{
    public partial class Form1 : Form
    {
        private bool isOpen = false;//打开标志

        private bool isRxShow = true;//接收标志

        private List<byte> reciveBuffer = new List<byte>();//接收数据缓冲区

        private List<byte> sendBuffer = new List<byte>();//定义发送缓冲区

        private int reciveCount = 0;//计数接收到数据

        private int sendCount = 0;//计数发送出的数据
        //SerialPort
        public Form1()
        {
            InitializeComponent();

            Control.CheckForIllegalCrossThreadCalls = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //在设计页面已经预先添加了COM1 COM2 COM3 
            //this.port_cbb.Items.Add("COM4");
            //this.port_cbb.Items.Add("COM5");

            //this.port_cbb.SelectedIndex = 2;

            //this.baud_cbb.SelectedIndex = 1;

            //this.check_cbb.SelectedIndex = 0;

            //this.databit_cbb.SelectedIndex = 3;

            //this.stopbit_cbb.SelectedIndex = 0;

            // 给发送框添加预设文本
            //  this.send_rtb.Text = "我是发送框";

            // 给接收框添加预设文本
            //  this.recive_rtb.Text = "我是接收框";

            serialLoad();//加载串口的属性
        }
        //自动加载串口端口号
        private void serialLoad()
        {

            EncodingInfo[] encodingInfos = Encoding.GetEncodings();//支持的字符编码


            RegistryKey keyCom = Registry.LocalMachine.OpenSubKey(@"Hardware\DeviceMap\SerialComm");

            string[] sSubKeys = keyCom.GetValueNames();
            port_cbb.Items.Clear();
            foreach (var sValue in   sSubKeys)
            {
                string portName = (string)keyCom.GetValue(sValue);
                port_cbb.Items.Add(portName);
            }

            this.port_cbb.SelectedIndex = 0;

            this.baud_cbb.SelectedIndex = 1;

            this.check_cbb.SelectedIndex = 0;

            this.databit_cbb.SelectedIndex = 3;

            this.stopbit_cbb.SelectedIndex = 0;
        }
        //发送数据
        private void sendData()
        {

            serialPort1.Write(sendBuffer.ToArray(),0,sendBuffer.Count);
            sendCount += sendBuffer.Count;
            recivecount_tssl.Text = sendCount.ToString();
        }

        private void send_btn_Click(object sender, EventArgs e)
        {
            // 如果发送的数据不为空,则接收
            if (this.send_rtb.Text != "" && serialPort1.IsOpen)
            {
                Console.WriteLine(Transform.ToHexString(sendBuffer.ToArray()));
                sendData();
            }
            else
            {
                MessageBox.Show("请先输入发送数据!");

            }
        }

        private void open_btn_Click(object sender, EventArgs e)
        {
            try
            {
                if (serialPort1.IsOpen == false)
                {
                    serialPort1.PortName = port_cbb.Text;
                    serialPort1.BaudRate = Convert.ToInt32(baud_cbb.Text);
                    serialPort1.DataBits = Convert.ToInt32(databit_cbb.Text);
                    switch (check_cbb.SelectedIndex)
                    {
                        //  none  odd  even 
                        case 0:
                            serialPort1.Parity = Parity.None;
                            break;
                        case 1:
                            serialPort1.Parity = Parity.Odd;
                            break;
                        case 2:
                            serialPort1.Parity = Parity.Even;
                            break;
                        default:
                            serialPort1.Parity = Parity.None;
                            break;
                    }
                    switch (stopbit_cbb.SelectedIndex)
                    {
                        // 1 1.5 2
                        case 0:
                            serialPort1.StopBits = StopBits.One;
                            break;
                        case 1:
                            serialPort1.StopBits = StopBits.OnePointFive;
                            break;
                        case 2:
                            serialPort1.StopBits = StopBits.Two;
                            break;
                        default:
                            serialPort1.StopBits = StopBits.One;
                            break;
                    }

                    serialPort1.Open();
                    isOpen = true;
                    open_btn.Text = "关闭串口";


                }
                else
                {
                    serialPort1.Close();
                    isOpen = false;
                    open_btn.Text = "打开串口";

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString()+serialPort1.PortName.ToString());
            }
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (isRxShow == false) return;
            // 1,需要读取有效的数据 BytesToRead
            byte[] dataTemp = new byte[serialPort1.BytesToRead];//将串口中的数据读出来
            serialPort1.Read(dataTemp,0,dataTemp.Length);//0表示偏移地址,dataTemp.Length表示数据长度

            reciveBuffer.AddRange(dataTemp);//将数据缓存到buff中

            reciveCount += dataTemp.Length;//进行接收计数

            //将buff中的数据更新到页面中,异步线程,更新UI
            this.Invoke(new EventHandler(delegate
            {
                // 显示接收数据的长度
                recivecount_tssl.Text = reciveCount.ToString();

                if (!recivehex_chb.Checked)//如果没有选中
                {
                    // 2, 编码格式的选择
                    string str = Encoding.GetEncoding("gb2312").GetString(dataTemp);//gb2312编码格式来接收数据
                    // 3,0x00 -> \0 结束 不会显示
                    str =str.Replace("\0", "\\0");//发送00时,转译为\0

                    recive_rtb.AppendText(str);

                   // recive_rtb.AppendText(Encoding.GetEncoding("gb2312").GetString(dataTemp).Replace("\0", "\\0"));
                }
                else
                {
                    //  十六进制是选中的状态下
                    recive_rtb.AppendText(Transform.ToHexString(dataTemp, " "));
                }

            }));
        }

        private void stop_btn_Click(object sender, EventArgs e)
        {
            if (isRxShow == true)
            {
                isRxShow = false;
                stop_btn.Text = "取消暂停";
            }
            else
            {
                isRxShow = true;
                stop_btn.Text = "暂停";
            }
        }

        private void recivehex_chb_CheckedChanged(object sender, EventArgs e)
        {
            if (recive_rtb.Text == "") return;
            if (recivehex_chb.Checked)
            {
                recive_rtb.Text = Transform.ToHexString(reciveBuffer.ToArray()," ");//以十六进制的形式显示出来
            }
            else
            {
                recive_rtb.Text = Encoding.GetEncoding("gb2312").GetString(reciveBuffer.ToArray()).Replace("\0","\\0");//以字符串的形式显示出来
            }
        }

        private void clear_btn_Click(object sender, EventArgs e)
        {
            reciveBuffer.Clear();
            recivecount_tssl.Text = "";
            recive_rtb.Text = "";
        }

        private void autoclear_chb_CheckedChanged(object sender, EventArgs e)
        {
            if (autoclear_chb.Checked)
            {


                timer1.Start();
            }
            else
            {
                timer1.Stop();
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (recive_rtb.Text.Length > 4096)
            {
                reciveBuffer.Clear();
                recive_rtb.Text = "";
                recivecount_tssl.Text = "";
            }
        }

        private void send_rtb_Leave(object sender, EventArgs e)
        {
            if (sendhex_chb.CheckState == CheckState.Checked)
            {
                if (DataEncoding.IsHexString(send_rtb.Text.Replace(" ", "")))
                {
                    sendBuffer.Clear();
                    sendBuffer.AddRange(Transform.ToBytes(send_rtb.Text.Replace(" ", "")));

                }
                else
                {
                    MessageBox.Show("请输入正确的十六进制数据!!");
                    send_rtb.Select();
                }
            }
            else
            {
                sendBuffer.Clear();
                sendBuffer.AddRange(Encoding.GetEncoding("gb2312").GetBytes(send_rtb.Text));
            }
        }

        private void send_rtb_TextChanged(object sender, EventArgs e)
        {
            // 十六进制切换 会出现问题  这问题就是0x00 转换
        }

        private void sendhex_chb_CheckedChanged(object sender, EventArgs e)
        {
            if (send_rtb.Text == "") return;

            if (sendhex_chb.Checked == true)
            {
                send_rtb.Text = Transform.ToHexString(sendBuffer.ToArray(), " ");//每一个字符以空格的形式隔开
            }
            else 
            { 
                send_rtb.Text = Encoding.GetEncoding("gb2312").GetString(sendBuffer.ToArray()).Replace("\0","\\0");

            }
        }

        private void sendclear_btn_Click(object sender, EventArgs e)
        {
            sendBuffer.Clear();

            send_rtb.Text = "";

            sendCount = 0;

            recivecount_tssl.Text = "0";
        }
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
是杰杰之前做的 一个参赛小作品 其实在做这个恒温控制系统项目的时候,师弟就问我,什么是上位机。。。。。可能很多师弟师妹都没一个大概的概念。 现在,就来看下什么是上位机上位机是指可以直接发出操控命令的计算机,一般是PC/host computer/master computer/upper computer,屏幕上显示各种信号变化(液压,水位,温度等)。下位机是直接控制设备获取设备状况的计算机,一般是PLC/单片机single chip microcomputer/slave computer/lower computer之类的。上位机发出的命令首先给下位机,下位机再根据此命令解释成相应时序信号直接控制相应设备。下位机不时读取设备状态数据(一般为模拟量),转换成数字信号反馈给上位机。简言之如此,实际情况千差万别,但万变不离其宗:上下位机都需要编程,都有专门的开发系统。 在概念上,控制者和提供服务者是上位机,被控制者和被服务者是下位机,也可以理解为主机和从机的关系,但上位机和下位机是可以转换的。 工作原理 两机如何通讯,一般取决于下位机,TCP/IP一般是支持的,但是下位机一般具有更可靠的独有通讯协议。通常上位机和下位机通讯可以采用不同通讯协议,可以有RS232的串口通讯或者采用RS485串行通讯。采用封装好的程序开发工具就可以实现下位机和上位机的通讯,当然可以自己编写驱动类的接口协议控制上位机和下位机的通讯。 通常工控机,工作站,触摸屏作为上位机,通信控制PLC,单片机等作为下位机,从而控制相关设备元件和驱动装置。 既然差不多知道什么是上位机与下位机,那么,我们做到小喇叭的要求:就得写个上位机,我自己也是学了下C#,用来开发上位机还是可以的,开发环境用visual studio 2015,微软的软件真的是很简单,之前看到有人问为什么微软的软件是最多人用的,答:因为那是傻瓜式操作。。。。。我不得不认同。。。 回归正题:先看看我们的上位机有什么功能: 1)能够实现与下位机的正常通讯。这必须得有,不然算哪门子上位机啊。 2)能够控制我们的恒温系统,通过电脑控制恒温系统的温度。这种应用场景很正常,我在机房就能控制我某一个地方的温度,简单方便。 3)能够实时显示温度与波形。这种应用的场景也是非常常见,实时显示温度我们可以知道温度是否正常,而波形我们能快速看出恒温系统空间温度是否出现异常。 4)数据保存功能,自动将实时的温度保存下来,加入 日期与时间,方便以后排查问题的时候用于检测某段时间的温度是否正常,这也是很使用的功能。 说了那么多,看看我们的上位机。由于我以前用的别人的上位机都是色调比较单一的,而我,又是那种比较活泼开朗的人,觉得单一的灰色调比较死沉,我不喜欢,当然那是别人做的上位机,即使再不喜欢,要用还是要用,没办法, 现在我自己做的就不一样了,得给他做个五颜六色出来。亮瞎眼。。。。。 1.png 2.jpg 3.jpg 当我们的温度达到目标温度的时候,下位机就会控制自己的温度,以保持温度恒定,同时在上位机显示看到温度为一条曲线,由于我设置的温度为整数,没有小数,但是我们通过下位机可以看到实时的温度,精确在0.4范围左右。 4.jpg 当我们把上位机与下位机通讯协议切断,可以看到上位机接受不到数据(在软件右下角粉红色的窗口,没有显示接收到的数据),上位机的波形就会回到默认值(0°),就是上图的样子 5.jpg 6.jpg 当我们需要后期的检测与排除故障的时候,我们可以从我们保存的温度来做简单的排查,上位机自动保存的温度数据,精确到某天某时某分某秒,简单方便。也是一个很实用的功能当没什么故障的时候,我们只需要隔一段时间吧数据清一下就OK了。 附上作品视频:http://v.youku.com/v_show/id_XMzE0Nzg0ODUzMg==.html?spm=a2h0k.8191407.0.0&from=s1.8-1-1.2 本次上位机介绍到此结束 源码文件会可以关注关注获得。 或者CSDN下载连接: 本上位机仅为杰杰个人娱乐,不做商业用途。 如需转载请说明出处。 欢迎关注“创客飞梦空间” 干货不间断 在未来的日子里 创客飞梦空间与你们同在,放飞我们的梦想
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

傻童:CPU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值