发动态
综合 最新发布 最新回复
图文
列表
置顶
HDI高密度互连板正式上线
上一期我们实现了串口助手收发数据之后,这期我们为我们的串口助手加上我们的波形图功能。 我们在前面有一期中介绍如何在C#中使用chart画图库 本期我们利用我们上一期制作的串口助手来实现我们的串口示波器。 准备工作 首先我们在上一期的基础上加上我们的chart库using System.Windows.Forms.DataVisualization.Charting; 其次,简单的布置一下我们的界面。 其中图表和按钮的默认状态是隐藏的,当我们勾选波形显示时显示。 private void ChartShow_CheckedChanged(object sender, EventArgs e) { if (ChartShow.Checked == true) { Receive.Height = 680/2; chart.Show(); ClearChart.Show(); } else { Receive.Height = 680; chart.Hide(); ClearChart.Hide(); } } 我们勾选按钮的时候,将接收区的高度减少一半,让按键和图表显形。 数据解析与存放 我们希望我们的数据格式是类似“a:xxx,b:xxx”等等。因此,我们需要解析我们的数据private Dictionary<string, string> ParseData(string input) {             Dictionary<string, string> result = new Dictionary<string, string>(); // 按逗号分割字符串             string[] pairs = input.Split(','); foreach (string pair in pairs) { // 再按冒号分割键值对                 string[] keyValue = pair.Split(':'); if (keyValue.Length == 2) { string key = keyValue[0].Trim();                     string value = keyValue[1].Trim(); result[key] = value; } } return result; } 我们定义一个解析键值对函数,利用逗号分隔字符串,冒号分隔将解析的结果返回,这样子我们就可以获取我们的键值对。 // 添加解析数据的代码 string[] lines = data.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); lines = lines.Skip(1).Take(lines.Length - 2).ToArray(); 由于我们的数据可能有很多行,因此我们在更新图表的代码中需要将数据按照换行符分开,并且由于第一行和最后一行的数据可能不完整,我们需要删除第一行和最后一行的数据。foreach (string line in lines) {     // 对每一行进行解析     Dictionary<string, string> parsedData = ParseData(line);     foreach (var kvp in parsedData) {        // 继续处理解析后的数据       int existingIndex = chart.Series.IndexOf(kvp.Key);       if (existingIndex != -1)       {          //如果该系列的图表存在           chart.Series[existingIndex].Points.AddXY(chart.Series[existingIndex].Points.Count, double.Parse(kvp.Value));      } else { //如果该系列的图表不存在 string seriesName = new string(kvp.Key.TakeWhile(char.IsLetter).ToArray()); // 获取字符串中的所有字母前缀 Series newSeries = new Series(seriesName); newSeries.ChartType = SeriesChartType.Spline; // 设置图表类型为 Spline newSeries.Points.AddXY(0, double.Parse(kvp.Value)); chart.Series.Add(newSeries); } } } 我们将我们解析的数据放入图表,按照数据的前缀来划分数据。 判断图表是否存在,如果不存在就添加相应的系列。 效果展示 接着让我们看看效果
基于C#的软件大杂烩(1.2)——串口示波器
嘉立创PCB
3层板怎么下单
嘉立创PCB
在我们上一期代码中,我们利用HTTP将我们的数据上传到局域网,但是由于我们的程序是串行程序,即ADC采集完需要等待数据上传成功才能继续运行我们的代码,因此我们的数据就会出现很严重的数据丢失。 而我们在之前学习过STM32中的FreeRTOS即实时操作系统,将不同的任务按照不同的优先级分别运行。因此我们尝试使用FreeRTOS将ADC采集和数据上传的任务按照不同级别的优先级进行划分。 关于FreeRTOS的介绍可以查看前几期的内容基于STM32F407的FreeRTOS学习笔记(13)—— 阶段性的总结与后续 FreeRTOS库准备 FreeRTOS在ESP32中的环境配置比在STM32中简单许多,我们只需要在库管理中搜索FreeRTOS即可安装我们的FreeRTOS 我们直接安装最新版本的FreeRTOS#include<Arduino.h>#include <WiFi.h> #include<HTTPClient.h>#include <freertos/FreeRTOS.h>//FreeRTOS头文件 #include <freertos/task.h>//任务头文件 #include <freertos/semphr.h>//信号量头文件 之后我们放入相关头文件包含信号量和任务头文件还有FreeRTOS的基本头文件。 任务创建 任务创建可以参考我们的公众号文章基于STM32F407的FreeRTOS学习笔记(2)——任务的创建与删除TaskHandle_t Task1, Task2; xTaskCreatePinnedToCore( Task1Code, // 任务函数 "Task1", // 任务名称 10000, // 任务堆栈大小 NULL, // 任务参数 1, // 任务优先级 &Task1, // 任务句柄 0); // 核心编号 // 创建任务2,绑定到核心1 xTaskCreatePinnedToCore( Task2Code, // 任务函数 "Task2", // 任务名称 10000, // 任务堆栈大小 NULL, // 任务参数 2, // 任务优先级 &Task2, // 任务句柄 1); // 核心编号 我们创建任务1和任务2 的句柄,并且由于ESP32是双核的MPU,比起STM32我们可以将不同的任务绑定到不同的核心进行使用,我们设置两个任务,并且任务1的优先级大于任务2的优先级。 我们将任务1用于ADC采集,任务2用于数据上传。String postData = ""; String Data; int dataArray[1000]; // 任务1的函 void Task1Code(void *parameter) { for (;;) { for (int i = 0; i < 1000; i++) { dataArray[i] = analogRead(34); postData += String(dataArray[i]); if (i < 1000-1) { postData += ","; } delay(5); }   //采集完成发送信号量 xSemaphoreGive(dataSemaphore); Data = PostData; PostData = ""; } } // 任务2的函数 void Task2Code(void *parameter) { for (;;) { // 等待信号,表示可以使用postData if (xSemaphoreTak(dataSemaphore, portMAX_DELAY)) { HTTPClient http; http.begin(serverUrl); http.addHeader("Content-Type", "text/plain");       int httpResponseCode = http.POST(Data); // 处理响应 if (httpResponseCode > 0) { Serial.print("HTTP Response code: "); Serial.println(httpResponseCode); String response = http.getString(); Serial.println(response); } else { Serial.print("HTTP Request failed. Error code: "); Serial.println(httpResponseCode); } } delay(1000); } } 接着我们定义我们的任务函数,关于HTTP的部分参考上一期公众号内容。 我们每次采集好数据之后释放信号量,任务2等待信号量的释放,当任务1释放信号量之后我们上传我们的数据,需要注意的是,此时任务2上传数据时postData依旧在进行改变,所以我们需要用一个新的变量来接受PostData。 效果展示 我们来看看我们的运行效果
基于C#和ESP32的远程示波器(5)—— 利用FreeRTOS双核运行减少数据丢失
嘉立创PCB
1-32层pcb打样,真A级板材,最快12小时出货,自营制造,品质可靠!
打赏记录
服务时间:周一至周六 9::00-18:00 · 联系地址:中国·深圳(福田区商报路奥林匹克大厦27楼) · 媒体沟通:pr@jlc.com · 集团介绍
移动社区