1、上位机与下位机
上位机相当于一个软件系统,可以用于接收数据、控制数据。即可以对接收到的数据直接发送操控命令来操作数据。上位机可以接收下位机的信号。下位机是一个控制器,是直接控制设备获取设备状况的计算机。上位机发出的命令首先给下位机,下位机再根据此命令解释成相应时序信号直接控制相应设备。下位机不时读取设备状态数据(一般为模拟量),转换成数字信号反馈给上位机。上位机不可以单独使用,而下位机可以单独使用。

2、串口通信
串口相当于硬件类型的接口。比如无线传感节点发送信号到汇聚节点,汇聚节点通过串口将数据传到计算机中的上位机中,上位机接收信息,并处理。

  串口是按位(bit)发送和接收字节。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。a,波特率:这是一个衡量符号传输速率的参数。b,数据位:这是衡量通信中实际数据位的参数。c,停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。d,奇偶校验位:在串口通信中一种简单的检错方式。

3、C#代码

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;
using System.IO.Ports;
using System.Diagnostics;
namespace serial2
{public partial class Form1 : Form{SerialPort s = new SerialPort();    //实例化一个串口对象,在前端控件中可以直接拖过来,但最好是在后端代码中写代码,这样复制到其他地方不会出错。s是一个串口的句柄public Form1(){InitializeComponent();Control.CheckForIllegalCrossThreadCalls = false;   //防止跨线程访问出错,好多地方会用到button1.Text = "打开串口";int[] item = { 9600,115200};    //定义一个Item数组,遍历item中每一个变量a,增加到comboBox2的列表中foreach (int a in item){comboBox2.Items.Add(a.ToString());}comboBox2.SelectedItem = comboBox2.Items[1];    //默认为列表第二个变量}private void Form1_Load(object sender, EventArgs e)   //窗体事件要先配置端口信息。{string[] ports = SerialPort.GetPortNames();comboBox1.Items.AddRange(ports);comboBox1.SelectedItem=comboBox1.Items[0];//Array.Sort(ports);}private void button1_Click(object sender, EventArgs e)   //下面讲解中差不多已经讲清楚了{try{if (!s.IsOpen){s.PortName = comboBox1.SelectedItem.ToString();s.BaudRate = Convert.ToInt32(comboBox2.SelectedItem.ToString());s.Open();s.DataReceived += s_DataReceived;button1.Text = "关闭串口";//MessageBox.Show("串口已打开");}else{s.Close();s.DataReceived -= s_DataReceived;button1.Text = "打开串口";}}catch (Exception ee){MessageBox.Show(ee.ToString());}}void s_DataReceived(object sender, SerialDataReceivedEventArgs e)   //数据接收事件,读到数据的长度赋值给count,如果是8位(节点内部编程规定好的),就申请一个byte类型的buff数组,s句柄来读数据{int count =s.BytesToRead;    string str=null ;if (count == 8){byte[] buff = new byte[count];s.Read(buff, 0, count);foreach (byte item in buff)    //读取Buff中存的数据,转换成显示的十六进制数{str += item.ToString("X2")+" ";}richTextBox1.Text =System.DateTime.Now.ToString()+": "+ str + "\n" + richTextBox1.Text;      //这是跨线程访问richtextbox,原程序和DataReceived事件是两个不同的线程同时在执行if (buff[0] == 0x04)   //如果节点是04发来的数据{ID.Text = buff[0].ToString();   //这下面是上位机右边那一段,用来显示处理好的数据的温度、湿度、光照、灰尘、ID信息的。buff【0】中存的是数据的ID信息,显示在ID的Label上面switch (buff[2])   //判断数据类型  buff【0】和buff【1】代表ID的低位和高位,同理2和3代表数据类型的低位和高位,当2和3的值为1时,4和5代表温度,6和7代表湿度;{  case 0x01:       //当2和3的值为1,4和5是温度,6和7是湿度{Tem.Text = (buff[5] * 4 + buff[4] * 0.05 - 30).ToString();Hum.Text = (buff[6]  + buff[7]).ToString();break;}case 0x02://6和7是光照{Light.Text = (buff[6] + buff[7]).ToString();break;}case 0x04://6和7是灰尘{Dust.Text = (buff[6] + buff[7]).ToString();break;}default:break;}}}}private void button3_Click(object sender, EventArgs e)   //每次发一个字节{string[] sendbuff = richTextBox2.Text.Split();  //分割输入的字符串,判断有多少个字节需要发送Debug.WriteLine("发送字节数:"+sendbuff.Length);foreach (string  item in sendbuff){int count = 1;byte[] buff = new byte[count];buff[0] = byte.Parse(item, System.Globalization.NumberStyles.HexNumber);//格式化字符串为十六进制数值s.Write(buff, 0, count);}}private void button2_Click(object sender, EventArgs e)//刷新右边的数值{int count = 1;byte[] buff = new byte[count];buff[0] = byte.Parse("04", System.Globalization.NumberStyles.HexNumber);//这里只显示04节点的信息s.Write(buff, 0, count);}}
}

(以上规则均是本实验室节点内部自定义规则,测试的,外面的相应要改)

4、结果

5、补充四点知识
1)在程序可能会遇到错误的地方,用try+两个Tab键,将代码写入try中。比如本例子中的代码:

