文档章节

串口通讯学习

o
 osc_kz2s8mnr
发布于 07/02 09:01
字数 1532
阅读 18
收藏 0

行业解决方案、产品招募中!想赚钱就来传!>>>

//前提需要

//需要一个 serialPort 工具 可在vs自带的工具栏中获得

//源代码加串口工具地址:

//链接:https://pan.baidu.com/s/1YbfvdXEmfsJX87D-Jxljyg   提取码:d32x

 

//记录用户打开的串口号 可改为泛型模式

string serialPortName;

//一般电脑是没有串口号的,所以要用个软件创建虚拟串口号

//软件名 - Configure Virtual Serial Port Driver

 

波特率设置的值为 1382400,921600,460800,256000,230400,128000,115200,76800,57600,

43000,38400,19200,14400,9600,4800,1200

停止位设置的值为:1,1.5,2

数据位设置的值为:8,7,6,5

校验位设置的值为:无,奇校验,偶校验

 

步骤:

1.设置串口的基本数据 (串口号,波特率,数据位,停止位,校验位)

2.使用Open打开串口

3.使用串口工具的DataReceived()事件进行数据的接收

4.创建发送数据 Write() ,一般发送的是byte数组

5.使用Close关闭串口

 

界面:

 

 

 

//一

//在窗口Load事件中,设置串口基本数据的默认值

//1.拿到电脑上可以使用的串口号,并赋值给窗口的串口下拉列表中,默认选项索引为0

string[] prots = System.IO.Ports.SerialPort.GetPortNames();

this.cbPort.Items.AddRange(prots);

this.cbPort.SelectedIndex = this.cbPort.Items.Count > 0 ? 0 : -1;

//2.设置波特率,停止位,数据位,校验位的默认值。

this.cbBaud.Text = "115200";

this.cbStopBit.Text = "1";

this.cbDataBit.Text = "8";

this.cbComparable.Text = "无";

 

 

//二

//设置打开串口和关闭串口按钮的单击事件

//为串口拿到基本数据

serialPort .PortName = this.cbPort.Text;//串口号

serialPortName = this.cbPort.Text;//记录用户打开的串口号

 

serialPort.BaudRate = int.Parse(this.cbBaud.Text);//波特率

serialPort.DataBits = int.Parse(this.cbDataBit.Text);//数据位

//设置停止位

if (this.cbStopBit.Text == "1") { serialPort.StopBits = StopBits.One; }

else if (this.cbStopBit.Text == "1.5") { serialPort.StopBits = StopBits.OnePointFive; }

else if (this.cbStopBit.Text == "2") { serialPort.StopBits = StopBits.Two; }

//设置奇偶校验

if (this.cbComparable.Text == "无") { serialPort.Parity = Parity.None; }

else if (this.cbComparable.Text == "奇校验") { serialPort.Parity = Parity.Odd; }

else if (this.cbComparable.Text == "偶校验") { serialPort.Parity = Parity.Even; }

 

//打开串口 只需要使用Open打开串口

serialPort1.Open();

 

this.btnOpenStat.Text = "关闭串口";

 

//如果按钮的Text为 关闭串口的话

serialPort.Close();//Close() - 关闭串口

 

 

//三 本次串口的简单数据协议 1 - 字符串 bp - 医疗数据 2 - 文件

//通过串口工具自带的DataReceived事件进行串口的数据接收

//这次的是自己定义的数据协议,一般都是用公司默认的协议 或者RS232和RS485

//获取可以读取的字节数 默认最大值是4096 如果想要更改可以直接改变串口的ReadBufferSize属性

int len = serialPort.BytesToRead;

if(len == serialPort.ReadBufferSize){

MessageBox.Show("程序最多只能接受"+serialPort1.ReadBufferSize+"字节的数据!","提示");

return;

}

//拿到数据,Read()

byte[] buff = new byte[len];

serialPort.Read(buff,0,len);

//如果选中了显示时间就赋值,没有就算

string DateNow = string.Empty;

//根据协议进行判断

