可编程逻辑器件FPGACPLD课程设计 DE2115.docx

上传人:b****5 文档编号:8482887 上传时间:2023-01-31 格式:DOCX 页数:17 大小:64.24KB
下载 相关 举报
可编程逻辑器件FPGACPLD课程设计 DE2115.docx_第1页
第1页 / 共17页
可编程逻辑器件FPGACPLD课程设计 DE2115.docx_第2页
第2页 / 共17页
可编程逻辑器件FPGACPLD课程设计 DE2115.docx_第3页
第3页 / 共17页
可编程逻辑器件FPGACPLD课程设计 DE2115.docx_第4页
第4页 / 共17页
可编程逻辑器件FPGACPLD课程设计 DE2115.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

可编程逻辑器件FPGACPLD课程设计 DE2115.docx

《可编程逻辑器件FPGACPLD课程设计 DE2115.docx》由会员分享,可在线阅读,更多相关《可编程逻辑器件FPGACPLD课程设计 DE2115.docx(17页珍藏版)》请在冰豆网上搜索。

可编程逻辑器件FPGACPLD课程设计 DE2115.docx

可编程逻辑器件FPGACPLD课程设计DE2115

PLD期末课程设计NIOSII开发

 

姓名:

李超

学号:

PB10011049

邮箱:

lichao37@

 

第一章简介

1.1硬件开发

NIOSII硬件开发主要是通过使用Qsys构建NIOSII软核,软核主要包括以下几个部分:

1.NIOSIIProcessor

2.PLL

3.clock

4.sysid

5.sdramcontroller

6.LCD

7.timer

8.ps2

9.seg7

10.led

11.key

12.jtag_uart

其中使用了DE2-115SystemCD中官方范例的IP和alterauniversityprogram提供的IP。

1.2软件开发

NIOSII的软件开发部分主要实现了以下几个功能:

13.点亮LED

14.KEY中断

15.定时器中断

16.七段数码管

17.LCD显示字符

18.PS2键盘

19.PS2鼠标

1.3基本系统搭建

DE2-115板子上提供的时钟只有50MHz,利用PLL产生三路时钟,clk0为100MHz提供给CPU和需要高速时钟的模块,如:

SRAM、SDcard、Jtag_uart等;clk1为相移-65°的100MHz,提供给SDRAM;Mclk2为10MHz提供给那些不需要高速时钟的模块,如:

key,led,lcd,timerps2等。

这样就可以根据系统的需要来选择不同的时钟。

CPU选择NIOSII/f型,储存单元选择SDRAM。

第二章基本功能开发

2.1点亮LED

在Qsys中添加PIO模块,由于红色LED有18个,所以PIO模块中width选择18,direction选择output,其他不变,如下图所示。

编译、分配管脚等步骤后,在NIOSIIIDE中system.h可以看到关于LED的相关宏定义。

根据LED_BASE就可以读写相应寄存器,实现LED的打开和熄灭。

利用PIO读写函数实现了下面几个函数,用来控制LED。

voidled(inttemp)//根据temp的每一个bit决定么个LED的状态。

//如temp=5即0101,则第1个LED和第三个LED点亮,其他熄灭

{

IOWR_ALTERA_AVALON_PIO_DATA(LEDR_BASE,temp);

}

voidled_on(inti)//将第i个LED点亮。

