原创 【原创】基于Nios II的VGA字符显示控制

2008-12-2 15:16 9381 11 17 分类: FPGA/CPLD

Nios II嵌入式系统硬件设计(四)


 


在上一篇文章 基于VerilogVGA显示控制 中介绍了使用纯硬件(Verilog)方法实现的VGA显示控制,不过上述方法只能显示静态的图像,不能更改,也不能显示字符,在本文中介绍一种基于Nios IIVGA字符显示控制,可以显示所有ASCII字符,显示图像可更改,便把分辨率改成了32*24


模块框图如下:


点击看大图


VGA控制器的设计和显存(RAM)的设计与 基于VerilogVGA显示控制 中的基本相同,只是显存用双口RAM替换了单口ROM,以便于修改显示内容。关键在于Nios II处理器中的设计。


       按照正常流程设计,需要将显存(RAM)加上Avalon slave接口挂到Avalon的互联结构上,在本设计中,为了偷懒,没有编写Avalon slave接口,直接用SOPCPIO与显存(RAM)连接,通过直接读写PIO来改变显存中存储的颜色值。


       为了在LCD上显示各种字符,需要在Nios II的存储器中存储所有字符的字模表。


35cd2afb-6450-43f3-b299-7588e850ddb4.jpg


unsigned char CHTAB[][5]=<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


