c#上位机 订阅
C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。尽管C语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,以一个标准规格写出的C语言程序可在包括类似嵌入式处理器以及超级计算机等作业平台的许多计算机平台上进行编译。 [1] 展开全文
C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发。C语言能以简易的方式编译、处理低级存储器。C语言是仅产生少量的机器语言以及不需要任何运行环境支持便能运行的高效率程序设计语言。尽管C语言提供了许多低级处理的功能,但仍然保持着跨平台的特性,以一个标准规格写出的C语言程序可在包括类似嵌入式处理器以及超级计算机等作业平台的许多计算机平台上进行编译。 [1]
信息
类    别
程序设计语言
影响语言
C++、C#、D、Java、JavaScript、ObjectPHP等
创始时间
1972年
主要编译器
Visual C++、Clang、GCC、Turbo C等
中文名
C语言
创始人
Dennis MacAlistair Ritchie
发    源
BCPL语言
外文名
C Programming Language
c语言简介
C语言是一门面向过程的计算机编程语言,与C++、Java等面向对象编程语言有所不同。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、仅产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。C语言描述问题比汇编语言迅速、工作量小、可读性好、易于调试、修改和移植,而代码质量与汇编语言相当。C语言一般只比汇编语言代码生成的目标程序效率低10%~20%。因此,C语言可以编写系统软件。 [2]  当前阶段,在编程领域中,C语言的运用非常之多,它兼顾了高级语言和汇编语言的优点,相较于其它编程语言具有较大优势。计算机系统设计以及应用程序编写是C语言应用的两大领域。同时,C语言的普适较强,在许多计算机操作系统中都能够得到适用,且效率显著。 [3]  冯.诺依曼在1945年提出了现代计算机的若干思想,被后人称为冯.诺依曼思想,这是计算机发展史上的里程碑。自1945 年至今大多采用其结构,因此冯.诺依曼被称为计算机之父。他的体系结构计算机由运算器、控制器、存储器、输入设备、输出设备五大部件构成。 C语言拥有一套完整的理论体系经过了漫长的发展历史,在编程语言中具有举足轻重的地位。 [4] 
收起全文
精华内容
下载资源
问答
  • c#上位机
    千次阅读
    2022-05-21 20:15:33

    基本介绍

    语言与开发技术:
    C#、Winform。
    串口通讯是上位机的基础功能,可以通过USB等COM串口进行数据的收发,实现数据采集,自动控制等功能。一套完整的串口通讯功能可以分为以下几个功能:属性设置,串口开关(检测),数据发送,数据接收。同时我们还有如下几个重要参数:
    波特率:
    波特率的大小代表每秒钟可以传输多少个二进制位,如波特率是9600,能每秒传输9600个二进制位。
    常用数值:
    4800
    9600
    14400
    19200
    38400
    56000
    57600
    115200
    128000
    256000
    起始位、停止位
    数据包从起始位开始,到停止位结束。起始信号用逻辑0的数据位表示,停止信号由0.5、1、1.5或2个逻辑1的数据位表示,只要双方约定一致即可。
    常用数值:
    1
    1.5
    2
    None
    数据位
    起始位之后便是传输的主体数据内容了,也称为有效数据,其长度一般被约定为5、6、7或8位长。
    常用数值:
    5
    6
    7
    8
    奇偶校验位
    由于在通讯过程中易受到外部干扰导致传输数据出现偏差,所以在有效数据之后加上校验位解决。
    常用数值:
    Even
    Odd
    None

    参数配置

    先在界面端布置好控件,示例如下:在这里插入图片描述
    大致结构:
    在这里插入图片描述

    一些声明:

     SerialPort sp = null;//声明一个串口类
            bool isOpen = false;//打开串口标志位
            bool isSetProperty = false;//属性设置标志位
            bool isHex = false;//十六进制显示标志位
    

    后端代码示例:

     for (int i = 0; i < 10; i++)//最大支持到串口10,可根据自己需求增加
                {
                    cbxCOMPort.Items.Add("COM" + (i + 1).ToString());
    
                }
                cbxCOMPort.SelectedIndex = 0;
                //列出常用的波特率
                cbxBaudRate.Items.Add("1200");
                cbxBaudRate.Items.Add("2400");
                cbxBaudRate.Items.Add("4800");
                cbxBaudRate.Items.Add("9600");
                cbxBaudRate.Items.Add("19200");
                cbxBaudRate.Items.Add("38400");
                cbxBaudRate.Items.Add("43000");
                cbxBaudRate.Items.Add("56000");
                cbxBaudRate.Items.Add("57600");
                cbxBaudRate.Items.Add("115200");
                cbxBaudRate.SelectedIndex = 5;
                //列出停止位
                cbxStopBits.Items.Add("0");
                cbxStopBits.Items.Add("1");
                cbxStopBits.Items.Add("1.5");
                cbxStopBits.Items.Add("2");
                cbxStopBits.SelectedIndex = 1;
                //列出数据位
                cbxDataBits.Items.Add("8");
                cbxDataBits.Items.Add("7");
                cbxDataBits.Items.Add("6");
                cbxDataBits.Items.Add("5");
                cbxDataBits.SelectedIndex = 0;
                //列出奇偶校验位
                cbxParity.Items.Add("无");
                cbxParity.Items.Add("奇校验");
                cbxParity.Items.Add("偶校验");
                cbxParity.SelectedIndex = 0;
                //默认为Char显示
                rbnChar.Checked = true;
    

    属性设置,打开串口前代码端的参数配置:

     private void SetPortProperty()
            {
                sp = new SerialPort();
                sp.PortName = cbxCOMPort.Text.Trim();//设置串口名
                sp.BaudRate = Convert.ToInt32(cbxBaudRate.Text.Trim());//设置串口的波特率
                float f = Convert.ToSingle(cbxStopBits.Text.Trim());//设置停止位
                if (f == 0)
                {
                    sp.StopBits = StopBits.None;
                }
                else if (f == 1.5)
                {
                    sp.StopBits = StopBits.OnePointFive;
                }
                else if (f == 1)
                {
                    sp.StopBits = StopBits.One;
                }
                else if (f == 2)
                {
                    sp.StopBits = StopBits.Two;
                }
                else
                {
                    sp.StopBits = StopBits.One;
                }
                sp.DataBits = Convert.ToInt16(cbxDataBits.Text.Trim());//设置数据位
                string s = cbxParity.Text.Trim();//设置奇偶校验位
                if (s.CompareTo("无") == 0)
                {
                    sp.Parity = Parity.None;
                }
                else if (s.CompareTo("奇校验") == 0)
                {
                    sp.Parity = Parity.Odd;
                }
                else if (s.CompareTo("偶校验") == 0)
                {
                    sp.Parity = Parity.Even;
                }
                else
                {
                    sp.Parity = Parity.None;
                }
    
                sp.ReadTimeout = -1;//设置超时读取时间
                sp.RtsEnable = true;
    
                //定义DataReceived事件,当串口收到数据后触发事件
                sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
                if (rbnHex.Checked)
                {
                    isHex = true;
                }
                else
                {
                    isHex = false;
                }
            }
    

    串口开关与检测

    串口检测,即检测可用串口,并自动显示在界面:

     private void btnCheckCom_Click_1(object sender, EventArgs e)
            {
                bool comExistence = false;//有可用串口标志位
                cbxCOMPort.Items.Clear();//清除当前串口号中的所有串口名称
                for (int i = 0; i < 10; i++)
                {
                    try
                    {
                        SerialPort sp = new SerialPort("COM" + (i + 1).ToString());
                        sp.Open();
                        sp.Close();
                        cbxCOMPort.Items.Add("COM" + (i + 1).ToString());
                        comExistence = true;
    
                    }
                    catch (Exception)
                    {
                        continue;
                    }
                }
    
                if (comExistence)
                {
                    cbxCOMPort.SelectedIndex = 0;//使ListBox显示第1个添加的索引
                }
                else
                {
                    MessageBox.Show("没有找到可用串口!", "错误提示");
                }
    
            }
    
    

    在此处可以添加开关触发接口,检测后自动连接,也可以在多个串口同时需要开启时设置串口位,比如XX功能串口要求串口号1-5,XX功能串口要求串口号6-10,然后在代码中更改for的范围;
    串口打开(关闭):

    /// <summary>
            /// 串口状态检测:是否设置、是否占用
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnOpenCom_Click(object sender, EventArgs e)
            {
                if (isOpen == false)
                {
                    if (!CheckPortSetting())//检测串口设置
                    {
                        MessageBox.Show("串口未设置!", "错误提示");
                        return;
                    }
    
    
                    if (!isSetProperty)//串口未设置则设置串口
                    {
                        SetPortProperty();
                        isSetProperty = true;
                    }
                    try//打开串口
                    {
                        sp.Open();
                        isOpen = true;
                        btnOpenCom.Text = "关闭串口";
                       
                    }
                    catch (Exception)
                    {
                        //打开串口失败后,相应标志位取消
                        isSetProperty = false;
                        isOpen = false;
                        MessageBox.Show("串口无效或已被占用!", "错误提示");
                    }
                }
                else
                {
                    try//打开串口
                    {
                        sp.Close();
    
                        isOpen = false;
                        isSetProperty = false;
                        btnOpenCom.Text = "打开串口";
                       
                    }
                    finally { }
                }
            }
    

    数据发送

    设置发送数据的格式(字符or十六进制):

     /// <summary>
            /// 发送串口数据
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnSend_Click(object sender, EventArgs e)
            {
                if (isOpen)//写串口数据
                {
                    try
                    {
                        byte[] data = null;
                        if (SendHex.Checked)
                        {
                            data = getBytesFromString(tbxSendData.Text);
                            sp.Write(data, 0, data.Length);
                        }
                        else
                            sp.WriteLine(tbxSendData.Text);
                    }
                    catch (Exception)
                    {
                        MessageBox.Show("发送数据时发生错误!", "错误提示");
                        return;
                    }
                }
                else
                {
                    MessageBox.Show("串口未打开!", "错误提示");
                    return;
                }
    
                if (!CheckSendData())//检测要发送的数据
                {
    
                    MessageBox.Show("请输入要发送的数据!", "错误提示");
                    return;
                }
            }
    

    数据接收

    接收数据时同样分为16进制接收和字符接收,并显示到界面的Text:

    private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                System.Threading.Thread.Sleep(100);//延时100ms等待接收完数据
    
                // this.Invoke就是跨线程访问ui的方法
    
                this.Invoke((EventHandler)(delegate
                {
                    if (isHex == false)//格式判断
                    {
                        tbxRecvData.Text += sp.ReadLine();
                    }
                    else
                    {
                        Byte[] ReceivedData = new Byte[sp.BytesToRead];
                        sp.Read(ReceivedData, 0, ReceivedData.Length);
                        String RecvDataText = null;
                        String Hexadecimal = null; 
                            for (int i = screen; i < ReceivedData.Length - 1 - screen; i++)
                            {
                                RecvDataText += ("0x" + ReceivedData[i].ToString("X2") + "");
                                Hexadecimal = ReceivedData[i].ToString("X2");
                                //getHex.Text += Convert.ToString(GetHexadecimalValue(Hexadecimal)) + " ";
                            }
                        
                        tbxRecvData.Text += RecvDataText+ "\r\n";
                        //getHex.Text += "\r\n";
    
    
                    }
                    sp.DiscardInBuffer();//丢弃接收缓冲区数据
                }));
            }
    

    相关功能函数

    内容检查:

    /// <summary>
            /// 检查是否发送数据
            /// </summary>
            /// <returns></returns>
            private bool CheckSendData()
            {
                if (tbxSendData.Text.Trim() == "")
                    return false;
                return true;
            }
    

    格式转换:

    /// <summary>
            /// 把十六进制格式的字符串转换成字节数组。
            /// </summary>
            /// <param name="pString">要转换的十六进制格式的字符串</param>
            /// <returns>返回字节数组。</returns>
            public static byte[] getBytesFromString(string pString)
            {
                string[] str = pString.Split(' ');     //把十六进制格式的字符串按空格转换为字符串数组。
                byte[] bytes = new byte[str.Length];     //定义字节数组并初始化,长度为字符串数组的长度。
                for (int i = 0; i < str.Length; i++)     //遍历字符串数组,把每个字符串转换成字节类型赋值给每个字节变量。
                    bytes[i] = Convert.ToByte(Convert.ToInt32(str[i], 16));
                return bytes;     //返回字节数组。
            }
    

    还有可能用得到的进制转换:

     /// <summary>
            /// 十六进制换算为十进制
            /// </summary>
            /// <param name="strColorValue"></param>
            /// <returns></returns>
            public static int GetHexadecimalValue(String strColorValue)
            {
                char[] nums = strColorValue.ToCharArray();
                int total = 0;
                try
                {
                    for (int i = 0; i < nums.Length; i++)
                    {
                        String strNum = nums[i].ToString().ToUpper();
                        switch (strNum)
                        {
                            case "A":
                                strNum = "10";
                                break;
                            case "B":
                                strNum = "11";
                                break;
                            case "C":
                                strNum = "12";
                                break;
                            case "D":
                                strNum = "13";
                                break;
                            case "E":
                                strNum = "14";
                                break;
                            case "F":
                                strNum = "15";
                                break;
                            default:
                                break;
                        }
                        double power = Math.Pow(16, Convert.ToDouble(nums.Length - i - 1));
                        total += Convert.ToInt32(strNum) * Convert.ToInt32(power);
                        
                    }
    
                }
                catch (System.Exception ex)
                {
                    String strErorr = ex.ToString();
                    return -1;
                }
    
    
               return total;
            }
    
    更多相关内容
  • C#工控上位机实例-「C#上位机」西门子1200PLC实用定位控制程序案例 c#经典案例.pdf
  • 一个用C#开发上位机的帮助类库,能减少重复开发某个模块的工作量。提高工作效率。同时帮助初学者提高自己的业务水平。 1.该资源是我上一个版本的2.0版本。其中增加了很多自定义通讯协议和数据同步的协议。 2.并且...
  • 很好基于C#语言的一个串口通信上位机程序,有界面,可以自己设置波特率和串口号.
  • 一个用C#开发上位机的帮助类库,能减少重复开发某个模块的工作量。提高工作效率。同时帮助初学者提高自己的业务水平。里面包含了Windows API、加密解密序列化、可移动设备管理类、各种仪表控件库、多媒体处理类、...
  • C#上位机串口助手源码
  • C#上位机开发视频,包含上位机串口助手开发,串口控制下位机,PC串口接收发送数据等的视频讲解,还有C#教程资料
  • 基于C#上位机开发实战指南,介绍了上位机软件开发过程中重点内容以及注意事项。
  • C#上位机源代码

    2018-03-14 17:21:52
    void Send_toMy(short a,short b,short c,short d,short e,short f) { u8 tbuf[14]; tbuf[0]=0XAA; tbuf[1]=0XAA; tbuf[2]=(a>>8)&0XFF; tbuf[3]=a&0XFF; tbuf[4]=(b>>8)&0XFF; tbuf[5]=b&0XFF;...}
  • C#上位机通过TCP通讯与库卡机器人连接,可实时返回机器人各关节位置,返回位置可导出为.CSV文件; 通过上位机控制机器人,实现各关节单步运动及当前位置到给定坐标的点运动两种形式; 资源包括【KUKA端】、【PC端】...
  • C#上位机通讯控件(含PLC控件).rar
  • 采用C#开发,将下位机发送的数据显示并绘制曲线,配套FPGA频率计下位机
  • 【亲测有效】C#上位机与PanasonicPLC通讯 文件类型:c# 主要功能: 写PLC单个外部输出 写PLC单个内部继电器 写PLC数据寄存器 写PLC多个外部输出触电 写PLC多个内部寄存器 获取PLC运行状态 读PLC多个外部输出触电 读...
  • 自己编写上位机控制伺服电机动作,本代码中主要实现了位置控制模式和速度控制模式,其他模式也都类似,都是通过发送SDO报文来改写相应的对象字典就可以了。其中要注意1、主站的eds文件里面SDO,PDO等对象涉及到从站ID...
  • 温度通过下位机发送,上位机显示,C#平台,串口通信
  • c#上位机界面用于查找图片
  • 本软件使用C#语言,基于TCP/IP协议,写了一个简单的上位机服务,该服务接受ESP8266的连接,并将其发送过来的数据编码为图像进行显示。由于软件写的很简单,因此很多功能并没有进行扩充实现,如其只支持一个设备的...
  • C#上位机与单片机的完美结合(内附有用户登录,注册,截图,温度采集,历史数据展示,左边菜单右边内容展示的主界面
  • c#上位机木材干燥控制系统,可运行,供大家参考交流。
  • C#上位机串口接收温度数据
  • 基于Zigbee的智能家居,串口传送数据到PC上位机C#)显示,有直观的图形界面,可以控制下发数据命令
  • C#写的上位机和OMRON PLC modbus通讯,不需要第三方DLL,已经有实际运行,稳定好用。C#代码及VB.NET代码全部是由本人参照说明书编写。
  • 利用C# 完成移动监测运动平台控制-热成像校准-运动机构 C#上位机开发与设计,内容设计到了串口应用,绘制图形,数据截取与处理
  • C#编写的一个上位机程序,能进行串口通信校验,极具参考价值,省了不少功夫,不错的上位机开发参考! 在Windows上,最早用VB语言开发,后来由于C++的发展,采用MFC开发,近几年,微软发布了基于.NET框架的面向...
  • C#上位机资料

    2019-01-27 02:35:32
    入门C#设计资料
  • 通过C#语言做的一个与西门子PLC通信的上位机DEMO,可做参考使用。使用的是西门子的S7.NET库文件进行,对上位机开发有帮助
  • c#上位机串口通讯控制stm32步进电机

    热门讨论 2015-05-24 20:38:13
    本历程用的是VS2012程序编写,用c#编程,本包为工程压缩包,非exe执行文件,历程实现串口实时控制stm32控制步进电机正转翻转,转动速度的控制,还有可固定角度转动,每一句的程序后均有解释语句,适合c#串口通信入门...
  • 数据采集上位机,采用c#实现,界面美观,功能实用,可靠
  • C#上位机(定时器计数)

    千次阅读 2022-03-15 14:02:11
    定时器上位机用到的是Timer组件,注意对其初始化时一般为1000ms。 定时器初始化设置为1s。 2.编写函数 2.1 实现下拉框列表中有数据,并对其进行初始化。实现该功能,在窗体函数中撰写。双击窗体部分,创建函数。 ...

    1.对窗体进行编辑,并对每一个控件进行属性修改
    在这里插入图片描述

    1.控件可以直接拖进窗体中;
    2.对每一个控件进行修改;主要修改Test(窗体显示的部分)和Name(内部函数名,一般建议大驼峰格式命名。)
    3.特别是组件,一般不在窗体中显示,比如Timer,串口等。定时器上位机用到的是Timer组件,注意对其初始化时一般为1000ms。

    在这里插入图片描述
    定时器初始化设置为1s。
    在这里插入图片描述
    2.编写函数

    2.1 实现下拉框列表中有数据,并对其进行初始化。实现该功能,在窗体函数中撰写。双击窗体部分,创建函数。

    //窗体函数
    private void FormTimerTest_Load(object sender, EventArgs e)
    {
         //下拉框计数范围
         for (int i = 1; i < 100; i++)
         {
             //初始化下拉框,数字后加一个空格是为了更容易获取字符
             //每一个变量都属于一个对象,i.ToString()获取字符串。
             comboBox1Count.Items.Add(i.ToString() + " 秒");
         }
         //默认下拉框显示为“1 秒”
         comboBox1Count.Text = "1 秒";
    }
    
    //开始计时按钮函数
    private void button1Start_Click(object sender, EventArgs e)
    {
    	//存储设定的定时值
    	int time = 0;
    	//将下拉框数添加至一个变量中
    	string str = comboBox1Count.Text;
    	//获取str中的子字符串,占两个字节,从0号位置开始。注意此汉字占一个字节。
    	string data = str.Substring(0,2);
    	//将字符串转换为十六位带符号整形,得到设定的整形定时值。
    	time = Convert.ToInt16(data);
    	}
    

    在这里插入图片描述
    1.ToInt16将字符串转换为十六位带符号整形,得到设定的整形定时值。
    *2.public string Substring(int startIndex, int length);
    子字符串从指定的字符位置开始且具有指定的长度在这里插入图片描述
    *

    2.2 实现定时器函数,实现该功能,双击定时器组件。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Timer
    {
        public partial class FormTimerTest : Form
        {
            //存储设定的定时值
            int time = 0;
            //用于定时器计数
            int count = 0;
    
    
            public FormTimerTest()
            {
                InitializeComponent();
            }
    
            //开始计时按钮函数
            private void button1Start_Click(object sender, EventArgs e)
            {
    
                //将下拉框数添加至一个变量中
                string str = comboBox1Count.Text;
                //获取str中的子字符串,占两个字节,从0号位置开始。注意此汉字占一个字节。
                string data = str.Substring(0, 2);
                //将字符串转换为十六位带符号整形,得到设定的整形定时值。
                time = Convert.ToInt16(data);
                //开始计时
                timer1.Start();
            }
    
            //窗体函数
            private void FormTimerTest_Load(object sender, EventArgs e)
            {
                //下拉框计数范围
                for (int i = 1; i < 100; i++)
                {
                    //初始化下拉框,数字后加一个空格是为了更容易获取字符
                    //每一个变量都属于一个对象,i.ToString()获取字符串。
                    comboBox1Count.Items.Add(i.ToString() + " 秒");
                }
                //默认下拉框显示为“1 秒”
                comboBox1Count.Text = "1 秒";
            }
    
            //定时器函数
            private void timer1_Tick(object sender, EventArgs e)
            {
    
                //记录当前秒数。初始化是1000ms
                count++;
                //获取剩余的秒数,time是设置的定时值,count是系统每经过1秒,则加一次。即(time - count)是剩余的时间。
                int remain = time - count;
                //将剩余的描述显示在label3RemainTimeCount控件中。
                label3RemainTimeCount.Text = remain.ToString() + " 秒";
                //count == time则时间到
                if (count == time)
                {
                    //停止计时
                    timer1.Stop();
                    //设置提示音
                    System.Media.SystemSounds.Asterisk.Play();
                    //弹出提示框
                    MessageBox.Show("时间到!", "提示");
                }
            }
        }
    }
    
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    3.对滚动条进行设置
    在这里插入图片描述
    在这里插入图片描述

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Timer
    {
        public partial class FormTimerTest : Form
        {
            //存储设定的定时值
            int time = 0;
            //用于定时器计数
            int count = 0;
    
    
            public FormTimerTest()
            {
                InitializeComponent();
            }
    
            //开始计时按钮函数
            private void button1Start_Click(object sender, EventArgs e)
            {
    
                //将下拉框数添加至一个变量中
                string str = comboBox1Count.Text;
                //获取str中的子字符串,占两个字节,从0号位置开始。注意此汉字占一个字节。
                string data = str.Substring(0, 2);
                //将字符串转换为十六位带符号整形,得到设定的整形定时值。
                time = Convert.ToInt16(data);
                //设置进度条最大值
                progressBar1Time.Maximum = time;
                //开始计时
                timer1.Start();
            }
    
            //窗体函数
            private void FormTimerTest_Load(object sender, EventArgs e)
            {
                //下拉框计数范围
                for (int i = 1; i < 100; i++)
                {
                    //初始化下拉框,数字后加一个空格是为了更容易获取字符
                    //每一个变量都属于一个对象,i.ToString()获取字符串。
                    comboBox1Count.Items.Add(i.ToString() + " 秒");
                }
                //默认下拉框显示为“1 秒”
                comboBox1Count.Text = "1 秒";
            }
    
            //定时器函数
            private void timer1_Tick(object sender, EventArgs e)
            {
    
                //记录当前秒数。初始化是1000ms
                count++;
                //获取剩余的秒数,time是设置的定时值,count是系统每经过1秒,则加一次。即(time - count)是剩余的时间。
                int remain = time - count;
                //将剩余的描述显示在label3RemainTimeCount控件中。
                label3RemainTimeCount.Text = remain.ToString() + " 秒";
                //设置进度条进度
                progressBar1Time.Value = count;
                //count == time则时间到
                if (count == time)
                {
                    //停止计时
                    timer1.Stop();
                    //设置提示音
                    System.Media.SystemSounds.Asterisk.Play();
                    //弹出提示框
                    MessageBox.Show("时间到!", "提示");
                }
            }
        }
    }
    
    

    4.停止计数
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Timer
    {
        public partial class FormTimerTest : Form
        {
            //存储设定的定时值
            int time = 0;
            //用于定时器计数
            int count = 0;
    
    
            public FormTimerTest()
            {
                InitializeComponent();
            }
    
            //开始计时按钮函数
            private void button1Start_Click(object sender, EventArgs e)
            {
                //如果按钮显示“开始计时”
                if (button1Start.Text == "开始计时")
                {
                    //防止下拉框没有设置默认值,造成的程序崩溃
                    if (comboBox1Count.Text == "" && count == 0)
                    { 
                        MessageBox.Show("请选择时间!","提示!");
                    }
                    else
                    {
                        //将下拉框数添加至一个变量中
                        string str = comboBox1Count.Text;
                        //获取str中的子字符串,占两个字节,从0号位置开始。注意此汉字占一个字节。
                        string data = str.Substring(0, 2);
                        //将字符串转换为十六位带符号整形,得到设定的整形定时值。
                        time = Convert.ToInt16(data);
                        //设置进度条最大值
                        progressBar1Time.Maximum = time;
                        //开始计时
                        timer1.Start();
                        //计时完成后显示“停止计时”
                        button1Start.Text = "停止计时";
                    }
                }
                //如果按钮显示“停止计时”
                else if (button1Start.Text == "停止计时")
                {
                    //停止计时
                    timer1.Stop();
                    //进度条为当前值
                    progressBar1Time.Value = count;
                    //停止计时后下一步能进行的就是继续计时,或者重新运行程序开始计时。
                    button1Start.Text = "继续计时";
                }
                //如果按钮显示“继续计时”
                else if (button1Start.Text == "继续计时")
                {
                    //开始计时
                    timer1.Start();
                    //继续计时后下一步能进行的就是停止计时。
                    button1Start.Text = "停止计时";
                }
                
            }
    
            //窗体函数
            private void FormTimerTest_Load(object sender, EventArgs e)
            {
                //下拉框计数范围
                for (int i = 1; i < 100; i++)
                {
                    //初始化下拉框,数字后加一个空格是为了更容易获取字符
                    //每一个变量都属于一个对象,i.ToString()获取字符串。
                    comboBox1Count.Items.Add(i.ToString() + " 秒");
                }
                //默认下拉框显示为“1 秒”
                //comboBox1Count.Text = "0 秒";
            }
    
            //定时器函数
            private void timer1_Tick(object sender, EventArgs e)
            {
    
                //记录当前秒数。初始化是1000ms
                count++;
                //获取剩余的秒数,time是设置的定时值,count是系统每经过1秒,则加一次。即(time - count)是剩余的时间。
                int remain = time - count;
                //将剩余的描述显示在label3RemainTimeCount控件中。
                label3RemainTimeCount.Text = remain.ToString() + " 秒";
                //设置进度条进度
                progressBar1Time.Value = count;
                //count == time则时间到
                if (count == time)
                {
                    //停止计时
                    timer1.Stop();
    
                    //执行完程序后,恢复最初状态
                    //停止计时后,将进度条的值初始化0
                    progressBar1Time.Value = 0;
                    //定时数也设置为0
                    count = 0;
                    //开始计时
                    button1Start.Text = "开始计时";
    
                    //设置提示音
                    System.Media.SystemSounds.Asterisk.Play();
                    //弹出提示框
                    MessageBox.Show("时间到!", "提示");
                }
            }
        }
    }
    
    

    5.运行后结果
    在这里插入图片描述
    在这里插入图片描述
    往期链接:
    c# 上位机(VS2013新建一个例程).

    展开全文
  • C#上位机(串口工具)

    千次阅读 2022-03-16 13:35:37
    1.窗体设计 注意: 1.上述窗体用到了按钮、Radio、Panel、GroupBox、TextBox、SerialPorts、ComboBox等控件,组件。 2.对于Panel、GroupBox控件,需要先插入。再插入其他控件。其中Panel一般是为了将Radio进行组合...

    1.窗体设计
    在这里插入图片描述

    注意:
    1.上述窗体用到了按钮、Radio、Panel、GroupBox、TextBox、SerialPorts、ComboBox等控件,组件。
    2.对于Panel、GroupBox控件,需要先插入。再插入其他控件。其中Panel一般是为了将Radio进行组合而使用。GroupBox是为了更明显的显示界面给用户。
    3.其中TextBox一般只能横向拉伸,不能纵向拉伸,选择TsxtBox框上的黑色三角符号,然后勾选“MultiLine”之后,即可进行上下左右拉伸。其中为了让其出现滚动条可以在属性中选择“ScrollBars”。
    在这里插入图片描述在这里插入图片描述

    2.窗体函数事件
    2.1 窗体函数中直接进行初始化和设置

    //窗体事件
    private void Form1_Load(object sender, EventArgs e)
    {
    	//对端口进行设置
    	for (int i = 1; i < 20; i++)
    	{
    		comboBox1.Items.Add("COM"+ i.ToString());
    	}
    	//对串口号、波特率进行默认值设置
    	comboBox1.Text = "COM1";
    	comboBox2.Text = "4800";
    	radioButton1.Checked = true;   //函数中选择发送模式 为“数值”发送模式。 radioButton1为单选按钮属性(name)名字
    	radioButton3.Checked = true;   //函数中选择接收模式 为“数值”接收模式。 radioButton3为单选按钮属性(name)名字
    	button1.Text = "打开串口";     //确保 “打开串口”按键文本属性为 “打开串口”
    	button2.Text = "关闭串口";     //确保 “关闭串口”按键文本属性为 “关闭串口”
    }
    

    在这里插入图片描述

    主要是进行窗体初始化设置,下拉框设置,选择发送模式 和接收模式设置为“数值”模式。

    2.2 在窗体函数中,只进行初始化,其他工作封装在一个函数中。

    //窗体事件
    private void Form1_Load(object sender, EventArgs e)
    {
    	Updata_Serialport_Name(comboBox1);  //调用更新可用串口函数,comboBox1为 端口 组合框名字
    	
    	/*//对端口进行设置
    	for (int i = 1; i < 20; i++)
    	{
    		comboBox1.Items.Add("COM"+ i.ToString());
    	}*/
    	//对串口号、波特率进行默认值设置
    	comboBox1.Text = "COM1";
    	comboBox2.Text = "4800";
    	radioButton1.Checked = true;   //函数中选择发送模式 为“数值”发送模式。 radioButton1为单选按钮属性(name)名字
    	radioButton3.Checked = true;   //函数中选择接收模式 为“数值”接收模式。 radioButton3为单选按钮属性(name)名字
    	button1.Text = "打开串口";     //确保 “打开串口”按键文本属性为 “打开串口”
    	button2.Text = "关闭串口";     //确保 “关闭串口”按键文本属性为 “关闭串口”
    
    	//必须手动添加处理串口数据接收
    	//serialPort1.DataReceived += new  EventHandler(this.Port_DataReceived);//SerialDataReceived 
    }
    /*用户自定义更新可用串口函数*/
    private void Updata_Serialport_Name(ComboBox MycomboBox)
    {
    	//System.IO.Ports.SerialPort.GetPortNames()函数功能为获取计算机所有可用串口,以字符串数组形式输出
    	string[] ArryPort = System.IO.Ports.SerialPort.GetPortNames(); //定义字符串数组,数组名为 ArryPort,将可用的串口信息存放在字符串中
    	MycomboBox.Items.Clear();       //清除当前组合框下拉菜单内容                  
    	for (int i = 0; i < ArryPort.Length; i++)
    	{
    		MycomboBox.Items.Add(ArryPort[i]);   //将所有的可用串口号添加到端口对应的组合框中
    	}
    }
    

    注意:
    1.System.IO.Ports.SerialPort.GetPortNames()函数功能为获取计算机所有可用串口,以字符串数组形式输出。可简写为SerialPort.GetPortNames()。但要加using System.IO.Ports;命名空间
    2.MycomboBox.Items.Add()在MycomboBox控件下添加下拉信息。
    3.Updata_Serialport_Name()该函数类似于串口扫描函数。

    在这里插入图片描述
    3.串口数据信息接收,字符和数值两种模式进行处理

    //串口数据信息接收
    private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)//SerialDataReceived 
    {
    //接收方式为字符模式,字符方式读
    //Checked:获取或设置一个值,该值指示是否已选中控件。
    if (!radioButton3.Checked)
    {
    	//字符串方式读缓冲区中的数据
    	string str = serialPort1.ReadExisting();
    	//把读取的数据添加至接收区。AppendText():向文本框的当前文本追加文本。
    	textBox2.AppendText(str);
    }
    //接收方式为数值模式,数值方式读
    else
    {
    	byte data;
    	//ReadByte()从 System.IO.Ports.SerialPort 输入缓冲区中同步读取一个字节。返回:强制转换为 System.Int32 的字节;或者,如果已读取到流的末尾,则为 -1。
    	//因为函数ReadByte()的返回值为int,因此要转换强制转换为byte。
    	data = (byte)serialPort1.ReadByte();
    	//Convert.ToString() 将 8 位无符号整数的值转换为其等效的指定基数的字符串表示形式。
    	// 参数: 
    	// value:要转换的 8 位无符号整数。
    	// toBase:返回值的基数,必须是 2、8、10 或 16。
    	// 返回结果: 以 toBase 为基数的 value 的字符串表示形式。
    	//转换为大写十六进制字符串
    	string str = Convert.ToString(data, 16).ToUpper();
    	//对单个值,进行补0
    	textBox2.AppendText("0x" + ((str.Length == 1) ? "0" + str : str));
    	/*
    	if (str.Length == 1)
    	{
    		str = "0" + str;
    	}
    	else
    	{
    		str = str;
    	}
    	textBox2.AppendText("0x" + str);
    	 */
    }
    

    注意:
    1.Checked:获取或设置一个值,该值指示是否已选中控件。
    2.AppendText():向文本框的当前文本追加文本。
    3.ReadByte()从 System.IO.Ports.SerialPort 输入缓冲区中同步读取一个字节。返回:强制转换为 System.Int32 的字节;或者,如果已读取到流的末尾,则为 -1。
    4.Convert.ToString() 将 8 位无符号整数的值转换为其等效的指定基数的字符串表示形式。
    参数:
    4.1 value:要转换的 8 位无符号整数。
    4.2 toBase:返回值的基数,必须是 2、8、10 或 16。
    返回结果:
    以 toBase 为基数的 value 的字符串表示形式。
    在这里插入图片描述

    4.打开按钮

    private void button1_Click(object sender, EventArgs e)
    {
    	try
    	{
    		//在打开串口之前获取串口号和波特率
    		serialPort1.PortName = comboBox1.Text;
    		//转换为10进制,10可省略
    		serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text,10);
    		//打开串口
    		serialPort1.Open();
    		//打开串口按钮不可用,变成灰色
    		button1.Enabled = false;
    		//关闭串口按钮可用。
    		button2.Enabled = true;
    	}
    	catch
    	{ 
    		MessageBox.Show("端口错误,请检查串口","打开串口错误");
    	}
       
    }
    

    打开按钮后,打开按钮图标变灰色,不可用。关闭按钮图标可用。

    在这里插入图片描述

    5.关闭按钮

    private void button2_Click(object sender, EventArgs e)
    {
    	try
    	{
    		//关闭串口
    		serialPort1.Close();
    		//打开串口按钮可用
    		button1.Enabled = true;
    		//关闭串口按钮不可用,变成灰色
    		button2.Enabled = false;
    	}
    	catch
    	{
    		//一般关闭串口不出错,此处对程序不进行处理
    	}
    }
    

    关闭按钮后,关闭按钮图标变灰色,不可用。打开按钮图标可用。
    在这里插入图片描述

    6.发送按钮,实现串口的发送功能,从字符和数值两个模式进行撰写。

    private void button3_Click(object sender, EventArgs e)
    {
    	byte[] data = new byte[1];
    	// IsOpen :获取一个值,该值指示 System.IO.Ports.SerialPort 对象的打开或关闭状态。
    	// 返回结果: 如果串行端口已打开,则为 true;否则为 false。 默认值为 false。
    	if (serialPort1.IsOpen)//串口打开
    	{ 
    		//发送框不能为空
    		if (textBox1.Text != "")
    		{ 
    			//发送模式为字符模式
    			if (!radioButton1.Checked)
    			{
    				try
    				{
    					//将发送的数据存在于缓冲区
    					serialPort1.WriteLine(textBox1.Text);
    				}
    				catch(Exception err)
    				{
    					MessageBox.Show("串口数据写入错误", "发送错误");
    				}
    			}
    			//发送模式为数值模式
    			else
    			{
    				try
    				{
    					//文本数据长度
    					int dataLength = textBox1.Text.Length;
    					//判断本本个数是奇数还是偶数
    					int dataRemain = textBox1.Text.Length % 2;
    					//(dataLength - dataRemain)/2 十六进制发送时,看有几个字节。
    
    					//处理前length-1个数据
    					for (int i = 0; i < (dataLength - dataRemain)/2; i++)
    					{
    						// Substring(): 
    						// 从此实例检索子字符串。 子字符串从指定的字符位置开始且具有指定的长度。
    						// 参数: 
    						//   startIndex:
    						//     此实例中子字符串的起始字符位置(从零开始)。
    						//   length:
    						//     子字符串中的字符数。
    						// 返回结果: 
    						//     与此实例中在 startIndex 处开头、长度为 length 的子字符串等效的一个字符串,如果 startIndex 等于此实例的长度且 length
    						//     为零,则为 System.String.Empty。
    						data[0] = Convert.ToByte(textBox1.Text.Substring(i*2,2),16);//将获取的数值转换为十六进制每两位两位存入data[0]这个字节中
    
    						//Convert.ToByte(): 
    						//将指定基数的数字的字符串表示形式转换为等效的 8 位无符号整数。
    						// 参数: 
    						//   value:
    						//     包含要转换的数字的字符串。
    						//   fromBase:
    						//     value 中数字的基数,它必须是 2、8、10 或 16。
    						// 返回结果: 
    						//     与 value 中数字等效的 8 位无符号整数,如果 value 为 null,则为 0(零)。
    
    						serialPort1.Write(data, 0, 1);//循环发送每一个字节,如abc则发0xab
    
    						// Write(data, 0, 1): 
    						// 使用缓冲区的数据将指定数量的字节写入串行端口。
    						// 参数: 
    						//   buffer:
    						//     包含要写入端口的数据的字节数组。
    						//   offset:
    						//     buffer 参数中从零开始的字节偏移量,从此处开始将字节复制到端口。
    						//   count:
    						//     要写入的字节数。
    
    					}
    
    					//处理奇数个数据的最后一位
    					if(textBox1.Text.Length % 2 != 0)
    					{   
    						//将最后一位转换为十六进制数据存入data中。
    						data[0] = Convert.ToByte(textBox1.Text.Substring(textBox1.Text.Length-1, 1),16);
    						//发送最后一位
    						serialPort1.Write(data, 0, 1);
    					}
    				}
    				catch (Exception err)
    				{
    					MessageBox.Show("发送数据错误", "发送错误");
    				}
    			}
    
    		}
    	}
    
    }
    

    注意:

    1. Substring():
      从此实例检索子字符串。 子字符串从指定的字符位置开始且具有指定的长度。
      参数:
      startIndex:此实例中子字符串的起始字符位置(从零开始)。
      length:子字符串中的字符数。
      返回结果:
      与此实例中在 startIndex 处开头、长度为 length 的子字符串等效的一个字符串,如果 startIndex 等于此实例的长度且 length为零,则为 System.String.Empty。

    2.Convert.ToByte():
    将指定基数的数字的字符串表示形式转换为等效的 8 位无符号整数。
    参数:
    value:包含要转换的数字的字符串。
    fromBase:value 中数字的基数,它必须是 2、8、10 或 16。
    返回结果:
    与 value 中数字等效的 8 位无符号整数,如果 value 为 null,则为 0(零)。

    3.Write(data, 0, 1):
    使用缓冲区的数据将指定数量的字节写入串行端口。
    参数:
    buffer:包含要写入端口的数据的字节数组。
    offset:buffer 参数中从零开始的字节偏移量,从此处开始将字节复制到端口。
    count:要写入的字节数。

    4.IsOpen :
    获取一个值,该值指示 System.IO.Ports.SerialPort 对象的打开或关闭状态。
    返回结果:
    如果串行端口已打开,则为 true;否则为 false。 默认值为 false。
    在这里插入图片描述在这里插入图片描述
    7.文本框,将滚动条调整至当前位置

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
    	//将滚动条调整至当前位置。
    	textBox1.ScrollToCaret();
    }
    
    private void textBox2_TextChanged(object sender, EventArgs e)
    {
    	textBox2.ScrollToCaret();
    }
    

    8.清空接收文本

    private void button4_Click(object sender, EventArgs e)
    {
         textBox2.Text = "";
    }
    

    9.运行结果
    在这里插入图片描述
    往期链接:

    1.C#上位机(简单实现串口发送).
    2.C#上位机(定时器计数).

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,803
精华内容 3,121
关键字:

c#上位机