Nios II嵌入式系统硬件设计(四)
在上一篇文章 基于Verilog的VGA显示控制 中介绍了使用纯硬件(Verilog)方法实现的VGA显示控制,不过上述方法只能显示静态的图像,不能更改,也不能显示字符,在本文中介绍一种基于Nios II的VGA字符显示控制,可以显示所有ASCII字符,显示图像可更改,便把分辨率改成了32*24。
模块框图如下:
VGA控制器的设计和显存(RAM)的设计与 基于Verilog的VGA显示控制 中的基本相同,只是显存用双口RAM替换了单口ROM,以便于修改显示内容。关键在于Nios II处理器中的设计。
按照正常流程设计,需要将显存(RAM)加上Avalon slave接口挂到Avalon的互联结构上,在本设计中,为了偷懒,没有编写Avalon slave接口,直接用SOPC的PIO与显存(RAM)连接,通过直接读写PIO来改变显存中存储的颜色值。
为了在LCD上显示各种字符,需要在Nios II的存储器中存储所有字符的字模表。
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 ++) //遍历字模中每个字节的8个bit
{
if(1 == ((*(CH + h) >> i) & 1))
{
color = frontcolor; //如果某bit为1,则显示前景颜色
}
else
{
color = backcolor; //如果某bit为0,则显示背景颜色值
}
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;
}
下面是程序运行结果。
用户1767490 2014-8-10 21:39
用户269646 2010-4-21 22:24
用户513885 2009-6-26 11:06
用户1407990 2008-12-7 23:41
用户1332143 2008-12-6 18:54
用户1407990 2008-12-6 17:58