{


{0x00, 0x00, 0x00, 0x00, 0x00}, //" "=00h


{0x00, 0x00, 0x<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />4F, 0x00, 0x00}, //"!"=01h


{0x00, 0x07, 0x00, 0x07, 0x00}, //"""=02h


{0x14, 0x7F, 0x14, 0x7F, 0x14}, //"#"=03h


{0x24, 0x2A, 0x7F, 0x2A, 0x12}, //"$"=04h


{0x23, 0x13, 0x08, 0x64, 0x62}, //"%"=05h


{0x36, 0x49, 0x55, 0x22, 0x50}, //"&"=06h


{0x00, 0x05, 0x03, 0x00, 0x00}, //"'"=07h


{0x00, 0x1C, 0x22, 0x41, 0x00}, //"("=08h


{0x00, 0x41, 0x22, 0x1C, 0x00}, //")"=09h


{0x14, 0x08, 0x3E, 0x08, 0x14}, //"*"=0Ah


{0x08, 0x08, 0x3E, 0x08, 0x08}, //"+"=0Bh


{0x00, 0x50, 0x30, 0x00, 0x00}, //","=0Ch


{0x08, 0x08, 0x08, 0x08, 0x08}, //"-"=0Dh


{0x00, 0x60, 0x60, 0x00, 0x00}, //"."=0Eh


{0x20, 0x10, 0x08, 0x04, 0x02}, //"/"=0Fh


{0x3E, 0x51, 0x49, 0x45, 0x3E}, //"0"=10h


{0x00, 0x42, 0x7F, 0x40, 0x00}, //"1"=11h


{0x42, 0x61, 0x51, 0x49, 0x46}, //"2"=12h


{0x21, 0x41, 0x45, 0x4B, 0x31}, //"3"=13h


{0x18, 0x14, 0x12, 0x7F, 0x10}, //"4"=14h


{0x27, 0x45, 0x45, 0x45, 0x39}, //"5"=15h


{0x3C, 0x4A, 0x49, 0x49, 0x30}, //"6"=16h


{0x01, 0x01, 0x79, 0x05, 0x03}, //"7"=17h


{0x36, 0x49, 0x49, 0x49, 0x36}, //"8"=18h


{0x06, 0x49, 0x49, 0x29, 0x1E}, //"9"=19h


{0x00, 0x36, 0x36, 0x00, 0x00}, //":"=1Ah


{0x00, 0x56, 0x36, 0x00, 0x00}, //";"=1Bh


{0x08, 0x14, 0x22, 0x41, 0x00}, //"<"=1Ch


{0x14, 0x14, 0x14, 0x14, 0x14}, //"="=1Dh


{0x00, 0x41, 0x22, 0x14, 0x08}, //">"=1Eh


{0x02, 0x01, 0x51, 0x09, 0x06}, //"?"=1Fh


{0x32, 0x49, 0x79, 0x41, 0x3E}, //"@"=20h


{0x7E, 0x11, 0x11, 0x11, 0x7E}, //"A"=21h


{0x41, 0x7F, 0x49, 0x49, 0x36}, //"B"=22h


{0x3E, 0x41, 0x41, 0x41, 0x22}, //"C"=23h


{0x41, 0x7F, 0x41, 0x41, 0x3E}, //"D"=24h


{0x7F, 0x49, 0x49, 0x49, 0x49}, //"E"=25h


{0x7F, 0x09, 0x09, 0x09, 0x01}, //"F"=26h


{0x3E, 0x41, 0x41, 0x49, 0x7A}, //"G"=27h


{0x7F, 0x08, 0x08, 0x08, 0x7F}, //"H"=28h


{0x00, 0x41, 0x7F, 0x41, 0x00}, //"I"=29h


{0x20, 0x40, 0x41, 0x3F, 0x01}, //"J"=2Ah


{0x7F, 0x08, 0x14, 0x22, 0x41}, //"K"=2Bh


{0x7F, 0x40, 0x40, 0x40, 0x40}, //"L"=2Ch


{0x7F, 0x02, 0x0C, 0x02, 0x7F}, //"M"=2Dh


{0x7F, 0x06, 0x08, 0x30, 0x7F}, //"N"=2Eh


{0x3E, 0x41, 0x41, 0x41, 0x3E}, //"O"=2Fh


{0x7F, 0x09, 0x09, 0x09, 0x06}, //"P"=30h


{0x3E, 0x41, 0x51, 0x21, 0x5E}, //"Q"=31h


{0x7F, 0x09, 0x19, 0x29, 0x46}, //"R"=32h


{0x26, 0x49, 0x49, 0x49, 0x32}, //"S"=33h


{0x01, 0x01, 0x7F, 0x01, 0x01}, //"T"=34h


{0x3F, 0x40, 0x40, 0x40, 0x3F}, //"U"=35h


{0x1F, 0x20, 0x40, 0x20, 0x1F}, //"V"=36h


{0x7F, 0x20, 0x18, 0x20, 0x7F}, //"W"=37h


{0x63, 0x14, 0x08, 0x14, 0x63}, //"X"=38h


{0x07, 0x08, 0x70, 0x08, 0x07}, //"Y"=39h


{0x61, 0x51, 0x49, 0x45, 0x43}, //"Z"=3Ah


{0x00, 0x7F, 0x41, 0x41, 0x00}, //"["=3Bh


{0x02, 0x04, 0x08, 0x10, 0x20}, //"\"=3Ch


{0x00, 0x41, 0x41, 0x7F, 0x00}, //"]"=3Dh


{0x04, 0x02, 0x01, 0x02, 0x04}, //"^"=3Eh


{0x40, 0x40, 0x40, 0x40, 0x40}, //"_"=3Fh


{0x01, 0x02, 0x04, 0x00, 0x00}, //"`"=40h


{0x20, 0x54, 0x54, 0x54, 0x78}, //"a"=41h


{0x7F, 0x48, 0x44, 0x44, 0x38}, //"b"=42h


{0x38, 0x44, 0x44, 0x44, 0x28}, //"c"=43h


{0x38, 0x44, 0x44, 0x48, 0x7F}, //"d"=44h


{0x38, 0x54, 0x54, 0x54, 0x18}, //"e"=45h


{0x00, 0x08, 0x7E, 0x09, 0x02}, //"f"=46h


{0x0C, 0x52, 0x52, 0x4C, 0x3E}, //"g"=47h


{0x7F, 0x08, 0x04, 0x04, 0x78}, //"h"=48h


{0x00, 0x44, 0x7D, 0x40, 0x00}, //"i"=49h


{0x20, 0x40, 0x44, 0x3D, 0x00}, //"j"=4Ah


{0x00, 0x7F, 0x10, 0x28, 0x44}, //"k"=4Bh


{0x00, 0x41, 0x7F, 0x40, 0x00}, //"l"=4Ch


{0x7C, 0x04, 0x78, 0x04, 0x78}, //"m"=4Dh


{0x7C, 0x08, 0x04, 0x04, 0x78}, //"n"=4Eh


{0x38, 0x44, 0x44, 0x44, 0x38}, //"o'=4Fh


{0x7E, 0x0C, 0x12, 0x12, 0x0C}, //"p"=50h


{0x0C, 0x12, 0x12, 0x0C, 0x7E}, //"q"=51h


{0x7C, 0x08, 0x04, 0x04, 0x08}, //"r"=52h


{0x58, 0x54, 0x54, 0x54, 0x64}, //"s"=53h


{0x04, 0x3F, 0x44, 0x40, 0x20}, //"t"=54h


{0x3C, 0x40, 0x40, 0x3C, 0x40}, //"u"=55h


{0x1C, 0x20, 0x40, 0x20, 0x1C}, //"v"=56h


{0x3C, 0x40, 0x30, 0x40, 0x3C}, //"w"=57h


{0x44, 0x28, 0x10, 0x28, 0x44}, //"x"=58h


{0x1C, 0xA0, 0xA0, 0x90, 0x7C}, //"y"=59h


{0x44, 0x64, 0x54, 0x4C, 0x44}, //"z"=5Ah


{0x00, 0x08, 0x36, 0x41, 0x00}, //"{"=5Bh


{0x00, 0x00, 0x77, 0x00, 0x00}, //"|"=5Ch


{0x00, 0x41, 0x36, 0x08, 0x00}, //"}"=5Dh


{0x02, 0x01, 0x02, 0x04, 0x02}, //"~"=5Fh


{0x7F, 0x7F, 0x7F, 0x7F, 0x7F} //" "=60h


};


