数码之家

 找回密码
 立即注册
搜索
查看: 3633|回复: 145

[Arduino] 从模块化开始,把 LCD-320240 盘成 Windows 桌面副屏,并科普相关原理

    [复制链接]
发表于 2024-10-6 02:35:18 | 显示全部楼层 |阅读模式
首先感谢大家和网站的支持!上个月把一块 LCD-320240 把玩成了一块高度抽象的实体模块,取得了不错效果:https://www.mydigit.cn/thread-474575-1-1.html




然这样搞出来终究只是个单片机显示屏,若无大用必然吃灰。

整天拿笔记本写东西,副屏又恰好不在手头,着实有些不便。
这时候如果能把 320240 模块搞成 Windows 副屏,必然神清气爽。

技术上,本文介绍了一系列 C/C++ 软件代码的设计框架,并最终成功实现:
使用 Arduino+u8g2 类,驱动带串并中继的 LCD-320240;
设计 Win32-App,实现基于串口的 Windows 桌面副屏扩展。


【系统结构】

Windows 原生支持多屏幕显示,快捷键 Win+P 即可召唤多屏设置。
当采用“扩展”方式延伸桌面时,相当于将桌面坐标系扩展到多块显示器上,实现拼接效果:



此次盘屏把玩即以此为目标,预计给笔记本盘一个可扩展的单色副屏。

提要求容易,实际做起来相当费劲。Windows 常见显示器如图所示:



Windows OS 通过内置的 VGA/HDMI 驱动访问相应端口,实现显示。
此次折腾桌面副屏有两个技术路线:

(a) 如图蓝色,设计 VGA/HDMI 采集器获取图案,进而驱动 LCD;
(b) 如图绿色,设计虚拟驱动直接抽取图像,经USB下发给单片机。

方案 (a) 相当于自造了一台标准显示器,兼容性好,但硬件要求高;
方案 (b) 从实用出发,折中了硬件vs软件复杂度,更适合折腾。

大致定下系统结构后,开始从液晶底层一步步搭建LCD副屏系统。


【u8g2 刷屏原理】

之前模块化设计已将 LCD320240、CPLD串并中继封装进 u8g2 驱动类,
简单的 u8g2_GDI 接口调用即可实现绘图显示,例如:



然此次目标是向LCD刷入任意图像,在不放弃 u8g2 的前提下,需要使用其底层 u8x8 接口:



这样一来在保证液晶访问效率的前提下,可最大程度复用之前的类封装工作,避免重复造轮子。
用于刷新 LCD-320240 的 u8x8_API 原型如下:



对于 LCD320240,使用 drawTile 可绘制一个 320px*8px 的条形区域,内存消耗量为 320Bytes:



连续调用 30 次 drawTile 即可完成整屏刷新,内存消耗量不超过 320 B.

在 16MHz Arduino UNO 的驱动环境下,整屏刷新时间大约 1s,
与之前 19264 的单位面积刷新速率基本一致。

由于 Arduino 平台基本是硬件无关的,因而可以通过升级 CPU 获得更快刷新率。
这次折腾以 UNO 为准,尝试在低性能平台上跑到极致效果。


【Win32+AVR 双缓存传输】

至此在硬件+u8g2 层面已实现显示驱动:输入 30*320 字节,即可刷新全屏。

然实际系统中,显示数据位于上位机 Windows OS 中,
刷屏接口位于下位机 Arduino UNO 中,二者需要使用硬件串口实现数据互联。

为确保下位机刷屏效率不减,使用了双缓存机制进行传输:



下位机 Arduino UNO 使用乒乓缓存结构,实现软件刷屏、硬件接收同时进行:

线程#1 负责将 BufA 数据送入 u8x8_drawTile,实现实时刷屏;
线程#2 负责将 UART 数据送入 BufB,实现后台接收。

当刷屏与接收均完成后,切换 BufA 与 BufB 角色,零延时进入下一包数据处理。

对于 AVR 这类简单单片机,双线程乒乓操作由串行中断实现:



为了避免奇怪的 BUG,双线程设计了完备的临界区及接口,实测效果不错;
对于 ARM 或其他支持 DMA 的单片机,使用 DMA 可以更高效实现双线程工作。

上位机这边则需要一套同步机制,当下位机请求新数据包时予以回应(例如刷屏+接收均已完成):



至此已打通任督二脉,Win32 上位机数据可以高速下传给 Arduino 下位机,
并由后者同步刷新至 LCD-320240 单元模块,实现实时显示刷新。

实测加入了接收线程后,全屏刷新时间由 1.0s 上升至约 1.5s,
若采用支持 DMA 的处理器进行接收,相信对刷屏时间的影响会更小。


【Win32 截屏】

写到这里,技术上已实现了下位机刷屏、上下位机串行传输,
距离 Windows 桌面副屏只差一层虚拟的屏幕驱动代码:

让 Windows 认为有这么块屏幕,并向这块屏幕显示窗口内容。

实际做起来可借助现有的 VGA/HDMI 驱动:



在 Win+P 菜单中以扩展方式开启副屏,Windows 会扩展桌面坐标区域,并向相应端口(以VGA为例)输出视频信号。

此时物理 VGA 端口上并不插真实显示器,但另写一段 Win32-App 对副屏坐标区域进行截屏(如图绿色部分),
以此就可以成功把 Windows 显示数据抠出来送下位机,实现虚拟的显示驱动。

说干就干,截屏代码大致流程是 Win32API::GetDC( ) => ::BitBit( ) => ::GetDIBits( )



至此,上位机获得了一张存于内存中的 320x240xRGB888 截屏像素矩阵。


【Win32 二值化】

