tag 标签: vga接口

相关博文
  • 热度 14
    2013-12-7 11:31
    4832 次阅读|
    1 个评论
    利用 FPGA 控制 VGA 接口来使显示器显示彩条纹 最近一直在调关于通过VGA接口来控制显示器的程序,今天终于调试出结果来了,赶紧上来与大家分享一下。 1 、VGA显示原理 常见的彩色显示器一般由阴极射线管(CRT)构成,彩色由GRB(Green Red Blue)基色组成。显示采用逐行扫描的方式解决,阴极射线*发出电子束打在涂有荧光粉的荧光屏上,产生GRB基色,合成一个彩色像素。扫描从屏幕的左上方开始,从左到右,从上到下,逐行扫描,每扫完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,CRT对电子束进行消隐,每行结束时,用行同步信号进行行同步;扫描完所有行,用场同步信号进行场同步,并使扫描回到屏幕的左上方,同时进行场消隐,并预备进行下一次的扫描。VGA显示原理图如图1所示。 在本文中,FPGA 通过串联电阻直接驱动 5 个 VGA 信号。每个颜色信号串一个电阻,每位的颜色信号分别是 VGA_RED,VGA_GREEN,VGA_BLUE。每个电阻与终端的 75 欧电缆电阻相结合,确保颜色信号保持在VGA规定的0V~0.7V之间。VGA_HSYNC 和VGA_VSYNC 信号使用 LVTTL 或 LVCMOS3I/O 标驱动电平。通过VGA_RED,VGA_GREEN,VGA_BLUE 置高或低来产生 8 种颜色。实际应用中,VGA_RED,VGA_GREEN 和 VGA_BLUE 可以接到 DAC 的输出,每个 DAC 用 8 bit 或更多的比特控制,3 条色彩控制线根据DAC 输出的电压大小配合实现更多种颜色的显示。VGA 显示的原理是利用水平扫描信号和竖直信号实现二维平面的像素扫描显示,以 640×480 像素的扫描显示示意图为例,当水平扫描信号 VGA_HSYNC 信号为高时,VGA 显示器从左向右依次扫描当前行的 640 个像素点。每扫描完一行,VGA_HSYNC 信号电平拉低,水平扫描位置回到最左端。 图1 VGA显示基本原理图 2 、VGA信号时序 普通的VGA显示器,其引出线共含5个信号:G,R,B三基色信号;HS:行同步信号;VS:场同步信号。     对于5个信号的时序驱动,以及VGA显示器,要严格遵循“VGA工业标准”,即640*480*60Hz模式。通常我们用的显示器都满足工业标准,因此设计VGA控制器是要参考显示器的技术规格。图2为VGA行扫描、场扫描的时序图。 图2 VGA行扫描、场扫描时序   由于本文采用的是640*480且刷新频率为60Hz显示模式,即显示器每秒扫描60场,而VGA在实际工作时并不是每行扫描640个点,每场扫描480行,而是每行800个点,每场525行,这是因为有行消隐和场消隐的存在的缘故,其中行消隐后沿为Tb+Tc=40+8=48个时钟周期,行消隐前沿为Te+Tf=8+8=16个时钟周期,场消隐后沿为Tb+Tc=25+8=33个时钟周期,行消隐前沿为Te+Tf=8+2个时钟周期,“消隐”的意思是指使显示器信号消失不见,所以在这段时间内不能有R,G,B信号输入,否则屏幕不会显示(本人就是在这儿出现了错误,下面会提到),用于有效显示的区域是640*480,所以才有了本段开头的模式。这样点像素的频率为:800*525*60=25.175MHz。由于采用的FPGA开发板为50MHz的系统时钟,所以需要对其进行2分频,然后按时序要求输出行、场同步信号即可。 但是在实际操作中我按照行、场信号时序要求输出了结果,也仍然还是不能调试通过,整个屏依然是无视频信号输入。于是我用signal tap Ⅱ进行实时观测,发现行时序信号(HS_OUT),与场时序信号输出(VS_OUT)与驱动时序要求完全一致,但是结果却无法显示。后来我就找到参考书按照参考书给出的程序代码一行一行的敲进去,最后却可以显示,通过使用signal tap Ⅱ实时观测信号输出,发现除了RGB信号外,其余的完全一样,那么问题肯定就出在R、G、B信号上,通过对比发现,我在所有的时刻均将R/G/B信号输出高电平,目的是想让整个屏都显示白色,因为我认为既然在固定的640*480这个区域内给予信号输入屏幕都会有显示,那么对于整个像素周期均给予输入,那么肯定也会有显示啊。但是事实上我是错的,原因就在于上一段中提到的行、场消隐的原因。即在消隐阶段不能有视频信号输入,也就是说在这一段内R/G/B必须均为低电平,只有在行数据有效区、长数据有效区的两个Td(即640*480的区域)同时满足的区域内才能给予视频信号输入,即R/G/B才能有输入,而我恰好违反了这个原则,在弄清原因之后,我修改了代码,结果可以屏幕顺利显示出我所要的结果。颜色显示组合为: R G B Resulting color 0 0 0 Black(黑色) 0 0 1 Blue(蓝色) 0 1 0 Green(绿色) 0 1 1 Cyan(靛色) 1 0 0 Red(红色) 1 0 1 Magenta(紫色) 1 1 0 Yellow(黄色) 1 1 1 White(白色) 具体代码与结果如下: library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; -- here we use the 640*480@60Hz screen_display mode,but there are --horizion_blacking(48back+16front), --vertical_blacking(33+10) and syn_time(96h,2v) time so the time counter is -- horizon_cnt=800(96+48+640+16),vertical_cnt=525(2+33+480+10),and --clk=60*800*525=25MHz(25174800Hz) entity VGA_control is       port(              clk50: in std_logic;              R: out std_logic;              G: out std_logic;              B: out std_logic;              hs_out: out std_logic;              vs_out: out std_logic       ); end entity;   architecture control of VGA_control is signal h_cnt,v_cnt: integer range 0 to 799; signal clk : std_logic;   begin clk_devide: process(clk50)       --according to VGA standard and the --analysis before,the frequency of clk should be 25MHz       begin              if(rising_edge(clk50)) then                     clk=not clk;              end if;       end process;       process(clk)       begin                  if (rising_edge(clk)) then                     if h_cnt=799 then                            h_cnt=0;                     else                            h_cnt=h_cnt+1;                     end if;              end if;          end process;       process(clk,h_cnt)              begin              if(clk'event and clk='1') then                     if((h_cnt=0) and (h_cnt96)) then                            hs_out='0';                     end if;                     if(h_cnt=96) and (h_cnt=799) then                            hs_out='1';                     end if;              end if;       end process;       process(clk,h_cnt)              begin              if (rising_edge(clk)) then    --由于要先进行行扫描,在进行列扫描所--以,必须行计数器满800后列计数器才能加1                     if(h_cnt=799) then                            if v_cnt=524 then                                   v_cnt=0;                            else                                   v_cnt=v_cnt+1;                            end if;                     end if;              end if;          end process;       process(clk,v_cnt)       begin       if(rising_edge(clk))then—产生              if(v_cnt=0) and (v_cnt2) then                     vs_out='0';              end if;              if(v_cnt=2) and (v_cnt525) then                     vs_out='1';              end if;       end if;       end process;       process(clk)       begin              if(rising_edge(clk)) then       --竖条纹颜色输出                     if (h_cnt=223) and (h_cnt=143) and (v_cnt=514) and (v_cnt=34)then                            R='0';                              G='0';                            B='1';                     elsif (h_cnt=303) and (h_cnt=223) and (v_cnt=514) and (v_cnt=34)then                            R='0';                            G='1';                            B='0';                     elsif (h_cnt=383) and (h_cnt=303) and (v_cnt=514) and (v_cnt=34)then                            R='0';                            G='1';                            B='1';                     elsif (h_cnt=463) and (h_cnt=383) and (v_cnt=514) and (v_cnt=34)then                            R='1';                            G='0';                            B='0';                     elsif (h_cnt=543) and (h_cnt=463) and (v_cnt=514) and (v_cnt=34)then                            R='1';                            G='0';                            B='1';                     elsif (h_cnt=623) and (h_cnt=543) and (v_cnt=514) and (v_cnt=34)then                            R='1';                            G='1';                            B='0';                     elsif (h_cnt=703) and (h_cnt=623) and (v_cnt=514) and (v_cnt=34)then                            R='1';                            G='1';                            B='1';                      elsif (h_cnt=783) and (h_cnt=703) and (v_cnt=514) and (v_cnt=34)then                            R='0';                            G='0';                            B='0';                     else                            R='0';                            G='0';                            B='0';                     end if;              end if;       end process; end architecture; 另外读者可以在颜色控制模块修改参数来进行条纹间隔大小修改,也可以产生方格等,这些有读者自己完成。
  • 热度 17
    2012-8-28 20:29
    1759 次阅读|
    0 个评论
    不知大家有没有注意到,在使用VGA接口的时候,通常RGB三根线上都会接上各种各样大小的电阻,这是为什么呢? 在讨论这个问题的时候,大家要明白VGA显示的是模拟信号,而非数字信号。那么在设计中又是怎样将数字信号转化为模拟信号的呢? 大家先看下面这张图片: 从图中可以看到,这是一个标准的VGA接口。RGB三端都接了一个270欧的电阻,这个电阻是起保护作用的,至于该接一个多大的电阻在此就不讨论了,有兴趣的朋友可以自行研究。不同的场合所接保护电阻的大小各一,在很多情况下通常接的是一个75欧的电阻,比如电视机里面通常接的就是这种。好了,言归正传,刚才我说VGA显示的模拟信号,可能有些同学会不明白,明明我们在设计的时候对RGB赋值的时候是数字信号呀,1或者0。这似乎有点自相矛盾吧? 答案是否定的,其实信号在输出的时候就已经是模拟信号了,也就是通常所说的IO口电压。说到这里,想必大家已经晃然大悟了吧! 哈哈 ------------------------------------------------------------------------------------------------------------------------------------------------- ****************************************************************************************************************** -------------------------------------------------------------------------------------------------------------------------------------------------- 好了,下面我们再看另外一张图:   或者很多人从来就没对此用法持怀疑态度吧!   其中G、B端都各引出了三根线,R却只引出了两根线,其中这就是我们通常所用来显示256色的(图一是8色)。这一点需要注意一下,RGB各引出几根线可以自行调节,并没有硬件的规定。假如在设计的时候你计为B(蓝色)不重要,你可以只引出一根线也是可行的,在这一点其灵活性是很强的。 那么数字信号又是怎样转换成模拟信号的呢? 呵呵,这就需要计算咯。比如IO的输出电压为3V,在设计中对B 的赋值为“101”。那么转换成模拟信号后其电压是多少呢? 其实这就是简单的分压原理的应用啦! V(B)=3* + 3* =0.52(V),这就是数字信号"101"转换为模拟信号的值啦!V(R)、V(G)原理同上。 说到这里,也说得差不多了吧 其大致的原理也就是这些,这里只是粗描淡写的描述了一下,关于VGA接口其实是一门很大的学问,读者需深究的话可自行查阅资料。   注:初写博文,可能会有很多不正确的地方,望大家指出来,日后加以改正;若觉得还可以的话,请大家继续肯定。
相关资源