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

1.Arduino UNO作为下位机

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

1.电路连接

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

2.下位机程序

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

  1. void setup() {
  2. // put your setup code here, to run once:
  3. pinMode(,OUTPUT);
  4. Serial.begin();
  5. }
  6.  
  7. void loop() {
  8. // put your main code here, to run repeatedly:
  9. int val=analogRead();
  10. int time;
  11. int result;
  12. for(time=;time<;time++)
  13. {
  14. result+=val;
  15. }
  16. result=result/;
  17.  
  18. if(result<)
  19. {
  20. digitalWrite(,HIGH);
  21. }
  22. else{
  23. digitalWrite(,LOW);
  24. }
  25.  
  26. Serial.println(result);
  27. delay();
  28. }

2.WPF串口上位机。

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

1.串口控件SerialPort。

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

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

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

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

代码写的很嫩。

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

xaml代码:

  1. <Window x:Class="Communication.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. xmlns:local="clr-namespace:Communication"
  7. xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0"
  8. mc:Ignorable="d"
  9. Title="MainWindow" Height="" Width=""
  10. Loaded="Window_Loaded">
  11. <Grid>
  12. <Grid.RowDefinitions>
  13. <RowDefinition Height=""/>
  14. <RowDefinition Height="auto"/>
  15. <RowDefinition Height="auto"/>
  16. <RowDefinition Height="auto"/>
  17. <RowDefinition Height="*"/>
  18. </Grid.RowDefinitions>
  19. <Grid.ColumnDefinitions>
  20. <ColumnDefinition Width="*"/>
  21. <ColumnDefinition Width="*"/>
  22. </Grid.ColumnDefinitions>
  23. <TextBlock HorizontalAlignment="Center"
  24. Text="光照度显示程序"
  25. Grid.ColumnSpan=""
  26. FontSize=""/>
  27. <StackPanel Orientation="Horizontal"
  28. Grid.Row="" >
  29. <TextBlock HorizontalAlignment="Left"
  30. Grid.Row=""
  31. Text="光照值:"/>
  32. <TextBlock HorizontalAlignment="Left"
  33. Grid.Row=""
  34. Name="light_result"/>
  35. </StackPanel>
  36.  
  37. <StackPanel Grid.Row=""
  38. Grid.Column=""
  39. Orientation="Horizontal"
  40. HorizontalAlignment="Center">
  41. <Button x:Name="开始"
  42. Content="开始"
  43. Click="开始_Click"
  44. Height=""
  45. Width=""
  46. Margin='10,0,10,0'/>
  47. <Button x:Name="关闭"
  48. Content="关闭"
  49. Click="关闭_Click"
  50. Height=""
  51. Width=""/>
  52. </StackPanel>
  53.  
  54. <ProgressBar Grid.Row="" Grid.ColumnSpan=""
  55. Minimum="" Maximum=""
  56. Height="" Width=""
  57. HorizontalAlignment="Left"
  58. x:Name="light_value"/>
  59. <d3:ChartPlotter x:Name="plotter"
  60. Margin="10,20,10,10"
  61. Grid.Row=""
  62. Grid.ColumnSpan="">
  63. <d3:HorizontalAxis>
  64. <d3:HorizontalIntegerAxis/>
  65. </d3:HorizontalAxis>
  66. <d3:VerticalAxis>
  67. <d3:VerticalIntegerAxis/>
  68. </d3:VerticalAxis>
  69. <d3:Header Content="光照曲线"/>
  70. <d3:VerticalAxisTitle Content="光照强度"/>
  71. </d3:ChartPlotter>
  72. </Grid>
  73. </Window>

