最近一直在学习UWP,其中有的技术参考了WPF,所以又回头再来学习WPF,感觉学的东西很杂,必须记录一下,不然时间长了还得忘掉,于是申请开始写博客,将学习的心得记录一下,以备后用。这次是因为公司内训,刚好想着推广一下开源硬件,所以选择了Arduino,而又结合WPF的强大功能,设计了串口上位机。

1.Arduino UNO作为下位机

利用Arduino作为下位机,理由很简单,语法很简单,上手很快。

1.电路连接

下图为电路原理图,主要利用模拟口A0读取光敏电阻和普通电阻的分压值,然后通过设定逻辑控制LED的状态。之后通过串口将数据发送给电脑。

2.下位机程序

在arduino IDE里完成。代码结构非常简单,setup()中设置IO口及串口,然后在loop()中读取数值,根据数据控制LED状态,并将数值从串口发送出去。

 void setup() {
// put your setup code here, to run once:
pinMode(,OUTPUT);
Serial.begin();
} void loop() {
// put your main code here, to run repeatedly:
int val=analogRead();
int time;
int result;
for(time=;time<;time++)
{
result+=val;
}
result=result/; if(result<)
{
digitalWrite(,HIGH);
}
else{
digitalWrite(,LOW);
} Serial.println(result);
delay();
}

2.WPF串口上位机。

这里主要使用WPF自带的串口控件、进度条、以及DynamicDataDisplay控件实现上位机数据显示。具体实现是:将arduino发过来的数据在页面上通过进度条显示出来,同时画出曲线。

1.串口控件SerialPort。

对于该控件,简单的使用过程如下:

  1. 实例化一个串口;
  2. 配置串口参数,例如波特率、数据位、串口号;
  3. 打开串口;
  4. 添加串口接收数据事件;
  5. 处理数据接收事件。

需要注意的是:多线程问题,由于WPF的控件都在UI线程,而串口数据在另外1个线程。一开始直接将串口数据给进度条赋值会出现错误,后来参考网上资料,使用了相应控件的dispatcher.invoke(Action()),解决了数据更新问题。关于多线程的问题,后续还需要再继续学习,搞清这一部分。

而数据曲线绘制使用了DynamicDataDisplay控件,相关使用方法可参考网上,由于第1次使用该控件,感觉效果还行。

代码写的很嫩。

程序界面如下,这里没有选择串口的选型,因为提前看了串口号。

xaml代码:

 <Window x:Class="Communication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Communication"
xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0"
mc:Ignorable="d"
Title="MainWindow" Height="" Width=""
Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=""/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Center"
Text="光照度显示程序"
Grid.ColumnSpan=""
FontSize=""/>
<StackPanel Orientation="Horizontal"
Grid.Row="" >
<TextBlock HorizontalAlignment="Left"
Grid.Row=""
Text="光照值:"/>
<TextBlock HorizontalAlignment="Left"
Grid.Row=""
Name="light_result"/>
</StackPanel> <StackPanel Grid.Row=""
Grid.Column=""
Orientation="Horizontal"
HorizontalAlignment="Center">
<Button x:Name="开始"
Content="开始"
Click="开始_Click"
Height=""
Width=""
Margin='10,0,10,0'/>
<Button x:Name="关闭"
Content="关闭"
Click="关闭_Click"
Height=""
Width=""/>
</StackPanel> <ProgressBar Grid.Row="" Grid.ColumnSpan=""
Minimum="" Maximum=""
Height="" Width=""
HorizontalAlignment="Left"
x:Name="light_value"/>
<d3:ChartPlotter x:Name="plotter"
Margin="10,20,10,10"
Grid.Row=""
Grid.ColumnSpan="">
<d3:HorizontalAxis>
<d3:HorizontalIntegerAxis/>
</d3:HorizontalAxis>
<d3:VerticalAxis>
<d3:VerticalIntegerAxis/>
</d3:VerticalAxis>
<d3:Header Content="光照曲线"/>
<d3:VerticalAxisTitle Content="光照强度"/>
</d3:ChartPlotter>
</Grid>
</Window>

后台代码:

 using Microsoft.Research.DynamicDataDisplay;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using System;
using System.IO.Ports;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading; namespace Communication
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
/// public partial class MainWindow : Window
{ SerialPort myPort = new SerialPort();
double result;
bool portClosing;
string lightValue; private ObservableDataSource<Point> dataSource = new ObservableDataSource<Point>();
private DispatcherTimer timer = new DispatcherTimer();
int i = ; public MainWindow()
{
InitializeComponent();
} private void 开始_Click(object sender, RoutedEventArgs e)
{
try
{
myPort.BaudRate = ;
myPort.DataBits = ;
myPort.PortName = "COM3";
myPort.NewLine = "\r\n";
myPort.Open();
portClosing = false;
}
catch (Exception err)
{
MessageBox.Show(err.Message); } myPort.DataReceived += MyPort_DataReceived; timer.Interval = TimeSpan.FromMilliseconds();
timer.Tick += drawPoint;
timer.IsEnabled = true;
plotter.Viewport.FitToView(); } private void MyPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (portClosing)
{
return;
} try
{
lightValue = myPort.ReadLine();
result = double.Parse(lightValue);
} catch(Exception err1)
{
//MessageBox.Show(err1.Message); } light_value.Dispatcher.BeginInvoke(new Action(() =>
{
light_value.Value = result;
})); light_result.Dispatcher.BeginInvoke(new Action(() =>
{
light_result.Text = result.ToString();
}));
} private void 关闭_Click(object sender, RoutedEventArgs e)
{
portClosing = true; Thread.Sleep(); if (myPort.IsOpen)
{
myPort.Close(); }
else
{
MessageBox.Show("串口已关闭");
} timer.Stop();
} private void Window_Loaded(object sender, RoutedEventArgs e)
{
plotter.AddLineGraph(dataSource, Colors.Green, , "光照度"); } private void drawPoint(object sender, EventArgs e)
{
double x = i;
double y = result; Point point = new Point(x,y);
dataSource.AppendAsync(base.Dispatcher, point);
i++;
}
}
}