{

inttemp=IORD_ALTERA_AVALON_PIO_DATA(LEDR_BASE);

IOWR_ALTERA_AVALON_PIO_DATA(LEDR_BASE,temp|1<

}

voidled_off(inti)//将第i个LED点亮。

{

inttemp=IORD_ALTERA_AVALON_PIO_DATA(LEDR_BASE);

IOWR_ALTERA_AVALON_PIO_DATA(LEDR_BASE,temp&(~(1<

}

voidled_toggle(inti)//将第i个LED的状态去反。

即由点亮变熄灭,由熄灭变点亮

{

if(tag[i]==0)//如果为熄灭

{

tag[i]=1;//点亮

led_on(i);

}

else//如果为点亮

{

tag[i]=0;//熄灭

led_off(i);

}

}

利用上述函数实现一个简单跑马灯,程序如下所示:

while

(1)

{

for(inti=0;i<8;i++)

{

usleep(100000);

led_on(17-i);

usleep(100000);

led_off(17-i);

}

}

2.2按键中断

在Qsys中添加PIO模块,由于按键有四个,所以width选择4,direction选择input,EdgeType选Falling,具体配置如下图所示。

key1按下时点亮LED8,key2按下时熄灭LED8,这样key1和key2就可以控制LED8的状态。

Key3按下时使LED9的状态翻转,依次熄灭、点亮。

key4按下时,7段数码管0和1显示0,即清零。

同时每个按键按下时,会在LCD上显示哪个按钮被按下。

按键中断初始化程序和中断服务程序如下所示:

/*

*按键中断服务程序

*/

voidkey_isr(void*context,alt_u32id)

{

volatileint*edge_capture_ptr=(volatilDeint*)context;

*edge_capture_ptr=IORD_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE);

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE,0xF);

//清中断边沿捕获寄存器

if(edge_capture==0x01)

{//key1

lcd_show_second_line("button1");

led_on(8);//点亮LED8

edge_capture=0x00;

}

elseif(edge_capture==0x02)

{//key2

lcd_show_second_line("button2");

led_off(8);//熄灭LED8

//IOWR(KEY_BASE,0x00,0xFD);

edge_capture=0x00;

}

elseif(edge_capture==0x04)

{//key3

led_toggle(9);//让LED9的状态取反

lcd_show_second_line("button3");

edge_capture=0x00;

}

elseif(edge_capture==0x08)

{//key4

count1=0;

lcd_show_second_line("button4");

SEG7_show(1,'0');//7段数码管0和1显示0,即清零。

SEG7_show(0,'0');

edge_capture=0x00;

}

else

{

printf("keyerror");

}

}

按键中断初始化程序

/*

*按键中断初始化程序

*/

voidkey_irq_init()

{

printf("initialkey");

void*edge_capture_ptr=(void*)&edge_capture;

IOWR_ALTERA_AVALON_PIO_IRQ_MASK(KEY_BASE,0xF);

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE,0);

alt_irq_register(KEY_IRQ,edge_capture_ptr,key_isr);

//alt_ic_isr_register(KEY_IRQ_INTERRUPT_CONTROLLER_ID,

//KEY_IRQ,

//key_isr,

//edge_capture_ptr,

//0x0);

}

2.3计数器中断

在Qsys中添加Timer,选择Full-featured特性,period选择1ms。

具体参数如下图所示:

由于Timer每1ms产生一个中断,这样在中断通过一个变量计数到1000,这样实现1000分频,即周期变成了1s。

在中断服务程序中实现了一个0到99计数的计数器,并且将数字显示中七段数码管0和1上,通过key4中断实现清零。

还实现了一个时钟,通过七段数码管显示当前时间的时、分、秒。

程序如下图所示:

/*

*计数器中断服务程序

*/

voidtimer_isr(void*context,alt_u32id)

{

//应答中断,将STATUS寄存器清零

IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_0_BASE,

~ALTERA_AVALON_TIMER_STATUS_TO_MSK);

TIMER_0_counter++;

if(TIMER_0_counter==1000)

{//即1000分频。

周期1s。

led_toggle(6);

//--------------------------seg2seg3seg4seg5seg6seg7显示当前时间的时:

分:

秒。

if(time1[0]==60)

{

time1[0]=0;

time1[1]++;//分钟加1

}

SEG7_show(7,time1[0]%10+'0');//显示秒

SEG7_show(6,time1[0]/10+'0');

time1[0]++;

if(time1[1]==60)

{

time1[1]=0;

time1[2]++;//时加1

}

SEG7_show(5,time1[1]%10+'0');//显示分钟

SEG7_show(4,time1[1]/10+'0');

if(time1[2]==24)

{

time1[2]=0;

}

SEG7_show(3,time1[2]%10+'0');//显示小时

SEG7_show(2,time1[2]/10+'0');

//---------------------------seg0seg1实现0到99循环基数,每秒加一

if(count1==100)

{

count1=0;

}

SEG7_show(1,count1%10+'0');//七段数码管显示数字

SEG7_show(0,count1/10+'0');

TIMER_0_counter=0;

count1++;

}

}