后台代码:

  1. using Microsoft.Research.DynamicDataDisplay;
  2. using Microsoft.Research.DynamicDataDisplay.DataSources;
  3. using System;
  4. using System.IO.Ports;
  5. using System.Threading;
  6. using System.Windows;
  7. using System.Windows.Media;
  8. using System.Windows.Threading;
  9.  
  10. namespace Communication
  11. {
  12. /// <summary>
  13. /// MainWindow.xaml 的交互逻辑
  14. /// </summary>
  15. ///
  16.  
  17. public partial class MainWindow : Window
  18. {
  19.  
  20. SerialPort myPort = new SerialPort();
  21. double result;
  22. bool portClosing;
  23. string lightValue;
  24.  
  25. private ObservableDataSource<Point> dataSource = new ObservableDataSource<Point>();
  26. private DispatcherTimer timer = new DispatcherTimer();
  27. int i = ;
  28.  
  29. public MainWindow()
  30. {
  31. InitializeComponent();
  32. }
  33.  
  34. private void 开始_Click(object sender, RoutedEventArgs e)
  35. {
  36. try
  37. {
  38. myPort.BaudRate = ;
  39. myPort.DataBits = ;
  40. myPort.PortName = "COM3";
  41. myPort.NewLine = "\r\n";
  42. myPort.Open();
  43. portClosing = false;
  44. }
  45. catch (Exception err)
  46. {
  47. MessageBox.Show(err.Message);
  48.  
  49. }
  50.  
  51. myPort.DataReceived += MyPort_DataReceived;
  52.  
  53. timer.Interval = TimeSpan.FromMilliseconds();
  54. timer.Tick += drawPoint;
  55. timer.IsEnabled = true;
  56. plotter.Viewport.FitToView();
  57.  
  58. }
  59.  
  60. private void MyPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
  61. {
  62. if (portClosing)
  63. {
  64. return;
  65. }
  66.  
  67. try
  68. {
  69. lightValue = myPort.ReadLine();
  70. result = double.Parse(lightValue);
  71. }
  72.  
  73. catch(Exception err1)
  74. {
  75. //MessageBox.Show(err1.Message);
  76.  
  77. }
  78.  
  79. light_value.Dispatcher.BeginInvoke(new Action(() =>
  80. {
  81. light_value.Value = result;
  82. }));
  83.  
  84. light_result.Dispatcher.BeginInvoke(new Action(() =>
  85. {
  86. light_result.Text = result.ToString();
  87. }));
  88. }
  89.  
  90. private void 关闭_Click(object sender, RoutedEventArgs e)
  91. {
  92. portClosing = true;
  93.  
  94. Thread.Sleep();
  95.  
  96. if (myPort.IsOpen)
  97. {
  98. myPort.Close();
  99.  
  100. }
  101. else
  102. {
  103. MessageBox.Show("串口已关闭");
  104. }
  105.  
  106. timer.Stop();
  107. }
  108.  
  109. private void Window_Loaded(object sender, RoutedEventArgs e)
  110. {
  111. plotter.AddLineGraph(dataSource, Colors.Green, , "光照度");
  112.  
  113. }
  114.  
  115. private void drawPoint(object sender, EventArgs e)
  116. {
  117. double x = i;
  118. double y = result;
  119.  
  120. Point point = new Point(x,y);
  121. dataSource.AppendAsync(base.Dispatcher, point);
  122. i++;
  123. }
  124. }
  125. }

程序运行效果:

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

快速设计一个简单的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. ES5中数组新增的方法说明

    一.前言-索引 ES5中新增的不少东西,了解之对我们写JavaScript会有不少帮助,比如数组这块,我们可能就不需要去有板有眼地for循环了. ES5中新增了写数组方法,如forEach (js v ...

  2. Ajax请求ashx一般处理程序实现文件下载

    具体功能为,在文件数据列表中选择一行,点击表格上方的下载按钮,下载文件.由于表格中不包含文件路径,只能取到在数据库表中的ID,所以具体实现就是这样:首先点击一行,获取点击的一行数据的ID,用Ajax传 ...

  3. 【CSS sprites (CSS图片精灵) 详解】

    本文包含 CSS sprites 简介.原理.适用在哪些类型的网页制作中.背景图片的 position 值如何确定以及制作 sprites 的技巧. [CSS sprites 简介] CSS Spri ...

  4. iOS: XCode6 beta 6 错误

    在使用XCode6 Beta6时, 遇到"__TFSs15_arrayForceCastU___FGSaQ__GSaQ0__"错误: 在http://stackoverflow.c ...

  5. 2016022610 - redis列表命令集合

    参考网址:http://www.yiibai.com/redis/redis_lists.html Redis列表是简单的字符串列表,排序插入顺序.您可以在头部或列表的尾部Redis的列表添加元素.列 ...

  6. 获取网络图片的大小 改变 图片色值 灰度什么的方法集合-b

    直接上代码了 头文件 // 图片处理 0 半灰色  1 灰度   2 深棕色    3 反色 +(UIImage*)imageWithImage:(UIImage*)image grayLevelTy ...

  7. Nginx配置免费SSL证书StartSSL,解决Firefox不信任问题

    先在StartSSL上申请免费一年的SSL证书,具体过程网上很多教程.然后把申请到的key和crt文件上传到服务器,比如/usr/local/nginx/certs/. Nginx配置SSL证书 直接 ...

  8. 并发视频,怎么hold住高并发

    http://v.qq.com/boke/page/z/w/s/z0110e15rws.html http://weibo.com/codebox

  9. bzoj 2209: [Jsoi2011]括号序列 splay

    2209: [Jsoi2011]括号序列 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 833  Solved: 392[Submit][Status ...

  10. I2C总线之(三)---以C语言理解IIC

    为了加深对I2C总线的理解,用C语言模拟IIC总线,边看源代码边读波形: 如下图所示的写操作的时序图: 读时序的理解同理.对于时序不理解的朋友请参考“I2C总线之(二)---时序” 完整的程序如下: ...