显示像素函数,负责向显存中写入指定行和列的颜色值,这里通过读写PIO来进行操作。


void Pixel(unsigned char row, unsigned char column, unsigned char color)


{


unsigned short offset;


offset = row * 32 + column;//根据行列数值计算显存中的便宜地址


IOWR_ALTERA_AVALON_PIO_DATA(WRADDRESS_BASE,offset);//输出显存地址


IOWR_ALTERA_AVALON_PIO_DATA(DATA_BASE,color);//输出改点的颜色值


IOWR_ALTERA_AVALON_PIO_DATA(WREN_BASE,1);


IOWR_ALTERA_AVALON_PIO_DATA(WRCLOCK_BASE,1);//时钟上升沿写入数据


IOWR_ALTERA_AVALON_PIO_DATA(WRCLOCK_BASE,0);


IOWR_ALTERA_AVALON_PIO_DATA(WREN_BASE,0);


}


清屏函数,是全屏显示成黑色


void ClearScreen(void)


{


unsigned char p,q;


for(p = 0; p < 24; p++ )


{


    for(q = 0; q < 32; q++)


    {


        Pixel(p,q,0);


    }


}


}


字符显示函数


void Character(unsigned char row, unsigned char column, unsigned char *CH, unsigned char frontcolor, unsigned char backcolor)


{


unsigned char i, h, color;


for(h = 0; h < 5; h ++) //遍历字模占用的5个字节


{


for(i = 0; i < 8; i ++) //遍历字模中每个字节的8bit


{


if(1 == ((*(CH + h) >> i) & 1))


{


color = frontcolor; //如果某bit1,则显示前景颜色


}


else


{


color = backcolor; //如果某bit0,则显示背景颜色值


}


Pixel(row + i, column + h, color); //显示像素


}


}


}


Main函数,首先清屏,然后在屏幕上分三行显示0123456789ABCDEFGH


Int main()