if(buff[0]==1){

//拿出原来的数据并去除协议部分 然后放入另一个byte[]数组中

byte[] result = new byte[len];

Buffer.BlockCopy(buff,1,result,0,buff.Length-1);

//将byte数组保存可读string 根据自己的编码格式进行转码

string str = Encoding.Default.GetString(result);

//将数据分割为string[] 判断是否为医疗数据

string[] strPle = str.Split(',');

if(strPle[0]=="bp"){

//放入方法中,重新拼装成可用数据

str = RecHBpData(strPle);

}

//由于我们的接收数据的事件是在一个子线程里面的,

//所以需要Invoke才能给我们主线程创建的控件赋值

//当然你也可以使用InvokeRequired()来判断是否为主线程创建的控件,我这里就没使用了

Invoke(new Action(() => {

//是否显示时间

if(this.ckDateTime.Checked){

DateNow = "\r\n" + DateTime.Now.ToString();

}

//是否为16进制显示

if(this.checkBox1.Checked){

this.txtMsg.AppendText(DateNow + "\r\n" + byteToHexStr(buff));

}

//默认是使用字符串显示

else{

this.txtMsg.AppendText(DateNow + "\r\n" + str);

}

 

})));

}

//如果传送的文件的话

else if(buff[0]==2){

ProcessRecieveFile(buff);

}

 

//一般呢,这些方法是放在一个方法类库里面,但是我懒得放就在一个类里面了

#region 封装的方法

 

/// <summary>

/// 传输的是文件就进行文件的操作

/// </summary>

/// <param name="data">数据流</param>

public void ProcessRecieveFile(byte[] data)

{

using (SaveFileDialog dialog = new SaveFileDialog())

{

dialog.DefaultExt = "txt";

dialog.Filter = "文本文件(*.txt)|*.txt|所有文件(*.*)|*.*";

//由于大部分可能不是主线程,所以我们要加this,不然不会弹出保存框

if (dialog.ShowDialog(this) != DialogResult.OK)

{

return;

}

byte[] result = new byte[data.Length - 1];

Buffer.BlockCopy(data, 1, result, 0, data.Length - 1);

File.WriteAllBytes(dialog.FileName, result);

}

}

 

#region 封装 数据定义的协议

 

public static string RecHBpData(string[] strPle)

{

string str = string.Empty;

 

//判断仪器

str += $"{StaticConstant.DicMedicalnoun[strPle[1]]} ";

 

//增加时间

str += " " + strPle[2] + " " + strPle[3] + "\r\n";

//增加具体数据

str += $"{StaticConstant.DicMedicalnoun[strPle[4]]}: {strPle[5].TrimStart('0')} \r\n{StaticConstant.DicMedicalnoun[strPle[6]]}: {strPle[7].TrimStart('0')}";

 

 

 

 

 

return str;

}

 

 

#endregion

 

 

/// <summary>

/// 字节数组转16进制字符串

/// </summary>

/// <param name="bytes">byte数组</param>

/// <returns>16进制显示形式</returns>

public static string byteToHexStr(byte[] bytes)

{

string retuenStr = "";

try

{

if (bytes != null)

{

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

{

retuenStr += bytes[i].ToString("X2") + " ";//变成16进制,两个中间用空格隔开

}

}

return retuenStr;

}

catch (Exception ex)

{

return retuenStr;

}

}

 

/// <summary>

/// 字符串转16进制格式,不够自动前面补0

/// </summary>

/// <param name="hexString"></param>

/// <returns></returns>

public static byte[] strToHexByte(string hexString)

{

int i;

if ((hexString.Length % 2) != 0)

{//奇数个

byte[] returnBytes = new byte[(hexString.Length + 1) / 2];

try

{

for (i = 0; i < hexString.Length - 1; i++)

{

returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);

i = i * 2;

}

returnBytes[returnBytes.Length - 1] = Convert.ToByte(hexString.Substring(hexString.Length - 1, 1).PadLeft(2, '0'), 16);

}

catch (Exception)

{

MessageBox.Show("含有非16进制字符", "提示");

return null;

}

return returnBytes;

}

else

{

byte[] returnBytes = new byte[(hexString.Length) / 2];

try

{

for (i = 0; i < hexString.Length; i++)

{

returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);

}

}

catch (Exception)

{

MessageBox.Show("含有非16进制字符", "提示");

return null;

}

return returnBytes;

}

}

 

#endregion

 

 

//我的医疗数据的封装是放在配置文件中,一般我们都是放在数据库中,不过我就做个小学习工具就 //没做到数据库里面了

 

//四 发送数据

//发送数据,我这边分为发送文件和发送字符串

//1.发送字符串

string str = this.txtSendMsg.Text.Trim().Tostring();

