STM32F767 Nucleo之RT-GUI实验


STM32F767 Nucleo是ST官方出的开发板,板子上引出了大量的管脚便于评估。板子上还有一个带串口功能的ST Link调试器,用于对767芯片进行调试,一些基础功能的评估在这一块板子上就能搞定,不需要额外的开发工具了。

我在这块板子上用rt-gui实现了一个计算器,屏幕数据通过USB摄像头来显示,鼠标和键盘数据通过自定义USB HID设备传送给开发板。PC端显示程序运行后效果如下:

   

PC端是一个简单的Qt程序,一边读取摄像头数据进行显示,一边将鼠标和键盘事件通过HID设备发送给开发板。这个程序的源代码在这里。如果有多个摄像头,可以用PageDown和PageUp按键进行切换。开发板上的程序在这里,采用rt-gui制作界面,用F767的jpeg硬核进行图片压缩,通过开发板的USB接口发送到PC端。

设计过程

F767 Nucleo板提供的资源如下:

这块板子已经具备了全速USB接口和以太网接口。为了在这块板子上运行rt-gui并显示出来,我用USB摄像头的方式来显示屏幕数据。767芯片内置了JPEG压缩硬核,可以将屏幕数据先压缩后再通过USB以摄像头数据的形式发送到PC进行显示,降低带宽要求。

整个工程的设计思路如下

从左至右看,要做的主要功能是rt-gui和rt-thread,为了便于开发调试,我还需要SWD进行在线调试。

rt-gui的输入部分通过自定义USB HID设备来做,把电脑鼠标的点击事件和键盘事件通过HID接口发送到板子上。rt-gui的显示部分用USB摄像头UVC(USB Video Class)来做,将rt-gui的图像数据用摄像头的方式发送给PC。rt-gui绘制屏幕数据先进行JPEG压缩然后再发送,减轻全速USB接口的压力。

767有512K的RAM,我准备使用320×240的分辨率,颜色用RGB565格式,这样模拟屏幕需要320x240x2=150K字节的内存。

rt-thread在cortex-m7上有移植好的代码,拿过来用就行了。用一个LED指示工作状态,一个LED用来指示摄像头是否为打开状态。finsh通过板子上的ST Link串口进行交互。

从右往左看,这块板子提供了USB接口,JPEG硬件编解码,足够大的内存,有LED指示灯,板子上的STLink为我们提供了SWD调试功能和串口功能。基本满足了上面的功能需求。

两边都能对上,把需要的功能在CubeMX中进行初始化。CubeMX是ST针对他家的芯片做的一个图形化初始化应用程序,用来生成初始化代码很方便,这个也是官方以后主推的方式。

在CubeMX中配置好要用的外设后,就可以生成我们的工程基础文件了。在CubeMX的中间件(middleware)中,并没有我们想要的USB UVC+HID的复合设备,这里先选一个Audio设备来修改。因为Audio和Video读起来和写起来比较相近,估计改起来也不会太难。

其实这里选Audio设备是因为他和Video设备类似,都是用同步传输模式传输数据。实际在修改的过程中,如果是一个全新的设备类,用什么设备来做模板差别都不大,因为USB规范中不同的设备类操作差异很大。

做好了准备后就是移植rtthread代码到CubeMX生成的工程中,这里我建议把CubeMX生成的工程修改成rtthread的,因为cube生成的代码少于rtthread 的。如何整合可以在这里了解。

在GitHub上的rtthread的主线中,rt-gui部分没有widget的代码。在realboard-lpc4088工程中有widget的代码,为了方便开发,我fork了一个rtthread的主线,在里面添加了realboard中widget的代码。添加了widget的rtt代码在这里。计算器的按键我用图片做的,为了降低内存开销,我在rt-gui的框架下定义了一种新的图片格式image_mem。这种格式完全不占用内存,只占用Flash空间,显示时直接通过blit_line绘制到屏幕上。

为了方便在Qt中调试UI部分的效果,我在scons的工具中添加了生成qt工程文件的功能,目前通过scons只能生成Qt工程文件,还不能调用gcc对代码进行Qt风格的编译。

STM32F767的JPEG硬核只能对YUV,CMYK和GrayScale的颜色格式进行编解码,不能对通常的RGB格式直接进行。为了将RGB颜色空间转换成JPEG硬核支持的格式,ST提供了转换库。为了减少转换时间,我针对这个应用写了个特殊的转换函数,速度比通用库快一些。

完成了这些准备工作后,计算器程序看起来就很简单了。界面部分模拟的液晶屏用了一个自定义的LCD widget,按钮直接贴图,有抬起和按下两种效果。计算部分直接用双精度浮点数做内置数据类型,因为767片子内置了双精度的浮点数计算单元,直接用double型代码会非常简单。液晶屏显示8位有效数字,double可以保证15位有效数字,完全够用了。