程序运行效果:

以上就是软硬件系统的全部细节,欢迎拍砖!

快速设计一个简单的WPF串口上位机的更多相关文章

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

    C#做一个简单的进行串口通信的上位机   1.上位机与下位机 上位机相当于一个软件系统,可以用于接收数据.控制数据.即可以对接收到的数据直接发送操控命令来操作数据.上位机可以接收下位机的信号.下位机是 ...

  2. VC++编写简单串口上位机程序

    VC++编写简单串口上位机程序   转载: http://blog.sina.com.cn/s/articlelist_1809084904_0_1.html VC++编写简单串口上位机程序 串口通信 ...

  3. 设计一个简单的,低耗的能够区分红酒和白酒的感知器(sensor)

    学习using weka in your javacode 主要学习两个部分的代码:1.过滤数据集 2 使用J48决策树进行分类.下面的例子没有对数据集进行分割,完全使用训练集作为测试集,所以不符合数 ...

  4. WInform 创建一个简单的WPF应用

    (一)创建一个简单的WPF应用 首先,在这里我要说明的是:这里的例子,都是通过控制台程序来创建WPF应用,而非使用现成的WPF模版.因为WPF模版封装了创建WPF应用所需要的各种基本元素,并不利于我们 ...

  5. 180626-Spring之借助Redis设计一个简单访问计数器

    文章链接:https://liuyueyi.github.io/hexblog/2018/06/26/180626-Spring之借助Redis设计一个简单访问计数器/ Spring之借助Redis设 ...

  6. 【Head First Servlets and JSP】笔记6:什么是响应首部 & 快速搭建一个简单的测试环境

    搭建简单的测试环境 什么是响应首部 最简单的响应首部——Content-Type 设置响应首部 请求重定向与响应首部 在浏览器中查看Response Headers 1.先快速搭建一个简单的测试环境, ...

  7. 制作一个简单的WPF图片浏览器

    原文:制作一个简单的WPF图片浏览器 注:本例选自MSDN样例,并略有改动.先看效果: 这里实现了以下几个功能:1.  对指定文件夹下所有JPG文件进行预览2.  对选定图片进行旋转3.  对选定图片 ...

  8. Tomcat详解系列(1) - 如何设计一个简单的web容器

    Tomcat - 如何设计一个简单的web容器 在学习Tomcat前,很多人先入为主的对它的认知是巨复杂的:所以第一步,在学习它之前,要打破这种观念,我们通过学习如何设计一个最基本的web容器来看它需 ...

  9. 【python免费代码】设计一个简单的学生信息管理系统

    文章目录 前言 一.理解 二.部分截图展示 三.代码 四.总结 前言 设计一个简单的学生信息管理系统,实现以下功能(bug) : 录入学生信息,信息以文件方式存储 以学生学号或者学生姓名为条件查询该学 ...

随机推荐

  1. Mysql创建删除索引

    1.查看某个表中的索引 show index from 表名 2.为某个表创建索引 alter table 表名 add index 索引名(列名)    //此种方式创建一般的索引 alter ta ...

  2. 对N个数组进行操作。先把这N个一维数组合并成一个2为数组;然后进行操作

    using System;using System.Collections.Generic;using System.Linq;using System.Collections;using Syste ...

  3. Android学习2--项目文件列表简单分析

    使用Eclipse创建的默认项目文件列表如下: src:src目录是Android工程的源程序目录,该目录用于存放Java项目的源代码 gen:gen目录存放所有自动生成的文件,在这个目录中最关键的文 ...

  4. 问题:Bringing up interface eth0: Device eth0 does not seem to be present,delaying initialization. [FAILED]—— 找不到网卡。

    克隆虚拟机的时候或其他情况出现以下问题(命令service network restart):   Bringing up interface eth0:  Device eth0 does not ...

  5. Fedora 21 中添加及更新源的命令

    原文: Fedora 21 中添加及更新源的命令 fedora的软件源信息文件(*.repo)都是放在 /etc/yum.repos.d 目录下的.可以通过# ls -l /etc/yum.repos ...

  6. 【C语言】中的版本规范(C89 C99等)

    C语言中的版本 一.相关基础知识 ISO:国际标准化组织(International Organization for Standardization,ISO)简称ISO,是一个全球性的非政府组织,是 ...

  7. 浅谈JS DDoS攻击原理与防御

    分布式拒绝服务攻击(DDoS)攻击是一种针对网站发起的最古老最普遍的攻击.Nick Sullivan是网站加速和安全服务提供商CloudFlare的一名系统工程师.近日,他撰文介绍了攻击者如何利用恶意 ...

  8. onchange事件

    一.onchange 一般input type text的onchange事件的触发需要两个条件:1.输入框的值发生了改变:2.该文本框失去了焦点,而真正的事件的触发却是发生在该文本框失去焦点的时候, ...

  9. 吉哥系列故事——完美队形II

    hdu4513:http://acm.hdu.edu.cn/showproblem.php?pid=4513 题意:给以一个序列,然后让你求一个最长回文序列的长度,这个序列的从左到最中间那个数是不降的 ...

  10. Astyle:代码格式化工具简明指南

    astyle是一个我自己常用的开放源码工具.它可以方便的将程序代码格式化成自己想要的样式而不必人工修改.本来嘛,作为高等生物应该优先去做一些智慧的事情,而不是把时间消耗在机器可以完美完成的事情上. 想 ...