try{

if(str.Length > 0){

//16进制发送

if(this.ckSend.Checked){

byte[] byt = strToHexBytes(str);

byte[] result = new byte[byt.Length+1];

//加上数据协议

result[0] = 1;

//数据转移

Buffer.BlockCopy(byt,0,result,1,byt.Lengt);

//发送数据,byte形式发送

serialPort.Write(result,0,result.Length);

}

//默认字符串发送

else{

//根据自己的编码格式编码

byte[] dataByte = Encoding.Default.GetBytes(str);

byte[] result = new byte[dataByte.Length + 1];

//加上数据协议

result[0] = 1;

Buffer.BlockCopy(dataByte ,0,result,1,dataByte .Lengt);

//发送数据,byte形式发送

serialPort.Write(result,0,result.Length);

}

}

}catch(Exception ex){}

 

//2.发送文件

try{

using(OpenFileDialog dialog = new OpenFileDialog()){

if(dialog.ShowDialog(this) != DialogResult.OK){

return;

}

byte[] data = File.ReadAllBytes(dialog.FileName);

byte[] result = new byte[data.Length + 1];

result[0] = 2;

Buffer.BlockCopy(data,0,result,1,data.Length);

serialPort.Write(result,0,result.Lenght);

}

}catch(Exception ex){

MessageBox.Show(ex.Message);

}

 

o
粉丝 0
博文 70
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
Nutch学习笔记4-Nutch 1.7 的 索引篇 ElasticSearch

上一篇讲解了爬取和分析的流程,很重要的收获就是: 解析过程中,会根据页面的ContentType获得一系列的注册解析器, 依次调用每个解析器,当其中一个解析成功后就返回,否则继续执行下一个解...

强子哥哥
2014/06/26
712
0
个人计算机操作系统--eComStation

eComStation(简写为 eCS)是一款基于OS/2,由Serenity Systems发布的个人计算机操作系统。它包含了一系列在OS/2的IBM版本中没有的组件及应用。 eComStation的最初版本v1发布于2001年,基于I...

匿名
2013/03/26
3.1K
0
高性能跨语言 RPC--Hprose

Hprose 是高性能远程对象服务引擎(High Performance Remote Object Service Engine)的缩写 —— 微服务首选引擎。 它是一个先进的轻量级的跨语言跨平台面向对象的高性能远程动态通讯中间件...

andot
2012/12/27
6.1W
28
商铺记账系统软件--bluebee蓝蜜蜂记账系统

此项目已废弃:) Donate捐助 bluebee accounting system is a popular and free accounting system for individual businesses.This system focus on the individual businesses operation......

刘学炜
2013/04/18
1.4W
10
Arduino 兼容开发板--Microduino

Microduino 是 Arduino 的兼容开发板。 Microduino 采用 U 型 27pin Microduino 接口规范,尺寸小巧,长25.4mm X 宽27.94mm,仅一枚1元人民币硬币的大小。轻量化的设计让Microduino在对尺寸、...

匿名
2013/05/14
8.1K
0

没有更多内容

加载失败,请刷新页面

加载更多

如何在Pandas的DataFrame中的行上进行迭代? - How to iterate over rows in a DataFrame in Pandas?

问题: I have a DataFrame from pandas: 我有一个来自熊猫的DataFrame : import pandas as pdinp = [{'c1':10, 'c2':100}, {'c1':11,'c2':110}, {'c1':12,'c2':120}]df = pd.DataFrame(......

富含淀粉
16分钟前
12
0
与电商节伴生,平台销量榜单背后还有被低估的营销价值

文 | 曾响铃 来源 | 科技向令说(xiangling0815) 时至今日,电商节已经成为各巨头零售平台例行的活动,花样在不断创新,玩法也在不断涌现。 在这个过程中,伴随电商节的各种品牌、产品销量榜...

曾响铃
17分钟前
14
0
volatile关键字详解

前言 提到JAVA的并发编程,就不得不提volatile关键字,不管是在面试还是实际开发中,volatile关键字的使用都是一个应该掌握的技能。它之所以重要,是因为它和JAVA并发编程中会遇到三种重要问...

ls_cherish
43分钟前
10
0
比继承更偏爱组成? - Prefer composition over inheritance?

问题: Why prefer composition over inheritance? 为什么更喜欢使用组合而不是继承? What trade-offs are there for each approach? 每种方法都有哪些取舍? When should you choose inher...

javail
46分钟前
17
0
2020软件测试工程师史上最全面试题(内含答案)-看完BATJ面试官对你竖起大拇指!

以下是软件测试相关的面试题及答案,欢迎大家参考! 我不是至尊宝,也不是孙悟空,我只是那城墙下的一猿。  1、你的测试职业发展是什么?  测试经验越多,测试能力越高。所以我的职业发展是需...

程序员一凡
50分钟前
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部