private void button1_Click(object sender, EventArgs e){try{if (!s.IsOpen){s.PortName = comboBox1.SelectedItem.ToString();s.BaudRate = Convert.ToInt32(comboBox2.SelectedItem.ToString());s.Open();s.DataReceived += s_DataReceived;button1.Text = "关闭串口";//MessageBox.Show("串口已打开");}else{s.Close();s.DataReceived -= s_DataReceived;button1.Text = "打开串口";}}catch (Exception ee){MessageBox.Show(ee.ToString());}}

如果代码没有写入try中,则可能出现的一种情况是比如有两个上位机,同时占用同一个串口,则就会冲突,会出错。程序就会终止,整个进程结束。而如果写入try中,并且把抛出异常的catch代码实例化,即捕获异常要实例化一个句柄,这样程序遇到error就不会终止,而会出现报错的原因。如下图,我的这个上位机和网上下载的一个上位机同时占用COM3串口(网上下载的先占用COM3),这时我的上位机在打开串口时会出现报错。

2)就我这个上位机而言,需要有打开串口和关闭串口两个button按钮,但是考虑到占地方,当然最重要的还是如果用两个按钮来表示,当你按下打开串口,如果忘了是否打开,则是看不出来是不是打开的,所以可以合并为一个button控件。(代码还是用上面那一段的代码)。(感觉很神奇啊)。在button1_Click事件中,先点击button,如果串口是关闭的,则打开串口,然后把button1.Text的值赋值为“关闭串口”,如果串口本来是关闭的,则点击按钮会把button1.Text的值赋值为“打开串口”,同时把接收的数据清空。感觉这个方法真的很不错!嘿嘿

3)当输入一个变量或方法什么的,它所有有的会自动出现在一个列表,这时,“正方体”代表“方法”,“小钳子”代表“变量”,“闪电”代表“事件”。

4) 产生对象的事件时

比如输入s.自动会出现DataReceived事件,再输入“+=”就会有如上图提示,按Tab键。然后又会如下图提示

再次按tab键,就会自动生成DataReceived事件处理函数。

