单片机esp32s2实现win10之USB副屏

单片机esp32s2实现win10之USB副屏_第1张图片

 

视频演示:

骚气双副屏,单片机实现win10 USB副屏演示esp32 s2_哔哩哔哩_bilibili-https://www.bilibili.com/video/BV1tU4y1F7B6?spm_id_from=333.999.0.0

开源计划

2021年最后一天,庆祝新年。
github开源地址如下,欢迎复刻魔改。发b站的可以@我,给三连打call。
https://github.com/chuanjinpang/win10_idd_xfz1986_usb_graphic_driver_display

概要

单片机esp32s2+SPI屏实现一个win10 USB接口显示器。

本项目借鉴了众多开源项目,主要借鉴:

1.github.com/microsoft/Windows-driver-samples/tree/master/video/IndirectDisplay

2.git://github.com/roshkins/IddSampleDriver.git

3.Bodmer/TFT_eSPI.git

4.nopnop2002/esp-idf-ili9340,

5.serge-rgb/TinyJPEG.git

6.TJpgDec。

目前FPS在~13FPS,纯黑屏幕时能摸到20FPS。

主机使用IDD显示驱动方案,将屏幕进行JPEG压缩,然后通过URB(USB请求包)发送到下位机。下位机解压并发DMA传输写屏达到高性能。下位机esp32s2只支持全速度12Mhz,所以必须高压缩的JPEG才能有高FPS.

为了获得较稳定的FPS,采用了动态码率策略,会依据图像情况,进行压缩率调整。

  1. 器件清单

以下链接与卖家只是我买的地方,仅作参考,只是型号是一样的,东西是同一种,有门道能找到更便宜的卖家最好。

像ESP-12H-Kit单独买模块小板就只要10块,适合自己做PCB板。

最近也支持了st7789这种屏。

名称

数量

参考图

参考链接

说明

1

ESP-12H-Kit/开发板

1个

3.0哈RJViXrMySIx! https://m.tb.cn/h.fW0rvEj?sm=7e7b4b  NodeMCU系列WiFi模块ESP32-S2F芯片 ESP-12H-Kit/开发板

2

2.4寸4线SPI串口TFT液晶显示屏模块 ILI9341驱动LCD触摸屏240*320

1个

7.0!vC8RXro0LDp嘻 https://m.tb.cn/h.fW0F9GF?sm=557ab4  2.4寸4线SPI串口TFT液晶显示屏模块 ILI9341驱动LCD触摸屏240*320

1.不用买触摸,软件目前不支持触摸功能。

用mouse更方便。

2.

其它类型的320*240屏也可以,比如st7789。不过软件目前只有9341驱动,将来会加上更多的屏。主要是合别人的代码。

3

MICRO USB转Dip 母座

1个

2信8fXpXroYDr0, https://m.tb.cn/h.fW0wxi2?sm=c95448  MICRO USB转Dip 母座B型 麦克5p 贴片转直插 转接板 已焊接 母头

4

2.54mm杜邦线

12根

自备

5

Micro USB线

1根

自备

  1. 整机组装图

这个是组双屏的效果,通常一个屏就好了。

3.硬件连接图

4 .安装说明

4.1 ESP32-S2固件更新

使用下载工具更新固件。第一次应该要更新所有的文件,包括bootloader.bin,partion-table.bin

4.2 windows驱动安装

因为目前没有给驱动签名,所以要关掉windows对驱动的检查,使用测试模式。

如果相对比较稳定后,看要不要弄个签名,淘宝上卖家签名一次要300!

4.2.1 启用测试模式

使用管理员身份打开命令行cmd

bcdedit /set testsigning on

重启系统,桌面右下角会有一个测试模式的水印。如下图。

如果要关掉,使用bcdedit /set testsigning off 然后重启即可。

4.2.2 安装驱动

1. 插入已经更新好esp32s2设备,这一步应该的固件。会被windows识别为未知设备,如下图。我们的USB设备号为:USB\VID_303A&PID_1986

2. 复制驱动文件到桌面,或者其它地方。

  1. 右键设备,选择浏览查找

  1. 找到驱动文件夹

  1. 选择始终安装此驱动,因为没有正式签名。系统给出警告。

  1. 安装完毕,会在显示适配器下面出现xfz1986_usb_graphic(demo). 正常就能看到windows桌面了。

  1. 本驱动目前只支持2种分辨率320*240,640*480.对于640会进行2:1缩放。

有兴趣的可以自己魔改,增加更多的设置,和更大的屏幕。

  1. 固件与驱动编译

4.1 esp32s2 设备固件编译

Esp-idf版本:v4.3-beta3

4.1.1. esp32s2_usbdisp 复制到esp-idf目录下

本身就是一个esp-idf工程

4.1.2 更新tinyusb

