简介
这是一个用于嵌入式计算机的VGA和键盘接口模块,需要在监视器上输出文本。可连接VGA显示器、PS/2键盘,通过TTL串口作为VT100终端。它会立即启动,这样它就不会错过来自主机的消息。
虽然市面上有很多基于ARM的VGA项目,但这只是一个练习,看看如何使用低端的STM32F030F4(只有4K RAM和16K闪存)。
小型嵌入式微控制器通常不带有视频输出。这个项目的目的是设计一个低成本的邮票大小的模块,可以用来提供一个VGA文本显示在全640X400或640X480,并与PS/ 2键盘接口。该模块作为一个可嵌入的VT100终端通过串行端口到主机。它负责视频生成、关键时序问题以及简化嵌入式主机的驱动程序。主机只需要通过串口处理发送/接收字符和控制代码。
这是一个DIY项目,有现成的零件。它可以立即启动以捕捉控制台消息,并在3.3V下消耗25Ma的单色视频(不带PS/ 2键盘)。该模块足够小(0.7“x1.0”),并且便宜到足以嵌入到设计中。
640 x 400/480 VGA text mode使用25.175MHz像素时钟。大多数视频监视器可以容纳25MHz,这通常用于以太网,晶体/振荡器容易以低得多的价格获得。
在这个项目中有一点超频,所以YMMV。
过时钟分析
我已经测试了STM32 F030 SPI在25MHz的三个芯片与不同的日期代码。它在8位主模式下对SCK和MOSI信号工作良好。
我试图推断SPI18MHz对数据表的限制来自何处。APB外设STM32 F0值线合格,工作在48 MHz。数据表上的I/O(时钟到数据输出)的时间实际上非常紧,并且有足够的余量意味着更高的频率。
由于某些原因,SPI时钟频率为18MHz。
以下是我想发生的事情:有人从不同的产品线上复制数字。
下面是从他们的72MHz STM32 F10X线。72MHz对于SPI块来说可能太快了一点,所以它们将频率降低到36MHz。对于SCK时钟,SPI模块内还存在2的进一步划分。因此,最大数据速率是:PCLK/2=36MHZ/2=18MHz。
视频生成:
大多数其他VGA项目使用一个中等范围的ARM皮层M,具有更多的RAM和/或以较低的分辨率呈现输出。在一个问题上更容易忽略成本和浪费资源。我试图使用“价值”线STM32 F0作为成本原因,作为一个技术挑战。该部分可在0.44美元10元。
我的挑战是实现VT100终端的工作子集,同时使用高级语言模拟丢失的硬件,并在原始VT100的类似内存约束中工作。对于VT100兼容性验证,我使用的是标准的开源测试套件
最初我计划使用external SPI RAM as the frame buffer,对于一个完整的图形+彩色显示器,但我缩回,并尝试只与芯片资源的工作。这个部分中RAM的数量只有4KB,这不足以存储整个帧缓冲区。另一种方法是在每帧上以全分辨率(640x400或640x480)生成所有扫描线。
框图实际上与“非常相似”。它都是在STM32 F030F4微控制器内部实现的。
以上是典型用法示例的修改版本。MC6845 datasheet 、www.datasheetarchive.com/MC6845CP-datasheet.html
- ARM M0内核是“处理器”
- 内部RAM被用作保持字符缓冲器和扫描线缓冲器的“刷新RAM”。缓冲区用于解耦(快于实时)渲染过程和视频生成。
- 硬件定时器用于生成HS(水平同步),IRQ用于跟踪当前扫描行“刷新存储器地址”用于呈现、VS(垂直同步)生成和乒乓缓冲管理。
- DMA传输呈现扫描线从缓冲器到SPI作为“移位寄存器”
- 下面描述的固件渲染例程用于实现“ROM字符生成器”功能。
渲染过程
- 文本缓冲器用于存储要显示的字符。
- 对于每个扫描行,对于活动行中的每个字符
- 查找字体位图表中的对应行(n)
- 将位图复制到扫描线中
下面显示了生成的VGA同步和用于移出像素的SCK。启用(重命名为背景)是我使用它作为时间调整指南的活动显示区域。(它也被用作外部SPI RAM的门控信号,在本项目中不使用)。
下面显示了VSYNC信号:
固件具有16个CPU周期(在50MHz),以在25MHz处渲染8个视频数据像素。初步试验(初步试验)显示出比预期更好的,因为编译器在优化代码方面做得更好。对输出比较IRQ内的每个扫描行进行渲染。
我设置GPIO信号“渲染”之前,并清除后的渲染代码计时测量。每条32条扫描线需要16.41U。固件可以比视频输出更快地渲染。缓冲器用于解耦定时和移除额外的周期,否则将浪费在同步上。
该图显示了活动扫描线(32秒周期)上的活动。
1. 在HSYNC IRQ完成房屋管理和DMA缓冲管理之后,它设置了PANSV标志和出口。
1. PANSV关闭了较低优先级的IRQ,清除了自己的中断并进入WFI睡眠。
1. 输出比较IRQ从睡眠唤醒ARM并启动SPI DMA。延迟预补偿。这里不允许抖动,因为它们会影响视频质量。见
1. 当DMA正在从缓冲器生成当前扫描线的视频时,固件开始呈现下一扫描线。
1. IRQ退出和控制返回控制返回PendSV,重新启用较低优先级IRQ和退出。
1. 其余优先级较低的IRQ,驱动程序/应用程序代码可以运行,直到它们被HSYNC IRQ抢占为止。
在活跃扫描线中,大约1/3的CPU周期(在50MHz)可用于应用程序代码。与那些终端使用的相比,这仍然是相当值得尊敬的。
文本缓冲区
文本在IRQ中由文本缓冲区的2D数组呈现,在PC上实现类似于旧的“文本模式”。对于更高级的例程,将字符的值写入数组会自动打印出来。诸如滚动/清除操作之类的屏幕操作使用标准C库中的高度优化的存储器移动和填充函数在文本缓冲区阵列上工作。例如,MeMyVE()是一个智能内存复制例程,可以处理重叠的源/目的地,是完美的文本滚动。
光标由一个单独的任务模拟,该任务从数组中保存字符。它使用倒置的视频字符在原字符和光标之间周期性地交替。
串口与PS/2
IRQ实时要求:
- 串行端口在115200,字符可以到达每1/11520=868US一次。
- PS/2,一个比特可以到达每100U
在下一个字符到达之前,较高优先级的渲染代码就可以完成这两者。运行VT100仿真,它运行在115200 BPS顺利滚动文本,而不需要握手。这可以简化8位主机上的主机软件。
PS/ 2代码具有强大的错误恢复功能,支持PS/2键盘的热插拔。PS/2信号用肖特基二极管箝位,以保护臂I/O引脚免受过电压。
软件任务
该程序被组织成一系列在无事件驱动循环中运行的协作任务。由于所有任务共享同一堆栈,因此内存开销非常低。IRQ低级别驱动程序在后台运行,使用一组FIFO例程缓冲I/O进行缓冲。
- 串行传输流在PS2Sub任务()(从按键按下)和ANSIIZFSM()(从主机查询)之间共享。每个任务都可以在不被抢占的情况下发送完整的数据包。这样可以防止数据包相互损坏。
- CURSORYTASK()和ANSIIZFSM()共享视频输出。AsisifFSM在CursRoStaskTebug()绘制光标之前完成滚动/清除屏幕/文本更新。这防止了在滚动期间的视频伪影,并且实际上简化了程序结构。
Pinout:
样品应用电路:
RXD:连接到主机TTL串行输出
TXD:连接到主机TTL串行输入
- 只需连接绿色视频信号就可以获得旧的绿色文本。我初始化SPI,使其与LSB序列化,以镜像字体。
- 连接蓝色到引脚13(Bug GND)。此输出蓝色文本上的白色
- 白色的黑色文本被支持作为VT100控制代码的一部分。
引导带跳线用于从TTL串口更新固件。这使得为嵌入式设计更新固件变得更容易。
材料清单:
我在原型中试用过低成本的中文部件,它们也能工作。
项目github 地址
Github https://github.com/FPGA-Computer/STM32F030F4-VGA
包含所有软件源码和硬件电路图
|