
【ART-Pi】ART-Pi 类PC多媒体扩展板
简介
为ART-Pi扩展USB和VGA接口,方便把ART-Pi打造成自己的小电脑。
简介:为ART-Pi扩展USB和VGA接口,方便把ART-Pi打造成自己的小电脑。开源协议
:描述
简介
本项目为RT-Thread旗下开源硬件ART-Pi的扩展板。为ART-Pi扩展了VGA和USB接口。可以用来连接VGA显示器和键盘,将ART-Pi打造成一台类似“PC”的设备。或者作为简单的GUI开发平台。
特性
- 支持标准VGA接口(D-Sub),由LTDC控制器驱动
- 最高支持XGA(1024x768)的分辨率
- 支持DDC协议,使用硬件I2C控制器,可用来提供EDID的支持
- 专用视频DAC,支持最高1600万色(16.7M色,RGB888)
- D-Sub上具有专有ESD保护,防止静电损伤
- 支持USB 2.0 Full-Speed
- USB接口上带有专用ESD防护和过流保护,以及一个过流保护指示灯
- 一个额外的电源接口,可以为扩展板和ART-Pi供电,输入电压为7~12V
- 通孔型扩展板,可继续连接其他扩展板模块
原理详解
VGA
首先,强烈推荐大家去看这个视频,链接:这可能是世界上最差的显卡 ,这个视频中作者在面包板上制作了一个可以输出VGA信号的“显卡”。作者对VGA信号的解释非常简单易懂,适合从来没有了解过VGA的朋友观看。
VGA的信号中有控制信号(同步信号)和数据信号,对于我们这个项目而言,我们首先要注意的是VGA控制信号的时序:
这张时序图也解释了VGA的具体工作方式:显示的内容是逐行发送的,在一行的内容发送完毕后,通过一个名为Horizontal Sync Pulse(HSP)的脉冲来通知显示设备当前行的内容传输完毕,然后传输下一行。如此循环,直到整屏的内容传输完毕后发送一个Vertical Sync Pulse(VSP)脉冲,至此一帧传输完毕。然后继续传输下一帧。
VGA是纯模拟信号,它是为CRT显示器准备的,显示设备完全是通过HSP和VSP两个脉冲的长度以及脉冲之间的间隔来确定信号的格式。因为没有数字通讯的过程,所以对时序的准确度要求较高。而且由于显示器的限制,事实上我们并不能自由决定HSP和VSP的信号长度和间隔,下面则是一些常用的信号格式:
知道了信号的格式,我们该如何产生精确的信号时序呢。可能有同学会说使用Timer定时器就可以。这的确也是一种方法, 但是实现起来比较麻烦。这里我们不用它而是使用ART-Pi的主控STM32H750XB的一个外设——LTDC来实现VGA信号的生成。
LTDC全称是“LCD-TFT display controller”即LCD显示设备控制器。故名思意,LTDC是用来控制LCD液晶显示器的外设,它有两种工作模式:DE模式和HV模式,区别是DE模式仅使用DE信号进行帧同步,而HV模式则需要使用HSYNC和VSYNC两个信号来进行数据帧同步。
看过VGA的信号工作原理后,相信你一定会对HV模式的HSYNC和VSYNC比较眼熟。事实上,LTDC的HV模式的工作原理和VGA信号的原理是高度一致的。只是LTDC传输的是数字信号而已。这也是我们使用LTDC产生VGA信号的理论基础。
我们来看LTDC的信号时序图(HV模式):
咋看一下似乎跟VGA信号的时序完全不同,其实仔细分析就会发现。其工作原理跟VGA的工作原理是完全一致的,只是这张图中把SYNC PULSE画到了前面,所以只是看起来有些不一致。
所以我们只需要将LTDC控制器的参数时序调整到与期望的VGA信号时序一致即可生成准确的VGA同步信号。接下来的问题是,我们使用那个信号格式?回到那张常用的VGA信号格式表,可以看到,大部分的信号的频率都是非整数倍,而生成非整数倍的信号是非常费劲的一件事,需要我们在STM32的时钟配置上做出较大的妥协才行。所以,最适合的信号就是这个:
40MHz的信号是一个非常容易实现的整数。然后800x600@60Hz的分辨率和刷新率也都比较合适。
然后我们可以查看这个信号格式的具体参数:
我们需要通过这些参数我们来配置STM32H750的LTDC控制器。这里推荐通过CubeMX配置,方便而且不容易出错:
LTDC的其他的配置与正常使用LCD屏时的配置相同,此处不再赘述。
控制信号满足要求了,接下来是显示内容的发送。LTDC发送的是数字信号,而VGA显示设备需要接收模拟信号。显然,我们需要一个DAC(数模转换器)来完成这个工作。
我们先看VGA物理接口的标准:
其中的HSYNC和VSYNC是同步信号,我们刚刚已经介绍了它,现在要关注的是被标记为RGB的Pin1,2,3三个引脚,这三个引脚正是用来发送对应的颜色数据的信号引脚。
我们注意到,信号在终端和源端是有75Ω的阻抗的。在简易模型中,我们可以认为就是信号对地有一个75Ω的电阻。然后信号的电压范围是00.7V。也就是我们需要把RGB通道的数字信号都转为00.7V的模拟信号,并通过这三条线传输出去。
我们可以使用电阻分压网络来实现RGB565数字信号到模拟信号的转换。这种方式成本低廉但是显示效果不是很理想。为了画质的提升,我们可以使用ADV7123这颗专用的VGA信号DAC来实现数字信号到模拟信号的转换。
相对于使用电阻网络实现数模转换。ADV7123需要一个额外的像素时钟信号来进行数据的同步,我们直接使用LTDC控制器输出的像素时钟信号即可。然后就没什么好说的了,根据ADV7123的数据表进行电路的设计即可,最终电路如下:
由于需要连接至外部VGA设备,考虑到可能带来的ESD损伤,这里在DAC和最终的VGA输出端子之前,我们额外添加一颗专用ESD保护芯片
至此,我们完成了输出VGA信号的全部准备工作。
USB
为了连接USB键盘,我们需要一个USB Host接口。这块儿其实没有什么好说的,网上有大把的资料。电气连接也比较简单。
由于STM32H750的USB接口相对比较脆弱,这里为了防护可能出现的短路和静电击穿情况,额外添加了专用的ESD防护芯片和USB短路保护芯片。
电源
考虑到ART-Pi本体的供电可能不足,此处添加了一个额外的供电电路,带有反接保护和过流保护,可以直接接受6~12V的输入电压来为ART-Pi和扩展板供电。
PCB设计
PCB直接使用ART-Pi的外形。需要注意的是,由于ART-Pi的LTDC接口是通过FPC座引出的,所以,扩展板的LTDC接口会使用FPC软排线于ART-Pi本体连接
最终设计效果图:
软件说明
本扩展板的设计思路是为实现一个类似ColorMixmate的类PC设备提供硬件基础(当然你也可以完全不按照我的设计思路来使用这个扩展板)。目前的Demo中,我实现了一个小型控制台,移植了一个命令行库,并嵌入了一个小型的BASIC解释器。在命令行环境中,你可以使用我内置的一些命令来实现挂载SD卡,切换文件路径,查看图片以及播放视频的功能。在BASIC环境中,你可以使用BASIC语言来进行编码。我在BASIC环境中实现了对GPIO的控制,所以你也可以使用BASIC来实现一些基本的GPIO操作。
Demo的代码是在trueStudio中开发的,完全开源,请跳转至附件下载。
shell环境的内置命令操作说明
- help
效果:列出所有支持的命令 - mount
效果:挂载SD卡。注意,在使用任何文件操作之间,必须先执行mount命令挂载SD卡 - clear
效果:清空屏幕 - ls
效果:列出当前目录下所有的文件 - cd [path]
效果:进入/退出目录。示例:进入test子目录:cd test
;返回根目录:cd /
;返回上一级目录:cd ..
- op [file]
效果:打开文件,目前只支持查看JPEG图片和播放MJPEG编码的AVI格式视频。
以数字开头的文件名需要用双引号括住
示例:打开图片123.jpg(注意引号不能少):op "123.jpg"
;打开视频aerith.avi:op aerith.avi
JPEG图片文件限制:不大于屏幕分辨率(800x600)
AVI视频文件限制:MJPEG编码,无音频,25FPS以下,分辨率不高于800x600 - basic
进入BASIC环境,注意,进入BASIC环境后不能返回命令行环境。
在命令行环境中添加自己的命令
首先,我们需要创建一个命令的入口函数,函数可以为以下类型中的一种:
main函数形式
使用此方式,一个函数定义的例子如下:
int func(int argc, char *agrv[])
{
printf("%dparameter(s)\r\n", argc);
for (char i = 1; i < argc; i++)
{
printf("%s\r\n", argv[i]);
}
}
然后,在函数外部使用宏注册命令:
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), testcmd, func, test);
第一个参数为固定形式,第二个参数为命令名称,即在命令行中执行的命令名称,第三个参数为命令入口函数名称,第四个参数为注释。
然后我们就可以在终端调用这个命令:
letter:/$ testcmd "hello world"
2 parameter(s)
hello world
普通C函数形式
使用此方式,shell会自动对参数进行转化处理,目前支持二进制,八进制,十进制,十六进制整形,字符,字符串的自动处理,例子如下:
int func(int i, char ch, char *str)
{
printf("input int: %d, char: %c, string: %s\r\n", i, ch, str);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC), func, func, test);
终端调用
letter:/$ func 666 'A' "hello world"
input int: 666, char: A, string: hello world
BASIC环境中的GPIO操作
当前Demo只实现了GPIO的输出功能。要操作某个GPIO之前,需要使用如下命令将对应的GPIO设置为输出模式:
PINMODE 2,1
第一个参数是GPIO的编号,第二个参数是模式,1表示输出模式。GPIO编号与真实的GPIO对应关系在host.c文件中被定义:
static const BASICPinDef supportedOutputPins[] = {
{2, GPIOH, GPIO_PIN_12},
{3, GPIOH, GPIO_PIN_11},
{4, GPIOA, GPIO_PIN_8},
{17, GPIOA, GPIO_PIN_15},
{22, GPIOH, GPIO_PIN_13},
{10, GPIOI, GPIO_PIN_3},
{9, GPIOI, GPIO_PIN_2},
{11, GPIOI, GPIO_PIN_1},
{5, GPIOH, GPIO_PIN_7},
{6, GPIOH, GPIO_PIN_9},
{13, GPIOB, GPIO_PIN_13},
{19, GPIOI, GPIO_PIN_7},
{26, GPIOI, GPIO_PIN_4},
};
如果想增加GPIO支持,也可以在此数组中添加。
设定输出模式后,就可以使用如下命令控制GPIO的输出状态
PIN 2,1
第一个参数是GPIO的编号,第二个参数是输出电平,0表示低电平,1表示高电平
成品效果图展示
PCB空板图
焊接成品图
安装图
基本命令行环境
显示图片
播放视频
BASIC环境
通过BASIC代码控制GPIO
设计图
BOM
ID | Name | Designator | Footprint | Quantity |
---|---|---|---|---|
1 | X05A20L40T | ALIENTEK-RGB | FFC-SMD_40P-P0.50_X05A20L40T | 1 |
2 | ADV7123KSTZ140-RL | U1 | LQFP-48_L7.0-W7.0-P0.50-LS9.0-TL | 1 |
3 | LED-0805_R | USB-FAULT | LED0805_RED | 1 |
4 | SMD2016B150TF | F1 | F2016 | 1 |
5 | LM285DR-1-2 | U7 | SOIC-8_L4.9-W3.9-P1.27-LS6.0-BL | 1 |

评论