此次把玩的 LCD-320240 属于单色液晶屏,每个像素的数据仅有  1bit,
像素显示效果仅有纯蓝、纯白两种样式,通常记作 1bpp 位深度。

常见的彩屏液晶使用 16M 真彩色域,每个像素的数据有 24bit,
像素显示效果为红、绿、蓝三个分量的叠加,各分量再细分 256 阶亮度,
通常记作 24bpp 位深度,也是前文截屏获所获得的图像结构。

将上述 24bpp 的像素矩阵转换为 1bpp 像素矩阵的过程,称作“图像二值化”:



二值化过程中图像的色彩信息完全丢失,仅保留部分灰度信息,其余全靠观众脑补。

好的二值算法可以通过抖动(Dithering)模拟中等灰度,效果有灵魂;
渣的二值算法直接给你糊成一坨黑白,结果不忍直视。

下图为常见的全局阈值法二值化所得,即判断 R,G,B 的加权平均是否超过阈值,作为输出黑白的依据:



左图选择阈值太低,计算结果大量被认为是白色,进而亮瞎眼+断线;
右图选择阈值太高,计算结果大量被认为是黑色,进而糊成一坨。

全局阈值算法简单粗暴,但一个合适的阈值显得尤为重要。
当然也可以通过统计来自动计算一个最佳阈值,例如“大津阈值”.

副屏显示这里就偷个懒,直接搞个拖动条来设置全局阈值,省去诸多烦恼:




【实现效果】

搞了这么久,终于把上下位机都搞定了,再就是 CPLD 也烧好了。
果断插上 USB 通上电,亮屏还是冒烟全随缘。

上位机界面很给力,把自己截成图片传给了下位机,320240 液晶努力显示中:



把“我的电脑”窗口拖过来看看,效果挺像回事:



Win10 里调整下各显示器的相对坐标,开个数码坛看看分屏扩展,大致对上了:



受限于 AVR 的性能,刷新率不能太高,副屏适合显示静态参考资料。比如写东西列个大纲啥的:



当然最最重要的用途,监视各路下载/上传进度:



折腾了一大圈,获得一只拥有着朴素色彩的 Windows 副屏显示器。

附上文中涉及的源码,整理不易,仅在本坛分享:

------------------------------------------------------------------------------------------------------------------------

以上,从模块化开始,把一只 LCD-320240 最终盘成了 Windows 桌面副屏。

成功在单片机上亮起了 Win10 特有界面,获得了一只朴素的显示器,实测辅助写东西效果不错。

最后祝大家 DIY 愉快!


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

打赏

参与人数 14家元 +400 收起 理由
上官梦舞 + 10 優秀文章
闻太师 + 30 这是高手
dz20062008 + 30 優秀文章
kkdkj + 30 謝謝分享
kangyd + 30 優秀文章
b26359 + 30 優秀文章
aping365 + 30 優秀文章
2n3055 + 30 謝謝分享
cushion + 30 原創內容
vip2128 + 30 優秀文章

查看全部打赏

发表于 2024-10-6 05:53:30 | 显示全部楼层
最后祝大家 DIY 愉快!
牛人干啥都牛
回复 支持 反对

使用道具 举报

发表于 2024-10-6 06:09:51 | 显示全部楼层
玩出了高水平
回复 支持 反对

使用道具 举报

发表于 2024-10-6 07:10:40 | 显示全部楼层
感谢分享  高水平的操作
回复 支持 反对

使用道具 举报

发表于 2024-10-6 08:07:28 | 显示全部楼层
还能这样玩啊
回复 支持 反对

使用道具 举报

发表于 2024-10-6 08:14:12 | 显示全部楼层
虽然看不懂,感觉好厉害
回复 支持 反对

使用道具 举报

发表于 2024-10-6 08:29:00 | 显示全部楼层
这个不错,但确实没什么用。
回复 支持 1 反对 0

使用道具 举报

发表于 2024-10-6 09:10:25 | 显示全部楼层
毋庸置疑这是高手
回复 支持 反对

使用道具 举报

发表于 2024-10-6 09:46:35 | 显示全部楼层
这个看不懂啊
回复 支持 反对

使用道具 举报

发表于 2024-10-6 10:42:21 | 显示全部楼层
争取下辈子学会
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-6 10:59:57 | 显示全部楼层
hijk1 发表于 2024-10-6 05:53
最后祝大家 DIY 愉快!
牛人干啥都牛

感谢支持哈
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-6 11:00:38 | 显示全部楼层

终于不再吃灰
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-6 11:01:33 | 显示全部楼层

屏尺寸到了,自然想要折腾一番。

如果是以前那种小的 12864,最多折腾下 AIDA 性能监视器
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-6 11:02:56 | 显示全部楼层
leafchy 发表于 2024-10-6 08:29
这个不错,但确实没什么用。

老屏获得了新角色
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-6 11:03:42 | 显示全部楼层

这次纯软件折腾了一圈,还得是 windows
回复 支持 反对

使用道具 举报

发表于 2024-10-6 17:10:25 | 显示全部楼层
太强了这个
回复 支持 反对

使用道具 举报

发表于 2024-10-6 19:08:24 | 显示全部楼层
虽然不会复刻,感觉好厉害
回复 支持 反对

使用道具 举报

发表于 2024-10-6 20:10:16 | 显示全部楼层
这玩的 太强悍了


回复 支持 反对

使用道具 举报

发表于 2024-10-6 21:56:07 | 显示全部楼层

感谢分享  高水平的操作
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-6 22:17:42 | 显示全部楼层

感谢支持哈
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-11-10 11:04 , Processed in 0.156000 second(s), 12 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

快速回复 返回顶部 返回列表