/*

*计时器中断初始化程序,周期1ms

*/

voidtimer_irq_init(inthour,intmin,intsec)

{

TIMER_0_counter=0;

count1=0;

time1[0]=sec;

time1[1]=min;

time1[2]=hour;

IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_0_BASE,

ALTERA_AVALON_TIMER_CONTROL_START_MSK|//START=1

ALTERA_AVALON_TIMER_CONTROL_CONT_MSK|//CONT=1

ALTERA_AVALON_TIMER_CONTROL_ITO_MSK);

alt_irq_register(TIMER_0_IRQ,0,timer_isr);

}

2.4七段数码管

在Qsys中添加SEG7模块,这个模块来自DE2-115SystemCD中官方范例的IP,参数默认即可,具体参数如下所示:

由于SEG7模块本质就是PIO,所以只需要PIO读写操作就可以控制SEG7,SEG7_show函数实现在数码管上显示字符。

代码如下所示:

#defineSEG7_SET(index,seg_mask)IOWR(SEG7_BASE,index,seg_mask)

//在第i个数码管上显示字符ch

voidSEG7_show(inti,charch)

{

if(ch>='0'&&ch<='9')

{

SEG7_SET(7-i,szMap[ch-'0']);

}

elseif(ch>='a'&&ch<='f')

{

SEG7_SET(7-i,szMap[ch-'a'+10]);

}

}

2.5LCD

在Qsys中添加16x2CharacterDisplay模块,该模块来自AlteraUniversityProgram。

实现了清零、显示字符串的功能。

/*

*cleartheline

*/

voidlcd_clear(intline)

{

alt_up_character_lcd_set_cursor_pos(char_lcd_dev,0,line);

alt_up_character_lcd_string(char_lcd_dev,"");

}

/*

*showthestringatthefirstline

*/

voidlcd_show_first_line(char*str)

{

lcd_clear(0);

alt_up_character_lcd_set_cursor_pos(char_lcd_dev,0,0);

alt_up_character_lcd_string(char_lcd_dev,str);

}

/*

*showthestringatthesecondline

*/

voidlcd_show_second_line(char*str)

{

lcd_clear

(1);

alt_up_character_lcd_set_cursor_pos(char_lcd_dev,0,1);

alt_up_character_lcd_string(char_lcd_dev,str);

}

/*

*initialLCD

*disablecursor

*/

voidlcd_init()