Tinyusb.tgz 解压合并放入esp-idf/components/tinyusb。图省事没有生成patch.大家可以用比较工具比较差异,改动并不大,主要是增加 vendor模式。需要注意的是,目前USB的改法是个临时方案,可能会对其它tinyusb有影响

4.1.3 配置工程

进入esp32s2_usbdisp

idf.py set-target esp32s2   #设置目标芯片

idf.py menuconfig #修改配置,

相关4个配置如下:主要是配置LCD管脚,提高CPU频率到 240M,编译为O2性能模式,使能 tinyUSB

4.1.4 编译

idf.py build

生成固件

4.1.5 可选的杂项

串口连接S2查看工作状态

默认打印FPS

开机logo

实现了一个开机图片,一个重要的功能是表明屏驱动在工作。是内嵌jpeg 文件的数组。具体是 logo.c 实现。

只要替换这个logo_jpg数组的内容即可。大小不要超过320*240.

我是用 git://github.com/Jamesits/bin2array.git 实现转换的,python小工具。

4.2 windows驱动编译

本人使用是vs2015+wdk10,也可以使用vs2019+wdk10等。大家可以自己看情况,网上也有相关教程。如果不想魔改,这个驱动也应该够用了。能魔改更好。

打开工程,右键工程,选择生成。

然后会在类似下面的路径生成驱动包。这个是x64的,应该没人用32位的系统吧?

  1. 软件架构

从设计实现上,本软件是支持2种数据模式,一种rgb565直传,一种是jpeg压缩数据。

USB传输也实现了两种:一种是同步,一种是异步模式。异步从理论上讲性能要好一些。

rgb565直传,同步模式主要是为了调试而存在了。

6.1 ESP32固件架构

Usb实现了一个vendor自己定义的USB设备,有一个in 管道。

注册一个回调处理函数tud_vendor_rx_cb,收到一个数据包64字节。

先进行头解析,如果是起始包byte[0] bit7 置位,表明一个操作开始,解析相应参数(total_size,top,bottom,...)。

然后将数据推入缓存disp_rx_ring_buf中。

显示线程,从disp_rx_ring_buf抽取数据进程处理,目前都是jpeg的显示数据,所以都会走jpeg显示处理,边接收数据边解码,积累到足够多时(一次多传输点,能降低额外开销,提高速度),启动SPI dma进行送显。同时会交换ping-pong buffer. 并行进行,提高FPS.

主机与设备通讯协议是沿用rpusbdisp的协议。就是消息头改了下:

该协议的要点:

USB是包消息,并且是固定长度64byte(大体如此),最后一个包例外。所以每个包第一个字节是协议占用,表明类型。好处是方便定位消息头部:如果第一个字节的bit7置位,就是一个新的操作,否则是数据。这样利于出错恢复。

解码与屏幕刷新:
1.这种是dma模式的spi,跑的是40Mhz,理论带宽可以跑到30 fps,如果spi是80Mhz的.屏幕也支持的话,就加倍了60fps。
2.另外一个关键点是边解码边刷数据,并行做。比如数据一帧要50ms.传输也要50ms.那串行就要100.并行就只要50ms.
3.一次刷dma数据不要太少,建议一次传5kb,降低非必要开销。具体大小要和数据配合调优。

6.2 windows驱动架构

大体框架是基于MS的idd驱动sampledriver,所以我只讲增加的部分。

1.在void SwapChainProcessor::RunCore()采集屏幕数据,当前没有找dirty区域,因为懒。

直接复制整个屏幕.

  1. 在这里,存在一个将GPU 数据转换为CPU能访问的数据区域,具体是创建了一个ID3D11Texture2D对象,其有D3D11_CPU_ACCESS_READ能力。然后复制出GPU 数据.
  2. 自动适应屏幕大小缩放。如果是640*480就2:1缩放。
  3. 然后调用usb_send_jpeg_image()发送
  4. 具体是先生成包头,内容jpeg编码压缩,这里有一个自动压缩率算法,目的是保证FPS能稳定在13-15fps。下位机能力比较弱,使用固定压缩质量,复杂画面容易把fps拉到10fps.
  5. 编码成usb协议包,也就是为每64byte增加一个特别的头。
  6. 调用usb_send_msg_async()进行真正的USB传输。

  1. 开发者

不才,欢迎相互交流下经验。

7.1 windows调试:

主要有2种,一种是用tracevew来查看驱动日志,另一种是windbg。

目前没有明显的bug,应该都用不上。只是开发过程中用得比较多。

7.2 esp32调试:

主要是log,当然也有一些高级点的调试,比如通过panic dump信息来正面刚来调试。

7.进一步的工作:

提高FPS,当前的瓶颈在于JPEG解码开销。 可能的方法:

  1. 采用 S3 双核并发提高JPEG 解码速度。

320*240对于桌面来说,分辨率小了些。因此可以考虑用安卓手机来当下位机显示器。

你可能感兴趣的:(DIY,干货,单片机,嵌入式硬件)