Graphics STM32上的VGA像素分组

Graphics STM32上的VGA像素分组,graphics,arduino,stm32,pixel,vga,Graphics,Arduino,Stm32,Pixel,Vga,我有一些代码可以通过VGA在屏幕上显示一个像素,但我有点不明白如何在屏幕上设置多个像素。我为垂直同步和水平同步设置了两个计时器,然后使用V-Sync中断,我设置了一个标志,以允许PA8根据我在计时器通道上设置的设置比较值在正确的时间切换和输出像素。STM32f103c8还超频至128MHz。代码如下: #include "Arduino.h" //640x480 at 60Hz static volatile int vflag = 0; void setup() { #define FL

我有一些代码可以通过VGA在屏幕上显示一个像素,但我有点不明白如何在屏幕上设置多个像素。我为垂直同步和水平同步设置了两个计时器,然后使用V-Sync中断,我设置了一个标志,以允许PA8根据我在计时器通道上设置的设置比较值在正确的时间切换和输出像素。STM32f103c8还超频至128MHz。代码如下:

#include "Arduino.h"

//640x480 at 60Hz
static volatile int vflag = 0;

void setup() {

#define FLASH_ACR (*(volatile uint32_t*)(0x40022000))
FLASH_ACR = 0b110010; //enable flash prefetch and wait state to increase stability at higher freq

pinMode(PA0, PWM); //31,468.75Hz (Horizontal Sync) (Channel 1)
Timer2.pause();
Timer2.setOverflow(4067); //reload register value 
Timer2.setPrescaleFactor(1); //number that divides main clock 
Timer2.setCompare(1, 488); //12% duty cycle (Syncpulse/Wholeline) 
Timer2.setCompare(2, 2000); //0-4067 = vertical line going left or right respectively
Timer2.attachInterrupt(2, TRIGGER);
Timer2.refresh();
Timer2.resume();

pinMode(PA6, PWM); //60Hz (Vertical Sync) (Channel 1)
Timer3.pause();
Timer3.setOverflow(4183); //reload register value 
Timer3.setPrescaleFactor(510); //number that divides main clock 
Timer3.setCompare(1, 16); //0.38% duty cycle (Syncpulse/Wholeframe) 
Timer3.setCompare(2, 2000); //0-4183 = horizontal line going up or down respectively
Timer3.attachInterrupt(2, TRIGGER2); 
Timer3.refresh();
Timer3.resume();

pinMode(PA8, OUTPUT); //need to set PinMode in order for the ODR register to work

}

void loop() {

}

