串口实现思路:
SerialPort类实现串口,作为类的成员,一直存在
加载窗体(构造方法)实现初始化控件
1.初始化串口号 可用SerialPort.GetPortNames获得 DataSource控件的数据源
2.波特率
3.数据位
4.校验位 可用枚举类型 Enum.GetNames 获取自带的校验位
5.停止位 可用枚举类型 Enum.GetNames 获取自带的校验位
打开串口功能:
定义一个串口是否打开的标志位字段
我们可用属性对字段进一步扩展,定义一个串口是否打开的属性
1.已打开串口 则:串口标志位为真,串口按钮文本改变,图片改变等
2.未打开串口 则:
点击打开串口按钮,我们可以先进行一些校验
判断串口是否打开
未打开串口则:
一.配置串口
1.配置串口号
2.配置波特率
3.配置数据位
4.配置校验位 字符串转枚举需要注意
5.配置停止位
二.打开串口
防止打开串口失败,我们可用用try承接一下,打开成功则标志位赋值为真,串口打开。 失败则抛出异常原因
已打开串口则:
关闭串口,标志位赋值为假
发送数据功能:
提示:发送数据前可以进行一些数据的校验,防止空数据或者错误数据的发送以及串口没有打开的状态
一、数据的16进制发送
例:"2010" 实际上我想发送的是值是3216 占2个字节
1.所以我首先要定义byte类型的数组,用来承接(16进制)转换后的字节数组
发送数据的校验:16进制只能发0-9A-Fa-f这些数 所以用到正则表达式Regex.IsMatch(txt_SendData.Text, "^[0-9A-Fa-f Xx]+$"); ^以什么开头 $以什么结尾
定义方法:16进制字符串转数值数组
首先要剔除一些没意义的值,空格,0X 0x等。这里可以用字符串的替换功能
定义byte类型的数组,长度是字符串长度的一半,因为这里是2个字符占一个字节,2个是一组
这里要把16进制的字符串转成数值数组多次,所以用到循环遍历截取字符
字符串.Substring(i*2,2),16)===》开始截取索引,截取长度,转换后的进制类型
2.发送的本质是写数据 内存走向外面
二、数据的字符串格式发送
Encoding.Default.GetBytes 直接转字符串格式
接收数据功能:
1.SerialPort类接收数据,会有事件产生(一共有三个事件),找到对应的事件
2.读取缓冲区数据 BytesToRead可以读取接收缓冲区字节数,接收的本质是读数据,所以需要用到write读入缓冲区数据
选择16进制显示===》调用字节数组转16进制字符串数组方法(形参 字节数组)
因为需要访问主窗体的控件,所以这里需要用到同步委托用来处理显示
打开串口的时候绑定该事件
定义方法:字节数组转16进制字符串数组显示
考虑到要进行多次转换,所以用到循环
方式1:ToString("X2") X代表是16进制,2代表2个
方式2:Convert.ToString(buffer[i], 16) 转16进制
方式3:用StringBuilder方式 对象.AppendFormat("{0:X2}", buffer[i])
选择字符串显示
Encoding.Default.GetString方式把字节数组转换成字符串
这里需要用到同步委托用来处理显示
报文解析功能:
这里我们需要对接收到的字节数组进行数据报文的解析,因此我们可用封装一个方法用来截取报文
这里考虑到高低位的影响,需要对字节数组进行翻转
BitConverter.ToInt16: 16进制转成10进制,ToInt16(代表2个字节)
温度值,湿度值这里可以用一个类库中的成员来表示,作为实体类的对象,这样要有多个数据的时候就方便管理
解析完成后,把值传递给子窗体进行显示
封装截取报文的方法:
封装方法的思路:把不变的封装成方法体,变化的作为参数,想得到的值作为返回值或者用out修饰,
这里我们想要从第x个开始截取(截取索引),截取长度,字节数组故而我们可将这些作为参数传递,得到的还是字节数组,所以返回值类型可以是字节数组
首先:我们可用对数据进行一些校验验证,防止字节数组索引+截取长度越界等情况=====》
截取后的字节数组长度应该是,实参的截取长度
截取是需要进行多次,所以考虑循环
选择自动发送
自动发送前,我们可以先进行一些校验。例如:串口未打开,数据不能为空,填写间隔时间为非整数
设置定时器.Interval间隔时间,定时器启动
*自动发送
调用16进制字符串格式转数值数组方法