公司动态

迪文串口屏曲线显示实战:从控件配置到MCU通信优化

📅 2026/8/1 10:51:08
迪文串口屏曲线显示实战:从控件配置到MCU通信优化
1. 项目概述与核心价值最近在做一个工业数据采集的项目需要在一块迪文科技的串口屏上实时显示传感器采集的温度、压力曲线。一开始觉得这应该是个挺简单的功能毕竟迪文的开发工具看起来挺直观的。但真上手做才发现要把动态的、平滑的曲线在资源受限的串口屏上流畅地画出来里面有不少门道。踩了几个坑之后总算把效果调得比较理想了曲线刷新流畅没有闪烁还能支持触控查看历史点数据。今天就把我在迪文串口屏上实现曲线显示的全过程包括底层原理、具体实现步骤、以及那些官方文档里没写的优化技巧系统地梳理一遍。如果你也在用迪文、淘晶驰、广州大彩这类串口屏做数据可视化特别是需要展示波形、趋势图那么这篇文章应该能帮你省下不少摸索的时间。串口屏的曲线显示核心解决的不仅仅是“画线”问题更是如何在有限的串口带宽和屏幕自身处理能力下实现高效、稳定、美观的数据呈现。这背后涉及到数据打包策略、屏幕绘图指令的巧妙运用、以及前端比如单片机和屏幕之间的协同优化。2. 曲线显示的核心原理与方案选型2.1 串口屏绘图的基本逻辑要理解曲线显示首先得明白迪文这类串口屏的“工作模式”。它本质上是一个带有独立处理器和显存的显示终端我们的主控MCU比如STM32、MSPM0等并不直接操控屏幕上的每一个像素。两者之间通过串口UART按照特定的指令集进行通信。MCU只需要发送一条简短的指令比如“在坐标(x1,y1)到(x2,y2)之间画一条红色的线”屏幕在接收到这条指令后会由自身的CPU去执行实际的像素填充操作。这种架构的优势非常明显极大减轻了主控MCU的负担主控无需管理复杂的图形库和显存只需关注业务逻辑和数据。但劣势也同样突出所有图形操作都依赖于串口指令的传输。一条简单的画线指令可能只有十几个字节但如果你要每秒更新几十个点构成的曲线串口通信就可能成为瓶颈导致刷新慢、曲线卡顿。因此在迪文屏上实现曲线显示首要原则就是最大化减少不必要的串口通信数据量并充分利用屏幕自身的图形处理能力。2.2 曲线实现的几种方案对比根据我的实践和项目需求主要有三种实现思路方案一基于“画线”指令的动态绘制这是最直观的方法。每次得到一个新数据点就计算其在屏幕坐标系中的位置然后从上一点到新点画一条线段。迪文的指令集里通常有画线指令比如AA 00 06 C5 x1 y1 x2 y2 ...这类格式。优点实现简单逻辑清晰适合曲线点稀疏或变化不频繁的场景。缺点当需要绘制连续、平滑的曲线时需要发送大量画线指令。假设每秒20个点就要发送19条画线指令串口压力巨大极易造成闪烁和延迟。而且无法方便地擦除旧曲线。方案二基于“图片”或“图标”的预渲染将整个曲线区域视为一张小图片。MCU在内存中维护一个曲线图像缓冲区将所有数据点绘制到这个缓冲区中然后将整张图片数据一次性发送给屏幕更新。优点刷新效率高一次传输即可更新整个曲线区域视觉效果稳定无闪烁。缺点对MCU的RAM和计算能力要求较高需要MCU端实现一个轻量级的图形绘制库画点、画线、清空区域。同时传输一张哪怕很小的位图数据量也远大于几条指令。方案三利用屏幕的“曲线”或“绘图”控件推荐这是最高效、最专业的方法。迪文科技的DGUSDwin Graphic User Interface System开发平台以及淘晶驰、广州大彩的同类型平台通常都提供了专门的“曲线显示”控件。这个控件的原理是屏幕端固件已经内置了高效的曲线绘制算法。MCU只需要通过串口以特定格式不断向该控件对应的变量地址写入新的数据点坐标值屏幕就会自动完成曲线的绘制、平移和更新。优点效率极高MCU仅传输核心数据如两个字节的Y坐标值通信量最小。功能强大控件通常支持背景网格、坐标轴、曲线颜色、线宽、自动平移、清屏等属性配置这些都在屏幕端完成不占用MCU资源。显示流畅由于是屏幕硬件加速绘制曲线滚动平滑无闪烁。缺点需要熟悉特定平台控件的配置和数据协议有一定的学习成本。对于绝大多数实时数据监控场景方案三使用曲线控件是最优解。它不仅性能好而且大大降低了MCU侧的软件复杂度。我后续的实操也将围绕这种方法展开。注意不同品牌、甚至同品牌不同系列的串口屏其曲线控件的具体名称、配置方式和数据协议可能有差异。例如迪文屏可能叫“曲线记录”控件而大彩屏可能叫“波形图”控件。但核心思想是相通的MCU发数据屏幕来画画。3. 迪文曲线控件配置详解这里我以迪文科技的DGUS屏如DMG系列为例详细说明如何配置一个曲线显示区域。如果你用的是其他品牌请参考其对应的开发软件手册但配置逻辑是相似的。3.1 软件准备与界面规划首先需要在电脑上安装迪文的开发软件DGUS Tool或新版DWIN PC软件。第一步不是急着拉控件而是做好规划确定曲线显示区域在屏幕上划定一块矩形区域用于显示曲线。记住这个区域的左上角和右下角坐标例如 (100, 50) 到 (500, 250)。确定坐标范围你的数据范围是多少比如温度是0-100℃压力是0-1MPa。这决定了Y轴的显示范围。X轴通常是时间可以设置为固定的点数比如显示最新的300个点。设计背景通常我们会设置一个带网格和刻度线的背景图让曲线更容易阅读。这个背景图可以用DGUS Tool绘制或者用Photoshop等工具做好后导入。关键点背景图需要单独作为一个页面或图层曲线控件将叠加在它上面显示。3.2 曲线控件属性配置在DGUS Tool的页面编辑中找到“曲线记录”控件可能位于“高级控件”或“图表”分类下将其拖拽到之前规划的区域中。接下来是核心的配置项每一项都直接影响最终效果基本属性控件ID/变量地址这是最重要的设置屏幕通过这个地址来识别数据是发给哪个曲线的。例如我们设置为0x1000。MCU后续就会向0x1000这个地址发送数据。数据点数控件内部缓存的数据点数量。例如设为300表示屏幕会记住最新的300个点当第301个点到来时最老的第1个点会被挤出实现曲线向右平移的效果。曲线颜色、线宽根据UI设计设置。坐标轴与缩放Y轴最小值/最大值对应你数据的物理范围。例如温度0-100℃这里就填0和100。这里有个坑迪文屏的Y坐标是从上往下增长的屏幕左上角为(0,0)而我们的数据通常是数值越大曲线越高。因此我们需要做一个“翻转”映射。通常的作法是在配置时将Y轴最大值设为0Y轴最小值设为100即反着填或者在MCU发送数据前进行换算。我强烈推荐在MCU端做换算这样配置更直观。X轴方向设置曲线是从左到右绘制以及平移方向。背景网格可以设置网格颜色、是否显示通常配合背景图使用。数据写入模式写入方式通常选择“自动平移”。当数据点超过显示点数时旧点向左移出新点从右侧进入。数据格式这是重中之重需要明确屏幕期待的数据格式。通常是16位无符号整数2字节。假设Y轴范围0-100对应数据0-100。但屏幕像素高度可能只有200个像素所以你需要将实际数据映射到0-6553516位整数的范围或者一个更小的范围。具体映射关系需要根据控件Y轴的最小/最大值设置来计算。配置示例与计算假设我们规划如下曲线显示区域像素高度Height 200 pixel(从Y坐标50到250)数据物理范围Temp_min 0°C,Temp_max 100°C屏幕控件Y轴配置Y_min 0,Y_max 1000(这里我们故意放大范围提高映射精度)目标当温度50°C时曲线应画在区域垂直中部。映射公式为y_send (temp - Temp_min) / (Temp_max - Temp_min) * (Y_max - Y_min) Y_min代入y_send (50 - 0) / (100 - 0) * (1000 - 0) 0 500那么MCU需要计算出一个0-1000之间的值。发送时需要将这个整数500转换为两个字节高位在前。即发送0x01 0xF4500的十六进制。实操心得不要在控件配置里把Y轴范围设得和像素高度一样比如0-200这样数据精度损失大。应该设置一个比物理范围更大的“逻辑范围”如0-1000这样MCU计算出的y_send精度更高曲线在屏幕上移动更平滑。3.3 背景与坐标刻度的实现曲线控件本身通常不负责绘制精细的网格和刻度文字。这部分有两种实现方式静态背景图在DGUS Tool中用基本绘图工具直线、文字画好网格、刻度值和单位生成一张背景图。将曲线控件叠加在此背景之上并设置曲线控件的背景为透明。这是最常用、最省事的方法。动态文本控件如果需要刻度值也能随数据范围变化可以为每个刻度值创建一个“文本显示”控件并分配单独的变量地址。MCU在更新曲线数据的同时也更新这些文本控件的值。这种方法更灵活但更复杂占用更多变量地址。对于大多数应用静态背景图完全足够。确保你的背景图网格划分与曲线控件中设置的Y轴范围0-1000在逻辑上对齐。例如背景图上每格代表50°C那么在0-1000的逻辑范围内每格就对应50 * (1000/100) 500个逻辑单位。4. MCU端数据发送与通信协议屏幕配置好了接下来就是让MCU以STM32为例把数据“喂”给屏幕。这里的关键是严格按照迪文的串口协议来打包数据。4.1 迪文串口协议要点迪文屏通常使用一种简单的帧结构[帧头] [数据长度] [指令/数据] ... [帧尾]常见的具体格式如5A A5 [Len] [83/82] [Addr_H] [Addr_L] [Data_H] [Data_L] ...5A A5帧头。[Len]后续数据的字节长度。[83]写变量存储器指令。82是读指令。[Addr_H] [Addr_L]两个字节的变量地址高位在前。比如我们曲线控件的地址0x1000就是0x10 0x00。[Data_H] [Data_L]要写入的数据。对于16位变量就是两个字节。4.2 数据发送函数实现在STM32的代码中你需要实现一个发送函数。假设我们使用USART1并配置好了串口。// 向迪文屏指定地址写入一个16位数据 void DWIN_Write_VP(uint16_t addr, uint16_t data) { uint8_t cmd_buf[7]; cmd_buf[0] 0x5A; cmd_buf[1] 0xA5; cmd_buf[2] 0x03; // 后续数据长度为3字节 (指令1 地址2) cmd_buf[3] 0x82; // 写变量指令注意有些屏是0x83以实际手册为准 cmd_buf[4] (uint8_t)(addr 8); // 地址高字节 cmd_buf[5] (uint8_t)(addr); // 地址低字节 // 对于曲线控件数据通常需要连续写入这里先不包含数据 HAL_UART_Transmit(huart1, cmd_buf, 6, 100); // 紧接着发送数据部分长度字节需要变化 // 实际协议中数据和指令地址可能在同一个包。这里拆开是为了说明。 // 更常见的格式是5A A5 05 82 10 00 01 F4 (向0x1000写入0x01F4) }对于曲线控件数据写入有特定格式。通常不是一次只写一个点而是可以连续写入多个点的Y坐标值。具体协议需要查阅你所用屏的《指令集手册》。一个典型的格式可能是先发送写指令和曲线控件起始地址然后连续发送N个点的16位数据。// 示例向曲线控件(地址0x1000)连续发送3个数据点 void DWIN_Send_CurveData(uint16_t addr, uint16_t *data_buf, uint8_t point_num) { uint8_t tx_buf[128]; // 足够大的缓冲区 uint8_t index 0; tx_buf[index] 0x5A; tx_buf[index] 0xA5; // 长度 指令1 地址2 数据(2*point_num) tx_buf[index] 1 2 2 * point_num; tx_buf[index] 0x82; // 写指令 tx_buf[index] (uint8_t)(addr 8); tx_buf[index] (uint8_t)(addr); for(int i0; ipoint_num; i) { tx_buf[index] (uint8_t)(data_buf[i] 8); tx_buf[index] (uint8_t)(data_buf[i]); } HAL_UART_Transmit(huart1, tx_buf, index, 200); }4.3 数据映射与定时发送在应用程序中你需要定时例如每秒10次从传感器读取数据进行映射计算然后调用发送函数。#define CURVE_ADDR 0x1000 // 曲线控件变量地址 #define Y_LOGICAL_MAX 1000 // 与屏幕控件配置的Y轴最大值对应 #define Y_LOGICAL_MIN 0 #define TEMP_PHYSICAL_MAX 100.0f #define TEMP_PHYSICAL_MIN 0.0f uint16_t MapTemperatureToLogic(float temp) { if(temp TEMP_PHYSICAL_MIN) temp TEMP_PHYSICAL_MIN; if(temp TEMP_PHYSICAL_MAX) temp TEMP_PHYSICAL_MAX; // 映射计算 float ratio (temp - TEMP_PHYSICAL_MIN) / (TEMP_PHYSICAL_MAX - TEMP_PHYSICAL_MIN); uint16_t logic_value (uint16_t)(ratio * (Y_LOGICAL_MAX - Y_LOGICAL_MIN) Y_LOGICAL_MIN); // 注意屏幕Y坐标从上往下增长如果需要曲线向上这里可能需要取反 // logic_value (Y_LOGICAL_MAX - Y_LOGICAL_MIN) - logic_value; return logic_value; } void App_Task_10Hz(void) { // 假设这个函数每100ms被调用一次 float current_temp Read_Temperature_Sensor(); uint16_t send_data MapTemperatureToLogic(current_temp); DWIN_Send_CurveData(CURVE_ADDR, send_data, 1); // 发送单个点 // 或者可以缓存多个点一次性发送以提高效率 }重要提示串口通信的可靠性至关重要。务必开启MCU串口的TX完成中断或DMA并确保发送缓冲区不溢出。在屏幕端有时也需要在DGUS Tool中设置合适的“触控上传”和“变量上传”间隔避免双方同时发送造成冲突。5. 高级优化与交互功能实现基础曲线显示完成后我们可以追求更好的体验和更多功能。5.1 多曲线同屏显示很多应用需要同时显示多条曲线比如温度、湿度、压力。实现方法有两种多个曲线控件叠加在屏幕上放置多个曲线控件分配不同的变量地址。MCU轮流向不同地址发送数据。需要仔细设置每个控件的显示区域和颜色确保不重叠或做好透明叠加。单个控件多通道一些高级的曲线控件支持多通道。即一个控件变量地址下可以通过协议区分不同通道的数据。例如发送的数据包中除了Y坐标还包含一个通道ID。这种方式更节省变量地址资源但协议更复杂需要屏幕固件支持。5.2 触控交互查看点数据与时间这是让图表变得“好用”的关键。类似于ECharts中鼠标悬停显示数值和时间的体验在串口屏上可以通过触控来实现。实现思路启用触控在曲线显示区域叠加一个“触控控件”透明按钮或者直接启用曲线控件本身的触控属性如果支持。读取触控坐标当用户点击屏幕时触控控件会将其对应的变量地址的值更新为触摸点的X坐标可能是一个0-宽度值的数字。MCU响应与查询MCU通过轮询或中断检测到该触控地址的值发生变化即可知道用户点击了曲线的大概位置X坐标。反查数据与显示MCU根据收到的X坐标像素位置换算出是第几个数据点因为你知道总点数和X轴范围。MCU在自己的内存中保存着最近一段时间的历史数据数组这是必须的屏幕只负责显示不负责存储原始数据。根据计算出的数据点索引从历史数据数组中取出对应的原始物理值如25.6°C和时间戳。MCU将这两个值分别写入屏幕上预留的“数值显示”文本框和“时间显示”文本框对应的变量地址。屏幕更新屏幕上的文本框立即显示出该点的具体数值和时间实现了“点击查数据”的效果。踩坑记录千万不要试图从屏幕端“读回”曲线数据。屏幕通常不提供这个功能或者效率极低。历史数据一定要在MCU端备份一份。MCU内存不够可以降低历史数据分辨率每10个点存1个或者使用外部Flash/EEPROM存储。5.3 清空曲线与暂停刷新有时需要手动清空曲线重新开始记录或者暂停观察。清空曲线通常曲线控件有一个“清空”指令或者向控件变量地址写入一个特定的值如0x5555来触发清空。最可靠的方法是在屏幕端配置一个“清空”按钮该按钮按下时通过串口向MCU发送一个特定指令由MCU来清除自己的历史数据缓冲区并停止发送数据一小段时间或者发送一组使曲线复位的数据。暂停刷新MCU端停止向曲线控件地址发送新数据即可。可以做一个标志位由屏幕上的“暂停/继续”按钮来控制。6. 常见问题排查与调试技巧在实际开发中你肯定会遇到各种问题。这里列几个我遇到的典型问题及解决方法。问题现象可能原因排查步骤与解决方案屏幕完全不显示曲线1. 串口通信不通。2. 变量地址错误。3. 控件未正确配置或未使能。1. 用USB转串口工具连接屏幕用PC串口助手发送简单指令如写一个文本控件测试通信。2. 核对DGUS工程中曲线控件的变量地址与MCU代码中发送的地址是否完全一致包括字节顺序。3. 检查曲线控件的“隐藏”属性是否被勾选确认控件已放置在正确的页面并已上传到屏幕。曲线显示位置错乱1. 数据映射公式错误。2. 屏幕Y轴坐标方向理解有误。3. 背景图坐标与控件区域不匹配。1. 在MCU端将计算出的待发送数据通过调试口打印出来检查其范围是否在预期内。2. 发送一组固定值如最小值、中间值、最大值测试曲线出现的位置调整映射公式或屏幕控件的Y轴最大/最小值设置。3. 在DGUS Tool中使用“预览”功能查看控件实际覆盖的区域是否与背景图对齐。曲线刷新闪烁或卡顿1. 串口发送频率过高数据拥堵。2. 单次发送数据点太多一包数据量过大。3. 屏幕处理不过来。1. 降低MCU发送频率尝试每200ms或500ms发送一个点。2. 不要一次性发送所有历史点。采用“增量更新”方式只发送新点。利用曲线控件的自动平移功能。3. 检查屏幕型号的刷新能力过于复杂的页面很多控件同时更新会导致整体变慢。简化页面设计。触控查数据不准1. 触控坐标与数据索引换算错误。2. MCU端历史数据缓冲区与屏幕显示不同步。1. 打印出触控返回的坐标值与屏幕实际像素坐标对比检查换算公式。2. 确保MCU每次发送一个数据点就将其存入历史数组。数组应采用FIFO循环队列管理大小至少等于屏幕显示的点数。上电后曲线控件不工作1. 屏幕配置文件未正确烧录。2. 变量存储器初始化问题。1. 重新使用SD卡或软件工具将完整的DGUS工程包括配置文件、图片、字库完整下载到屏幕Flash中。2. 尝试在MCU初始化后延迟几秒再开始发送数据确保屏幕系统完全启动。或先发送一条简单的指令“握手”确认。调试必备工具串口助手软件连接屏幕的通信串口监控MCU发出的每一帧数据。确保帧头、长度、指令、地址、数据都正确。也可以手动发送指令测试屏幕。DGUS Tool的“离线模拟”在电脑上模拟屏幕运行可以单步调试触控反馈非常方便但无法完全模拟真实的数据流刷新。逻辑分析仪或示波器如果遇到奇怪的通信问题用它抓取串口波形检查时序、波特率是否准确。最后再分享一个提升视觉效果的小技巧如果曲线需要平滑抗锯齿而屏幕控件本身不支持可以在MCU端做文章。采用简单的滑动平均滤波算法处理原始数据再发送给屏幕这样画出来的曲线会柔和很多避免生硬的锯齿状。当然这会引入一定的延迟需要根据实际需求权衡。整个实现过程从原理理解、工具配置、代码编写到调试优化是一个典型的嵌入式GUI开发流程。核心思想始终是合理分工让屏幕做它擅长的图形渲染让MCU做它擅长的数据采集和逻辑控制两者通过高效的串口协议协同工作。希望这份详细的总结能让你在实现串口屏曲线显示的路上走得更顺畅。