C#做一个简单的串口收发上位机相关推荐

  1. C#做一个简单的进行串口通信的上位机

    C#做一个简单的进行串口通信的上位机 乱世中的单纯 发布于 1年前,共有 10 条评论 1.上位机与下位机 上位机相当于一个软件系统,可以用于接收数据.控制数据.即可以对接收到的数据直接发送操控命令来 ...

  2. Visual Studio 2019 C# 上位机入门(2):写一个简单的串口助手

    前言 本文记录一下用Visual Studio 2019 C# 写一个简单的串口助手的过程,由于没有先从小处学习,而是直接找相关资料就开始做,免不了很多奇怪的问题花了一些时间,基于此情况,我将尽可能整 ...

  3. 做一个简单的“远程”开关 ESP8266 + APP

    简单的远程开关制作(纯代码.无解析版.UDP通信) 引言 本篇文章,我们将做一个超级简单的开关,当你学会该操作后,就可以自己进行一些简单的添加.修改从而实现一些自定义的功能.你可以做一个简单的远程开关 ...

  4. 动手做一个简单的智能小车

    动手做一个简单的智能小车 来到CNDN一年了,看到了许多大佬的杰出作品.也该写点什么来回馈给大家了前不久接触了单片机,想提前进行实践一下所以有想法做一个实体出来,想来想去难的怕自己搞不定,但是还好找到 ...

  5. 用RC522与arduino做一个简单的门禁系统

    用RC522与arduino做一个简单的门禁系统 插本成功要去新学校了,结果发现新学校宿舍没有电梯没有电子门(虽然海景房很香).这对于住惯养老院的我属实难受所所以打算自己也整一个IC卡的门禁系统.然后 ...

  6. C#编写一个串口助手上位机软件

    对于工程师来说,串口助手可以说是必不可少的一个工具,一个好的串口助手可以大大方便我们的研发调试.网上串口助手很多,如果能够根据自己需要做一个合适的串口助手,那么既能方便自己,也能掌握上位机的开发,对于 ...

  7. pygame做一个简单的打字游戏

    pygame做一个简单的打字游戏 1.基本代码 下面的代码完成了每一秒在界面的顶部随机生成一个新的字母 # -*- coding=utf-8 -*- import pygame from pygame ...

  8. 第四章 .net core做一个简单的登录

    项目目标部署环境:CentOS 7+ 项目技术点:.netcore2.0 + Autofac +webAPI + NHibernate5.1 + mysql5.6 + nginx 开源地址:https ...

  9. clistctrl控件最后插入在后面_用图表控件做一个简单的员工信息查询系统

    前几天在上课的时候有同学说在做人员的信息查询的时候,经常的要去做查找搜索很麻烦,能不能做一个简单的人员信息查询系统,只需要选择人员的编号就可以查询到这个员工的信息.其实要实现这个同学的需求在EXCEL ...

最新文章

  1. asp.net mvc 4 AntiForgery 提供的防伪标记适用于用户“”,但当前用户为“XX” 问题处理记录...
  2. [Swift]LeetCode388. 文件的最长绝对路径 | Longest Absolute File Path
  3. 【django】路由传递参数
  4. docker安装配置分布式elasticsearch、kibana、head、cerebro
  5. PostgreSQL数据库、表空间、角色及用户
  6. 个人永久性免费-Excel催化剂功能第26波-正确的Excel密码管理之道
  7. python输出50-150之间不能被5整除的整数代码解读
  8. 【软件分析与挖掘】Vision of Software Clone Management: Past, Present, and Future (Keynote Paper)...
  9. 颓废了1年+,今天开始勤(tui)奋(fei)啦
  10. C/C++与Fortan混编
  11. TS文件合并,这里提供了一点小思路。
  12. 用户流失数据分析报告
  13. 电脑罗盘时钟html怎么设置成桌面,抖音网红款Word Clock罗盘时钟电脑桌面屏保设置教程-完整版...
  14. 我二刷以上的网文小说,本本经典,值得推荐
  15. 量化交易——PEG策略
  16. RAID控制器是什么?
  17. 马哥教育42期第四周作业
  18. Esp8266 -- 心知天气get请求及url讲解说明
  19. Django 上传图片存储到数据库中
  20. Udacity数据分析(进阶)-Prosper 贷款数据分析

热门文章

  1. python复利计算_使用Python函数计算复利
  2. 黑马毕向东Java课程笔记(day16-1-16-9):集合类(集合框架)——Map集合
  3. Response响应字符流和字节流数据
  4. Cell index must be >= 0
  5. adjacent angle_【数学几何的英语用语包括图形的名称.】作业帮
  6. 上海迪士尼乐拍通disney相片免费下载,含香港迪士尼处处拍相片下载
  7. C++ 库函数<string>示例
  8. 支撑百万并发的“零拷贝”技术,你了解吗?
  9. 入门java游戏——飞翔小鸟
  10. python中array是什么意思_Python库Numpy里ndarray.ndim 是什么意思?