{


ClearScreen();


 Character(0,0,CHTAB[16],7,0);//blue first line


 Character(0,5,CHTAB[17],164,0);


 Character(0,10,CHTAB[18],56,0);//green


 Character(0,15,CHTAB[19],199,0);


 Character(0,20,CHTAB[20],192,0);//red


 Character(0,25,CHTAB[21],255,0);


 Character(8,0,CHTAB[22],63,0);//second line


 Character(8,5,CHTAB[23],248,0);


 Character(8,10,CHTAB[24],199,0);


 Character(8,15,CHTAB[25],56,0);


 Character(8,20,CHTAB[33],248,0);


 Character(8,25,CHTAB[34],182,0);


 Character(16,0,CHTAB[35],164,0);//third line


 Character(16,5,CHTAB[36],7,0);


 Character(16,10,CHTAB[37],248,0);


 Character(16,15,CHTAB[38],182,0);


 Character(16,20,CHTAB[39],255,0);


 Character(16,25,CHTAB[40],199,0);


 


 


  return 0;


}


下面是程序运行结果。


710e1b1f-b507-412a-9321-ccf7c328783f.jpg

文章评论6条评论)

登录后参与讨论

用户1767490 2014-8-10 21:39

写得好

用户269646 2010-4-21 22:24

你好,小弟初学fpga,想知道你上面的例子中的frontcolor是如何计算出来的,请赐教一二,小弟感激不尽。

用户513885 2009-6-26 11:06

你的显存是外挂的RAM吗?如果是是如何实现RAM控制的呢?谢谢!

用户1407990 2008-12-7 23:41

可否把整个项目共享出来呢,或者写一编怎么样用通过双口RAM把两者结合起来的文章呢?

用户1332143 2008-12-6 18:54

VGA时序产生是基于Verilog写的,Nios II是控制VGA显示的内容,两者通过双口RAM连接

用户1407990 2008-12-6 17:58

VGA的显示是用VERILOG写的?? 如果是用NIOSII的,怎么没看到有显示函数的? 如何把NIOSII和VERILOG写的模块连接起来呢?
相关推荐阅读
用户1332143 2009-08-16 21:47
时序电路亚稳态分析
这篇文章是我对电子设计中,亚稳态问题的一种分析和总结。文章通过对数字电路中器件的工作机制的介绍,引出亚稳态问题的发生机制。并通过对亚稳态问题发生机制的探讨,用以得到一种能够清楚地,有的放矢地解决亚稳态...
用户1332143 2009-08-16 10:52
【推荐】ADF4350配置软件下载
p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">  随着现代半导体工艺的不断发展, 几十纳米级的CMOS工艺给数字电路带来了很大的恩惠, 但对模拟...
用户1332143 2009-08-14 12:47
【原创】基于NiosII及FT245BM的USB接口设计
以前做的一个项目,FPGA接收AD采集数据后,通过串口发送回PC机,由于串口传输速率较低,对于实时性要求较高的场合不太适用,因此站长选用FT245BM芯片来实现USB接口传输,本文主要讲解FT245B...
用户1332143 2009-08-13 14:56
【原创】MAXII:UFM中晶振的使用
MAXII系列CPLD中带有UFM模块,本文主要讲解UFM中晶振的使用,具体内容请点击下面链接MAXII:UFM中晶振的使用...
用户1332143 2009-03-01 21:53
【原创】如何使用FPGA进行信号调制
       最近要做一个通信收发系统项目,以前对收发器的射频前段关注的比较多,而对基带部分的信号处理一直没有仔细研究。因此,正好借这个项目,熟悉整个基带部分的信号处理流程。       基带部分主要...
用户1332143 2009-02-27 21:56
寒假回来——FPGA市场评论
寒假在家里电脑不能上网,好久没来更新自己的博客了,首先感谢大家对我博客的支持。回来后马上开始了一个863项目,一直没有时间来写博客,今天总算有时间,上来看看。回来这段时间关注了下FPGA的相关新闻,发...
EE直播间
更多
我要评论
6
11
关闭 站长推荐上一条 /3 下一条