{

//opentheCharacterLCDport

char_lcd_dev=alt_up_character_lcd_open_dev(LCD_NAME);

if(char_lcd_dev==NULL)

printf("Error:

couldnotopencharacterLCDdevice\n");

else

printf("OpenedcharacterLCDdevice\n");

alt_up_character_lcd_init(char_lcd_dev);

alt_up_character_lcd_cursor_off(char_lcd_dev);

alt_up_character_lcd_string(char_lcd_dev,"Hello!

");

lcd_clear(0);

lcd_show_first_line("helloworld");

charsecond_row[]="MynameisLi\0";

lcd_show_second_line(second_row);

}

2.6ps2键盘

在Qsys中添加ps2模块,该模块来自AlteraUniversityProgram。

通过中断方式响应键盘,敲入一个字符,键盘中断服务程序响应,将输入得到字符显示在LCD上。

/*

*键盘输入

*/

charkbd_input(){

KB_CODE_TYPEdecode_mode;

alt_u8buffer;

charascii;

chartemp[20];

if((decode_scancode(ps2,&decode_mode,&buffer,&ascii)==0)){

ix=ix+1;

if((ix%2)==0){

ix=0;

sprintf(temp,"kbdinput:

%c",ascii);

lcd_show_first_line(temp);

printf("ch=%c",ascii);

returnascii;

}

}

return-1;

}

/*

*键盘中断服务程序

*/

voidkbd_isr(void*context,alt_u32id){

KB_CODE_TYPEdecode_mode;

alt_u8buffer;

charascii;

chartemp[20];

if((decode_scancode(ps2,&decode_mode,&buffer,&ascii)==0)){

ix=ix+1;

if((ix%2)==0){

ix=0;

sprintf(temp,"kbdinput:

%c",ascii);

lcd_show_first_line(temp);

printf("ch=%c\n",ascii);

//returnascii;

}

}

//return-1;

}

/*

*键盘初始化

*/

intkbd_init(void){

charkey;

printf("InitializingSetup\n");

ps2=alt_up_ps2_open_dev(PS2_NAME);//openPS/2device

//ps2->timeout=100;

alt_up_ps2_init(ps2);

alt_up_ps2_clear_fifo(ps2);

reset_keyboard(ps2);

printf("Readyforkeypress:

\n");

//while

(1){

//key=kbd_input();

//if(key=='1')//outputasamplevalueforaknowkeypress

//printf("%c",key);

//}

//注册中断

kbd_input();

kbd_input();

kbd_input();

kbd_input();

kbd_input();

alt_up_ps2_enable_read_interrupt(ps2);

alt_irq_register(PS2_IRQ,ps2,kbd_isr);

return0;

}

2.7ps2鼠标

Ps2鼠标和ps2键盘共用ps2模块。

通过中断方式响应中断,即点击鼠标左右键,鼠标中断服务程序响应,在LCD上显示是左键还是右键点击。

#defineLEFT_BUTTON_DOWN0

#defineRIGHT_BUTTON_DOWN1

/*

*鼠标按键解码

*

*/

intgetButton_down(alt_u8first_byte){

if((first_byte&0x08)==0x08){

if((first_byte&0x01)==1){

returnLEFT_BUTTON_DOWN;

}

if((first_byte&0x02)==0x02){

returnRIGHT_BUTTON_DOWN;

}else{

return-1;

}

}else{

return-1;

}

}

/*

*鼠标服务中断子程序

*/

voidmouse_isr(void*context,alt_u32id){

//lcd_show_first_line("1111");

alt_u8mous_info[3];

alt_up_ps2_read_data_byte(mouse,&mous_info[0]);

alt_up_ps2_read_data_byte(mouse,&mous_info[1]);

alt_up_ps2_read_data_byte(mouse,&mous_info[2]);

//lcd_show_second_line("2222");

intbutton=getButton_down(mous_info[0]);

if(button==LEFT_BUTTON_DOWN){

lcd_show_first_line("Leftbutton");

}elseif(button==RIGHT_BUTTON_DOWN){

lcd_show_first_line("Rightbutton");

}

}

/*

*鼠标初始化

*/

intmouse_irq_init(){

//init_lcd();

//setCursorPosition(50,50);

//打开鼠标设备

mouse=alt_up_ps2_open_dev(PS2_NAME);

//禁用timeout

mouse->timeout=0;

//初始化

alt_up_ps2_init(mouse);

//复位

alt_up_ps2_mouse_reset(mouse);

//清FIFO

alt_up_ps2_clear_fifo(mouse);

//设置数据接收有效让鼠标状态返回

alt_up_ps2_mouse_set_mode(mouse,MOUSE_ENABLE_DATA_REPORTING);

//重新设置采样率设为10

alt_up_ps2_mouse_set_mode(mouse,MOUSE_SET_SAMPLE_RATE);

alt_up_ps2_mouse_set_mode(mouse,10);

//设置分辨率设为2count/mm

alt_up_ps2_mouse_set_mode(mouse,MOUSE_SET_RESOLUTION);

alt_up_ps2_mouse_set_mode(mouse,0x02);

alt_up_ps2_enable_read_interrupt(mouse);

//开中断

//IOWR_ALT_UP_PS2_PORT_CONTROL(PS2_BASE,0x01);

//启动流模式

alt_up_ps2_mouse_set_mode(mouse,MOUSE_STREAM_MODE);

//查看设备信息

alt_up_ps2_mouse_set_mode(mo

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 幼儿读物

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1