void TRIGGER(){
if(vflag==1){ 
__asm__ volatile (
"ldr r0, =(0x4001080C) \n\t" //GPIOA base address is 0x40010800 and ODR offset is 0x0C
"ldr r1, =(1<<8) \n\t" //turn on PA8
"ldr r2, =0 \n\t" //turn off PA8 

"str r1, [r0] \n\t" //turn on PA8
"str r2, [r0] \n\t" //turn off PA8

);
vflag = 0; //we set the vflag back to zero when were done outputing pixels.
}
}
#包括“Arduino.h”
//60Hz时为640x480
静态易失性int vflag=0;
无效设置(){
#定义FLASH_ACR(*(易失性uint32_t*)(0x40022000))
FLASH_ACR=0b110010;//启用FLASH预取和等待状态以提高更高频率下的稳定性
引脚模式(PA0,PWM);//31468.75Hz(水平同步)(通道1)
Timer2.pause();
Timer2.setOverflow(4067);//重新加载寄存器值
Timer2.setPrescaleFactor(1);//划分主时钟的数字
Timer2.setCompare(1488);//12%占空比(同步脉冲/全行)
Timer2.setCompare(22000);//0-4067=分别向左或向右的垂直线
定时器2.连接中断(2,触发器);
Timer2.refresh();
Timer2.resume();
pinMode(PA6,PWM);//60Hz(垂直同步)(通道1)
Timer3.pause();
Timer3.setOverflow(4183);//重新加载寄存器值
Timer3.setPrescaleFactor(510);//划分主时钟的数字
Timer3.setCompare(1,16);//0.38%占空比(同步脉冲/全帧)
Timer3.setCompare(22000);//0-4183=分别向上或向下的水平线
定时器3.连接中断(2,触发器2);
Timer3.refresh();
Timer3.resume();
pinMode(PA8,OUTPUT);//需要设置pinMode才能使ODR寄存器工作
}
void循环(){
}
无效触发器(){
如果(vflag==1){
__反复无常(
“ldr r0,=(0x4001080C)\n\t”//GPIOA基址为0x40010800,ODR偏移量为0x0C

“ldr r1,=(1我不为STM32编码,因此即使代码对我来说也是陌生的,但听起来像是用定时器对单个像素进行硬编码…并通过一些GPIO生成VGA信号。这种方法的组合对于可编程图形来说是有问题的

我正在使用AVR32(UC3A,时钟比你的慢得多)制作VGA图像,使用:

  • 屏幕缓冲区(视频RAM)

    简单地说,我将整个屏幕图像存储在MCU内存中。因此,您只需更改其内容,而无需更改VGA输出代码

    问题是您需要有足够的内存来存储图像(编码方式可以直接传输到VGA接口)。我使用的AVR32具有16+32+32 KB的RAM,但大多数MCU的RAM要少得多(静态图像可以存储在EPROM中,但无法更改图像输出)。因此,如果您没有足够的低分辨率来容纳内存或向系统中添加外部内存

  • 使用集成硬件外围设备生成VGA信号

    我有更多版本的VGA信号生成功能:

    • SDRAM…使用单片机的SDRAM接口
    • SMC…使用MCU的SMC接口
    • SSC…使用同步串行接口
    这一切归结为将屏幕缓冲区复制到IO接口,然后在硬件端将使用的MCU引脚组合成VGA信号

    为了提高速度,您可以使用DMA

    除此之外,您还需要生成同步信号,仅此而已

    因此,请查看您的MCU数据表,找到能够以VGA点时钟速度同步传输至少3位数据(R、G、B)的接口。时钟越接近VGA点时钟越好(因为某些VGA显示器和LCD不能承受太大的差异)

    同步信号可以硬编码,甚至可以在视频ram中编码

    最快的是使用串行接口,但输出仅为B&W而不是RGB(除非您有3个SSC单元/通道),但是您可以一次发送整个8/16/32像素,或者直接通过DMA发送,这样MCU就有时间处理其他内容,而且所需的VRAM也要少得多

    我最喜欢的是SDRAM接口(仅使用其数据总线)

  • 这里是来自矿山系统的图像:

    矿井互连如下所示(使用MCU SDRAM接口版本):

    功能
    picu copy
    仅将硬编码图像复制到VRAM中

    函数
    VGA\u screen()
    以无休止的循环创建VGA信号,因此其他任务必须编码为ISR或硬编码为暂停代码或在单个帧之间(但是这对我的设置要求很高,因为我的MCU时钟很小,所以没有太多空间进行其他工作)。VRAM编码为16色(每像素4位)

    亮度应该只为R、G、B增加一些电压,使用很少的电阻器和二极管,但是在HW侧实现了它,我有这个电路(仅8种颜色):

    二极管必须快,具有相同的势垒电压,且电容为1nF。这是为了避免由于使用的接口数据总线定时而导致图像闪烁。此外,如果将来添加二极管,则需要其亮度。有关更多信息,请参阅此处的R2R电流问题:


    感谢您的详尽回答,我想总结一下,以确保我了解这是如何做到的。要输出像素,请先将它们放入阵列中,然后将它们复制到ram中,以便硬件外围设备可以访问它们。然后(通过查看for循环),你把像素一个接一个地放入SDRAM地址,每次递增。现在,我不喜欢颜色,我想要最简单的实现,所以黑白都可以。你说这一切归结为以像素时钟的速度将像素数据输出到硬件接口。既然我已经设置了H-sync和V-sync带定时器的信号,设置第三个定时器(在我的例子中是25.175MHz)并每0.0397微秒(1/2517500)触发一次中断来设置每个像素是否正确?还是我忽略了什么
    VGA <-  AT32UC3A0512
     R      PX10 (EBI_D0)
     G      PX09 (EBI_D1)
     B      PX08 (EBI_D2)
     Bright PX07 (EBI_D3)*
     HS     PA03
     VS     PA04
    
             8 4 2 1
    Brightness B G R