1.这个错误是由什么引起?提示LED_ PIO_BASE没有声明 答:这是因为名字不一致引起的比如,在生成SOPC系统时,双击PIO(Parallel I/O)(在Avalon Modules -> Other 下),为系统添加输出接口,你没有把该组件改名成LED_PIO,而是保留了原始的名字:PIO_0;但你又通过 IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led);来向该组件写入数据,就会导致上述错误。解决办法:1.可以修改sopc系统,为该PIO改名为LED_PIO ;2.在hello_led.c的前面给LED_PIO_BASE赋值,如#define LED_PIO_BASE 0x00001800,后面的这个地址要与SOPC中的地址对应. 2. 怎样在NIOSII中操作PIO,提供一种参考方法。 答:hello_led.c是这样写IO口的: IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led);首先在altera_avalon_pio_regs.h找到定义#i nclude#define IORD_ALTERA_AVALON_PIO_DATA(base) IORD(base, 0)#define IOWR_ALTERA_AVALON_PIO_DATA(base, data) IOWR(base, 0, data)因此在NIOSII中可以调用#i nclude库函数IORD/IOWR来操作PIO。在smallsoftwarehello_led_0_syslibDebugsystem_des cription下的system.h中,有以下内容:#define LED_PIO_TYPE "altera_avalon_pio"#define LED_PIO_BASE 0x00004000其中LED_PIO_BASE(IO寄存器地址?)为0x00004000同SOPCBuilder中设置一致!(其实在SopcBuilder中有关NiosII的配置,就是通过system.h来传送给IDE的!)最后用IOWR(0x00004000, 0, led);替代IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led);编译,下载到开发板上,运行成功!3.出错信息如下: Linking hello_world_0.elf... /cygdrive/e/DE2Project_restored/software/hello_world_0_syslib/Debug/libhello_world_0_syslib.a(alt_main.o)(.text+0x60): In function `alt_main':/cygdrive/c/altera/72/nios2eds/components/altera_hal/HAL/src/alt_main.c:163: undefined reference to `main'collect2: ld returned 1 exit statusmake: *** [hello_world_0.elf] Error 1Build completed in 1.953 seconds 答:将主函数名字写错了.应该写成int main(void),结果写成了 int mian() 悲剧!!!!!! 4.IOWR_ALTERA_AVALON_PIO_DATA怎么使用? 答:IOWR_ALTERA_AVALON_PIO_DATA是一个宏定义,其位置在altera_avalon_pio_regs.h中,另外还要参考io.h头文件。NiosII IDE为了避开NiosII的Cache以及简化IO端口操作程序的编写,定义了两类基本的宏(以IOWR_开头的为写PIO操作,以IORD_开头的为读PIO操作),其效果与使用指针的效果不完全一样。 LED_PIO_BASE是在system.h中定义的一个宏,是LED_PIO端口的基地址。 IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE,led)的含义就是往LED_PIO端口的数据输出寄存器写入led, 具体可以参考 Altera_embeded_peripherals 一文,这里讲解了一个PIO端口包含了那些寄存器。参考NiosII_software_developer's_handbook 进行驱动设计。这两个文件可以在Altera的官方网站上下载。 |
在这里先简单介绍一下各头文件的作用,,<stdio.h>这个头文件包含了标准输入、输出、错误函数库;"system.h",这个文件描述了每个设备并给出了以下一些详细信息:设备的硬件配置、基地址、中断优先级、设备的符号名称,用户不需要编辑system.h 文件,此文件由HAL 系统库自动生成,其内容取决于硬件配置和用户在IDE 中设置的系统库属性;“altera_avalon_pio_regs.h ” 这个文件是通用I/O 口与高层软件之间的接口.IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE, led)这个函数就是在此文件中定义的,此函数的功能为将数值(led)赋给LED_PIO_BASE 为基地址的用户自定义的I/O 口上,也就是将led 这个值赋给我们硬件中LED 灯所接的FPGA 管脚上;“alt_types.h”头文件定义了数据类型,如下表所示 类型 说明alt_8 有符号8 位整数alt_u8 无符号8 位整数alt_16 有符号16 位整数alt_u16 无符号16 位整数alt_32 有符号32 位整数 alt_u32 无符号32 位整数 IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_PIO_BASE,0xf);IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE,0x0);IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE);alt_irq_register(BUTTON_PIO_IRQ,edge_capture_ptr,handle_button_interrupts)在文件"altera_avalon_pio_regs.h"中有如下定义#define IOWR_ALTERA_AVALON_PIO_IRQ_MASK(base,data)IOWR(base,2,data)#define IOWR_ALTERA_AVALON_PIO_EDGE_CAP(base,data)IOWR(base,3,data)#define IORD_ALTERA_AVALON_PIO_EDGE_CAP(base)IORD(base,3)第一个函数是使能中断函数,是按位来势能的,比如0xf表示四位全部使能,而0x7表示使能低3位中断;第二个函数是设置边沿捕获寄存器函数,用来重新设定寄存器的值;一般在读取之后会重新设定为0;第三个函数是读取边沿捕获寄存器函数,用来读取寄存器的值;下面是alt_irq_register函数的原形,此函数用来声明ISR,在软使用IRS之前一定要先声明;extern int alt_irq_register(alt_u32 id,void*context,void(*irq_handler)(void*,alt_u32));一般在开发按键中断程序时,handle_button_interrupts()和init_button_pio()这两个函数直接使用,不用再编辑。 |
#include "system.h" #include "altera_avalon_pio_regs.h"#include "alt_types.h"#include "stdio.h"#include "unistd.h"int main (void) __attribute__ ((weak, alias ("alt_main")));int alt_main (void){ unsigned char led = 0;while (1) { for(led=0;led<8;led++) { IOWR_ALTERA_AVALON_PIO_DATA(LED_GREEN_BASE, 1<<led); usleep(500000); //延时0.5秒 } } return 0;} |
count_binary.h文件 #ifndef COUNT_BINARY_H_ #define COUNT_BINARY_H_#include "alt_types.h"#include <stdio.h>#include <unistd.h>#include "system.h"#include "sys/alt_irq.h"#include "altera_avalon_pio_regs.h"#define ESC 27#define ESC_TOP_LEFT "[1;0H"#define ESC_COL2_INDENT5 "[2;5H"#define ESC_CLEAR "K"#define ECS_COL1_INDENT5 "[1;5H"#endif /*COUNT_BINARY_H_*/
main.c文件: #include "count_binary.h" int main(void){ int i; int data; while(1) { i=0; data=0x80; for(i=0;i<8;i++) { IOWR(LED_GREEN_BASE,0,data); data>>=1; usleep(500000); } } }/* 注: 函数原型:IOWR(BASE, REGNUM, DATA) 输入参数:BASE为寄存器的基地址,REGNUM为寄存器的偏移量,DATA为要写入的数据函数说明:往偏移量为REGNUM寄存器中写入数据。寄存器的值在地址总线的范围之内。返回值:*/ |
count_binary.h文件见上
main.c文件 /* 硬件环境:DE2开发板 按键未按时是高电平 按下后是低电平 4个按键控制4个灯(配置的系统有八个灯,4个键只点亮高四位的灯) */#include "count_binary.h"int alt_main(){ int key,data; data=0x00; while(1) { key=IORD(BUTTON_PIO_BASE,0); if(key==0x7) data=0x80; key=IORD(BUTTON_PIO_BASE,0); if(key==0xb) data=0x40; key=IORD(BUTTON_PIO_BASE,0); if(key==0xd) data=0x20; key=IORD(BUTTON_PIO_BASE,0); if(key==0xe) data=0x10; IOWR(LED_GREEN_BASE,0,data); }}/* IO操作函数 函数原型:IORD(BASE, REGNUM) 输入参数:BASE为寄存器的基地址,REGNUM为寄存器的偏移量函数说明:从基地址为BASE的设备中读取寄存器中偏移量为REGNUM的单元里面的值。寄存器的值在地址总线的范围之内。返回值: -*/ |
/* 硬件环境:DE2开发板 四个按键对应着四个不同的外部中断 通过不同的按键在数码管上面显示不同的数字 */#include "count_binary.h"volatile int edge_capture;/*外部中断服务子函数声明(与单片机不同,这里需要声明一下)*/static void handle_button_interrupts(void *context,alt_u32 id);/*按键初始化*/static void init_button_pio(){ void *edge_capture_ptr=(void*)&edge_capture; /*使能四个按键的中断(外部中断)*/ IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_PIO_BASE,0xf); /*复位边沿捕获寄存器*/ IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE,0x0); /*注册四个按键锁对应的外部中断*/ alt_irq_register(BUTTON_PIO_IRQ,edge_capture_ptr,handle_button_interrupts);}/*主函数*/int main(void){ init_button_pio(); while(1) { switch(edge_capture) { /*按键3按下时8个数码管全部显示1*/case 0x08: IOWR(SEG7_DISPLAY_BASE,0,0x11111111); break; case 0x04: IOWR(SEG7_DISPLAY_BASE,0,0X22222222); break; case 0x02: IOWR(SEG7_DISPLAY_BASE,0,0X33333333); break; /*按键0按下时8个数码管全部显示4*/ case 0x01: IOWR(SEG7_DISPLAY_BASE,0,0x44444444); break; } }}/*外部中断服务子函数*/ static void handle_button_interrupts(void *context,alt_u32 id){ volatile int * edge_capture_ptr=(volatile int *)context; /*键按键的值存储到边沿捕获寄存器中*/ *edge_capture_ptr=IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE); /*复位边沿捕获寄存器*/ IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE,0);} |
#include "count_binary.h"int alt_main(){ int second=0; while(1) { usleep(100000); second++; IOWR(SEG7_DISPLAY_BASE,0,second); } } |
lcd.h文件 #ifndef LCD_H_#define LCD_H_#define lcd_write_cmd(base,data) IOWR(base,0,data)#define lcd_read_cmd(base) IORD(base,1)#define lcd_write_data(base,data) IOWR(base,2,data)#define lcd_read_data(base) IORD(base,3)void lcd_init();void lcd_show_text(char * text);void lcd_line2();void lcd_test();#endif /*LCD_H_*/ main.c文件 /*硬件环境:DE2开发板 * 软件环境:quaters II 7.2,NIOS II 7.2 * 函数功能:1602液晶驱动程序 */#include <unistd.h>#include <string.h>#include <io.h>#include "system.h"#include "lcd.h"void lcd_init(){ /*采用8位数据总线的方式,两行显示*/ lcd_write_cmd(LCD_16207_0_BASE,0X38); usleep(2000); /*关显示,关光标闪烁方式*/ lcd_write_cmd(LCD_16207_0_BASE,0X0C); usleep(2000); /*清显示*/ lcd_write_cmd(LCD_16207_0_BASE,0X01); usleep(2000); /*光标前移方式,不允许整屏移动*/ lcd_write_cmd(LCD_16207_0_BASE,0X06); usleep(2000); /*显示指针指向处事位置*/ lcd_write_cmd(LCD_16207_0_BASE,0X80); usleep(2000); }/*显示一行字符*/void lcd_show_text(char * text){ int i; for(i=0;i<strlen(text);i++) { lcd_write_data(LCD_16207_0_BASE,text[i]); usleep(2000); }}void lcd_line1(){ lcd_write_cmd(LCD_16207_0_BASE,0X80); usleep(2000); }/*换行,即切换到第二行*/void lcd_line2(){ lcd_write_cmd(LCD_16207_0_BASE,0XC0); usleep(2000);}int main(){ char text1[16]="Wu Qin De Shi"; char text2[16]="Jie,Wu Qin De Ni"; lcd_init();//液晶初始化 while(1) { /*切换到第一行*/ lcd_line1(); /*显示第一行字符*/ lcd_show_text(text1); /*切换到第二行*/ lcd_line2(); /*显示第二行字符*/ lcd_show_text(text2); usleep(4000000); lcd_write_cmd(LCD_16207_0_BASE,0X01);//清屏 usleep(2000); /*切换到第一行*/ lcd_line1(); lcd_show_text("Liu Ya Li,"); lcd_line2(); /*显示第二行字符*/ lcd_show_text("I Love You!"); usleep(4000000); } return 0; } |
/*硬件环境:DE2开发板 * 软件环境:quaters II 7.2,NIOS II 7.2 * 函数功能:1602液晶驱动程序 * 使用NIOS II的fprintf标准函数对lcd编程比较简单! */#include <unistd.h>#include <stdio.h>#include <string.h>#include <io.h>#include "system.h"int main(void){ FILE *lcd; lcd=fopen("/dev/lcd_16207_0","w"); /*1602液晶第一行显示的内容*/ fprintf(lcd,"I love NIOS II!\n"); /*1602液晶第二行显示的内容*/ fprintf(lcd,"I love you!"); fclose(lcd); return 0;} |
count_binary.h文件 #ifndef COUNT_BINARY_H_#define COUNT_BINARY_H_#include "alt_types.h"#include <stdio.h>#include <unistd.h>#include "system.h"#include "sys/alt_irq.h"#include "altera_avalon_pio_regs.h"#define ESC 27#define ESC_TOP_LEFT "[1;0H"#define ESC_COL2_INDENT5 "[2;5H"#define ESC_CLEAR "K"#define ECS_COL1_INDENT5 "[1;5H"#endif /*COUNT_BINARY_H_*/
main.c文件 #include "count_binary.h"static alt_u8 count;volatile int edge_capture;#ifdef BUTTON_PIO_BASEstatic void handle_button_interrupts(void *context,alt_u32 id){ volatile int *edge_capture_ptr=(volatile int *)context; *edge_capture_ptr=IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE); IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE,0);}static void init_button_pio(){ void *edge_capture_ptr=(void *)&edge_capture; IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_PIO_BASE,0XF); IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE,0X0); alt_irq_register(BUTTON_PIO_IRQ,edge_capture_ptr,handle_button_interrupts);}#endif#ifdef SEG7_DISPLAY_BASEstatic void sevenseg_set_hex(int hex){ static alt_u8 segments[16]={0x81,0xcf,0x92,0x86,0xcc,0xa4,0xa0,0x8f,0x80,0x84, 0x88,0xe0,0xf2,0xc2,0xb0,0xb8}; unsigned int data=segments[hex&15]|(segments[(hex>>4)&15]<<8);IOWR_ALTERA_AVALON_PIO_DATA(SEG7_DISPLAY_BASE,data);}#endif static void lcd_init(FILE *lcd){ fprintf(lcd,"%c%s Counting will be displayed below...",ESC,ESC_TOP_LEFT);}static void initial_message(){ } static void count_led(){ #ifdef LED_RED_BASE IOWR_ALTERA_AVALON_PIO_DATA(LED_RED_BASE,count); #endif}static void count_sevenseg(){ #ifdef SEG7_DISPLAY_BASE sevenseg_set_hex(count); #endif}static void count_lcd(void *arg){ FILE *lcd=(FILE*)arg; fprintf(lcd,"%c%s 0x%x\n",ESC,ESC_COL2_INDENT5,count);}static void count_all(void *arg){ count_led(); count_sevenseg(); count_lcd(arg); printf("%02x, ",count); }static void handle_button_press(alt_u8 type,FILE *lcd){ if(type=='c') { switch(edge_capture) { case 0x1: count_led();break; case 0x2: count_sevenseg();break; case 0x4: count_lcd(lcd);break; case 0x8: count_all(lcd);break; default: count_all(lcd);break; } }}int main(void){ int i; int wait_time; FILE *lcd; count=0; lcd=fopen("/dev/lcd_16207_0","w"); #ifdef BUTTON_PIO_BASE //init_button_pio(); init_button_pio(); #endif initial_message(); while(1) { usleep(100000); if(edge_capture!=0) { handle_button_press('c',lcd); } else { count_all(lcd); } if(count==0xff) { fprintf(lcd,"%c%s Waiting...\n",ESC,ESC_TOP_LEFT,ESC,ESC_CLEAR, ESC,ESC_COL2_INDENT5); edge_capture=0; fprintf(lcd,"%c%s",ESC,ESC_COL2_INDENT5,ESC,ESC_CLEAR); wait_time=0; for(i=0;i<70;++i) { wait_time=i/10; fprintf(lcd,"%c%s",ESC,ESC_COL2_INDENT5,wait_time); if(edge_capture!=0) { handle_button_press('w',lcd); usleep(100000); } } initial_message(); lcd_init(lcd); } count++; } fclose(lcd); return(0);} |
#include <stdio.h>#include <sys/unistd.h>#include <io.h>#include <string.h>#include "system.h"#include "altera_avalon_pio_regs.h"#include "altera_avalon_timer_regs.h"#include "alt_types.h"#include "sys/alt_irq.h"static void timer1_init(void); //初始化中断int i = 0;/*主函数*/int main(void){ //初始化Timer timer1_init(); while(1); return 0;} /*定时器1中断服务子函数*/static void ISR_timer1(void *context, alt_u32 id){ //控制流水灯闪烁,一共8个LED IOWR_ALTERA_AVALON_PIO_DATA(LED_GREEN_BASE, 1<<i); i++; if(i == 8) i = 0; //清除Timer中断标志寄存器 IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_1_BASE, 0x00);} /*定时器1初始化函数*/void timer1_init(void) //初始化中断{ //清除Timer1中断标志寄存器 IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_1_BASE, 0x00); //设置Timer1周期T=25000000/5000000=0.5s //设定定时器的低16位 IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_1_BASE,25000000); //设定定时器的高16位 IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_1_BASE,25000000 >> 16); //Timer1中断使能 IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_1_BASE, 0x07); //注册Timer1中断 alt_irq_register(TIMER_1_IRQ, (void *)TIMER_1_BASE, ISR_timer1); }
|
#include <stdio.h>#include <sys/unistd.h>#include <io.h>#include <string.h>#include "system.h"#include "altera_avalon_pio_regs.h"#include "altera_avalon_timer_regs.h"#include "alt_types.h"#include "sys/alt_irq.h"static void timer1_init(void); //初始化中断unsigned long int i = 0;/*主函数*/int main(void){ //初始化Timer timer1_init(); while(1); return 0;} /*定时器1中断服务子函数*/static void ISR_timer1(void *context, alt_u32 id){ //在8个7段数码管上面完成计数 IOWR(SEG7_DISPLAY_BASE,0,i); i++; //清除Timer中断标志寄存器 IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_1_BASE, 0x00);} /*定时器1初始化函数*/void timer1_init(void) //初始化中断{ //清除Timer1中断标志寄存器 IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_1_BASE, 0x00); //设置Timer1周期T=25000000/5000000=0.5s //设定定时器的低16位 IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_1_BASE,25000000); //设定定时器的高16位 IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_1_BASE,25000000 >> 16); //Timer1中断使能 IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_1_BASE, 0x07); //注册Timer1中断 alt_irq_register(TIMER_1_IRQ, (void *)TIMER_1_BASE, ISR_timer1); }
|
/*硬件环境:DE2开发板 * 软件环境:NIOS II7.2,QUATERS II 7.2 * 本程序有定时器1控制灯的闪烁 * 由定时器2控制定时器1的周期 * */#include <stdio.h>#include <sys/unistd.h>#include <io.h>#include <string.h>#include "system.h"#include "altera_avalon_pio_regs.h"#include "altera_avalon_timer_regs.h"#include "alt_types.h"#include "sys/alt_irq.h"/*注:我自己的DE2的system.h文件中的两个定时器分别是TIMER_0和TIMER_1 * 而我直接采用的是黑金刚开发板的程序 * 在system.h 文件中 * #define TIMER_0_BASE 0x00681020 * #define TIMER_0_IRQ 3 * #define TIMER_1_BASE 0x00681040 * #define TIMER_1_IRQ 4 * 故而需做修改如下:*/#define TIMER1_IRQ 3#define TIMER2_IRQ 4#define TIMER1_BASE 0x00681020 #define TIMER2_BASE 0x00681040static void timer_init(void); //初始化中断 int i = 0,j = 0,flag;alt_u32 timer_prd[4] = {5000000, 10000000, 50000000, 100000000};//定时器的周期//T1依次为0.1s,0.2s,1s,2sint main(void){ //初始化Timer timer_init(); while(1); return 0;}static void ISR_timer1(void *context, alt_u32 id){ //控制流水灯闪烁,一共8个LED IOWR(LED_GREEN_BASE,0,i); //数码管显示 IOWR(SEG7_DISPLAY_BASE,0,i); i++; if(i == 255) i = 0; //清除Timer中断标志寄存器 IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER1_BASE, 0x00);}/*用定时器2改变定时器1的周期*/static void ISR_timer2(void *context, alt_u32 id){ //改变定时器1的周期T1=timer_prd[j]/50M(单位:秒) IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER1_BASE, timer_prd[j]); IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER1_BASE, timer_prd[j] >> 16); //重新启动定时器 IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER1_BASE, 0x07); //闪烁频率先高后低然后又变高 if(j == 0) flag = 0; if(j == 3) flag = 1; if(flag == 0){ j++; } else{ j--; } //清除中断标志位 IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER2_BASE, 0); }void timer_init(void) //初始化中断{ //清除Timer1中断标志寄存器 IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER1_BASE, 0x00); //设置Timer1周期 IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER1_BASE,80000000); IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER1_BASE, 80000000 >> 16); //允许Timer1中断 IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER1_BASE, 0x07); //注册Timer1中断 alt_irq_register(TIMER1_IRQ, (void *)TIMER1_BASE, ISR_timer1); //清除Timer2中断标志寄存器 IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER2_BASE, 0x00); //设置Timer2周期 T2=400M/50M=8s; IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER2_BASE,400000000); IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER2_BASE, 400000000 >> 16); //允许Timer2中断 IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER2_BASE, 0x07); //注册Timer2中断 alt_irq_register(TIMER2_IRQ, (void *)TIMER2_BASE, ISR_timer2); }
|
/*硬件环境:DE2开发板 * 软件环境:NIOS II 7.2,QUATERS II 7.2 * 本程序主要功能: * 1.每隔1秒钟用串口向外发送一个字符串 * 2.当用串口调试助手向其发送0-9这9个数字时,八个数码管都依次显示0-9 * *//*配置的系统的波特率是115200*/#include "altera_avalon_uart_regs.h"#include "system.h"#include "altera_avalon_pio_regs.h"#include "alt_types.h"#include "sys/alt_irq.h"#include <stdio.h>#include <string.h>#define UART_BASE 0x00681000#define UART_IRQ 2#define TIME_DELAY 1000000//1M,即一秒//UART发送一个字节子程序void Uart_send(unsigned char data){ alt_u16 status; status=IORD_ALTERA_AVALON_UART_STATUS(UART_BASE); while(!(status&0x0040))//等待发送完成 status=IORD_ALTERA_AVALON_UART_STATUS(UART_BASE); IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE,data);}//UART发送多个字节子程序void Uart_send_n(unsigned char *ptr){ while(*ptr) { Uart_send(*ptr); ptr++; } Uart_send(0x0a);//显示完一个字符串就回车换行} //UART接收子程序int Uart_receive(void){ alt_u16 status; int temp; status=IORD_ALTERA_AVALON_UART_STATUS(UART_BASE); while(!(status&0x0080))//等待发送完成 status=IORD_ALTERA_AVALON_UART_STATUS(UART_BASE); temp=IORD_ALTERA_AVALON_UART_RXDATA(UART_BASE); return temp;} //串口接收中断服务程序void Uart_ISR(void * context,alt_u32 id){ unsigned char temp; temp=IORD_ALTERA_AVALON_UART_RXDATA(UART_BASE); switch(temp) { case '0': IOWR(SEG7_DISPLAY_BASE,0,0x00000000);break; case '1': IOWR(SEG7_DISPLAY_BASE,0,0x11111111);break; case '2': IOWR(SEG7_DISPLAY_BASE,0,0x22222222);break; case '3': IOWR(SEG7_DISPLAY_BASE,0,0x33333333);break; case '4': IOWR(SEG7_DISPLAY_BASE,0,0x44444444);break; case '5': IOWR(SEG7_DISPLAY_BASE,0,0x55555555);break; case '6': IOWR(SEG7_DISPLAY_BASE,0,0x66666666);break; case '7': IOWR(SEG7_DISPLAY_BASE,0,0x77777777);break; case '8': IOWR(SEG7_DISPLAY_BASE,0,0x88888888);break; case '9': IOWR(SEG7_DISPLAY_BASE,0,0x99999999);break; } }//串口中断初始化void Uart_init(){ IOWR_ALTERA_AVALON_UART_CONTROL(UART_BASE, 0x80);//接收中断使能 IOWR_ALTERA_AVALON_UART_STATUS(UART_BASE, 0x0);//清状态标志 // IOWR_ALTERA_AVALON_UART_RXDATA(UART_BASE, 0x0);//清接收寄存器 alt_irq_register(UART_IRQ,0,Uart_ISR);}int main(){ Uart_init(); while(1) { Uart_send_n("Liu Ya Li,I love u!"); //Uart_send_n(64); usleep(TIME_DELAY);//延时一微秒 } }
|
#define timer2 #ifdef timer2#include <stdio.h>#include <sys/unistd.h>#include <io.h>#include <string.h>#include "system.h"#include "altera_avalon_pio_regs.h"#include "altera_avalon_timer_regs.h"#include "alt_types.h"#include "sys/alt_irq.h"//#define TIMER_2_BASE 0x01b02060//#define TIMER_2_IRQ 9static void timer2_init(void); //初始化中断unsigned long int i = 0;/*主函数*/int main(void){ //初始化Timer timer2_init(); while(1); return 0;}/*定时器2中断服务子函数*/ static void ISR_timer2(void *context, alt_u32 id){ //在8个7段数码管上面完成计数 IOWR(SEG7_DISPLAY_BASE,0,i); i++; //清除Timer2中断标志寄存器 IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_2_BASE, 0x00);}/*定时器1初始化函数*/ void timer2_init(void) //初始化中断{ //清除Timer2中断标志寄存器 IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_2_BASE, 0x00); //设置Timer2周期T=1s //设定定时器的低16位 IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_2_BASE,100000000); //设定定时器的高16位 IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_2_BASE,100000000 >> 16); //Timer1中断使能 IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_2_BASE, 0x07); //注册Timer2中断 alt_irq_register(TIMER_2_IRQ, (void *)TIMER_2_BASE, ISR_timer2); }#else#include <stdio.h>#include <sys/unistd.h>#include <io.h>#include <string.h>#include "system.h"#include "altera_avalon_pio_regs.h"#include "altera_avalon_timer_regs.h"#include "alt_types.h"#include "sys/alt_irq.h"static void timer1_init(void); //初始化中断unsigned long int i = 0;/*主函数*/int main(void){ //初始化Timer timer1_init(); while(1); return 0;}/*定时器1中断服务子函数*/ static void ISR_timer1(void *context, alt_u32 id){ //在8个7段数码管上面完成计数 IOWR(SEG7_DISPLAY_BASE,0,i); i++; //清除Timer中断标志寄存器 IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_1_BASE, 0x00);}/*定时器1初始化函数*/ void timer1_init(void) //初始化中断{ //清除Timer1中断标志寄存器 IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_1_BASE, 0x00); //设置Timer1周期T=1s //设定定时器的低16位 IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_1_BASE,100000000); //设定定时器的高16位 IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_1_BASE,100000000 >> 16); //Timer1中断使能 IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_1_BASE, 0x07); //注册Timer1中断 alt_irq_register(TIMER_1_IRQ, (void *)TIMER_1_BASE, ISR_timer1); } #endif |
首先,对memest()函数进行一下介绍。 memest原型 (please type "man memset" in your shell) void *memset(void *s, int c, size_t n); memset:作用是在一段内存块中填充某个给定的值,它对较大的结构体或数组进行清零操作的一种最快方法。 常见的三种错误 第一: 搞反了c 和 n的位置. 一定要记住 如果要把一个char a[20]清零, 一定是 memset(a, 0, 20) 而不是 memset(a, 20, 0) 第二: 过度使用memset, 我想这些程序员可能有某种心理阴影, 他们惧怕未经初始化的内存, 所以他们会写出这样的代码: char buffer[20]; memset(buffer, 0, sizeof((char)*20)); strcpy(buffer, "123"); 这里的memset是多余的. 因为这块内存马上就被覆盖了, 清零没有意义. 第三: 其实这个错误严格来讲不能算用错memset, 但是它经常在使用memset的场合出现 int some_func(struct something *a){ … … memset(a, 0, sizeof(a)); … } 问:为何要用memset置零?memset( &Address, 0, sizeof(Address));经常看到这样的用法,其实不用的话,分配数据的时候,剩余的空间也会置零的。 答:1.如果不清空,可能会在测试当中出现野值。 你做下面的试验看看结果() char buf[5]; CString str,str1; //memset(buf,0,sizeof(buf)); for(int i = 0;i<5;i++) { str.Format(“%d “,buf[i]); str1 +=str ; } TRACE(“%s\r\n“,str1) 2.其实不然!特别是对于字符指针类型的,剩余的部分通常是不会为0的,不妨作一个试验,定义一个字符数组,并输入一串字符,如果不用memset实现清零,使用MessageBox显示出来就会有乱码(0表示NULL,如果有,就默认字符结束,不会输出后面的乱码) 问: 如下demo是可以的,能把数组中的元素值都设置成字符1, #include <iostream> #include <cstring> using namespace std; int main() { char a[5]; memset(a,'1',5); for(int i = 0;i < 5;i++) cout<<a[i]<<" "; system("pause"); return 0; }
#include <stdio.h>//#include "../inc/sopc.h"#include "system.h"#include "string.h"#include "unistd.h"#include "altera_avalon_pio_regs.h"/*在DE2开发板相对应的system.h文件中定义的是SDRAM_0_BASE * #define SDRAM_0_BASE 0x00800000,所以有如下宏定义*/#define SDRAM_BASE 0x00800000unsigned short * ram = (unsigned short *)(SDRAM_BASE+0x10000); //SDRAM地址 int main(void){ int i; memset(ram,0,100); //从这里可以看出SDRAM的读写速度有多么的快!!! //向ram中写数据,当ram写完以后,ram的地址已经变为(SDRAM_BASE+0x10100) for(i=0;i<100;i++) { *(ram++) = i; } //逆向读取ram中的数据 for(i=0;i<100;i++){ printf("%d\n",*(--ram)); } for(i=100;i<200;i++) { *(ram++) = i; } //逆向读取ram中的数据 for(i=100;i<200;i++) { IOWR(SEG7_DISPLAY_BASE,0,*(--ram)); printf("%d\n",*(--ram)); usleep(1000000); } return 0;}
|
#include "system.h"#define _LEDtypedef struct { unsigned long int DATA; unsigned long int DIRECTION; unsigned long int INTERRUPT_MASK; unsigned long int EDGE_CAPTURE;} PIO_STR; #ifdef _LED#define LED ((PIO_STR *)LED_GREEN_BASE)#endif #include "unistd.h"#include "stdio.h"unsigned int i=0;int main(){ while(1) { for(i=0;i<8;i++) { LED->DATA=1<<i; usleep(1000000);//延时1秒 } }}
流水灯2: #include "system.h"#include "unistd.h"#include "stdio.h"/*结构体的定义*/typedef struct { unsigned long int DATA; unsigned long int DIRECTION; unsigned long int INTERRUPT_MASK; unsigned long int EDGE_CAPTURE;} PIO_STR;/*绿灯的定义*/#define LED_GREEN ((PIO_STR *)LED_GREEN_BASE)/*红灯的定义*/#define LED_RED ((PIO_STR *)LED_RED_BASE)/*按键的定义*/#define KEY ((PIO_STR *)BUTTON_PIO_BASE) unsigned int i=0;int main(){ while(1) { for(i=0;i<18;i++) { LED_RED->DATA=1<<i; LED_GREEN->DATA=1<<i; usleep(500000);//延时0.5秒 } }}
需要注意的是: 当你的CPU选择的是NIOS II/f(最高级的那种)的时候,在高速缓存的配置的地方要注意一下,应选择none,否则 灯是不会亮的!如果选择的是其他两种CPU的话,就不用注意这种问题:
|
/* 硬件环境: DE2开发板 * 软件环境:QUATERS II 7.2,NIOS II 7.2 * 编写时间:2010.7.17 * 功能:8个数码管加定时器1计数 * 定时器1周期T=timer_1_period/50000000 * */#include "system.h"#include "altera_avalon_pio_regs.h"#include "altera_avalon_timer_regs.h"#include "sys/alt_irq.h"#include <io.h>#define timer_1_period 50000#define uint unsigned int#define uchar unsigned charalt_u32 count=0; uchar seg_table[11]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x7f};void isr_timer_1();/*定时器1的初始化*/void timer_1_init(){ /*清除定时器1的中断标志*/ IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_1_BASE,0X00); /*设定定时器周期的低16位*/ IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_1_BASE,timer_1_period); /*设定定时器周期的高16位*/ IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_1_BASE,timer_1_period>>16); /*定时器1中断使能*/ IOWR_ALTERA_AVALON_TIMER_CONTROL(TIMER_1_BASE,0X07); /*对定时器1中断进行注册*/ alt_irq_register(TIMER_1_IRQ, (void *)TIMER_1_BASE, isr_timer_1); }/*定时器1的中断服务子函数*/void isr_timer_1(){ count++; /*清除定时器1的中断标志*/ IOWR_ALTERA_AVALON_TIMER_STATUS(TIMER_1_BASE,0X00);}/*数码管显示子函数*/void seg_display(alt_u32 z){ if(z<10) { IOWR(SEG0_DISPLAY_BASE,0,seg_table[z%10]); IOWR(SEG1_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG2_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG3_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG4_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG5_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG6_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG7_DISPLAY_BASE,0,seg_table[10]); } else if(z<100) { IOWR(SEG0_DISPLAY_BASE,0,seg_table[z%10]); IOWR(SEG1_DISPLAY_BASE,0,seg_table[z%100/10]); IOWR(SEG2_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG3_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG4_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG5_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG6_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG7_DISPLAY_BASE,0,seg_table[10]); } else if(z<1000) { IOWR(SEG0_DISPLAY_BASE,0,seg_table[z%10]); IOWR(SEG1_DISPLAY_BASE,0,seg_table[z%100/10]); IOWR(SEG2_DISPLAY_BASE,0,seg_table[z%1000/100]); IOWR(SEG3_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG4_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG5_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG6_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG7_DISPLAY_BASE,0,seg_table[10]); } else if(z<10000) { IOWR(SEG0_DISPLAY_BASE,0,seg_table[z%10]); IOWR(SEG1_DISPLAY_BASE,0,seg_table[z%100/10]); IOWR(SEG2_DISPLAY_BASE,0,seg_table[z%1000/100]); IOWR(SEG3_DISPLAY_BASE,0,seg_table[z%10000/1000]); IOWR(SEG4_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG5_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG6_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG7_DISPLAY_BASE,0,seg_table[10]); } else if(z<100000) { IOWR(SEG0_DISPLAY_BASE,0,seg_table[z%10]); IOWR(SEG1_DISPLAY_BASE,0,seg_table[z%100/10]); IOWR(SEG2_DISPLAY_BASE,0,seg_table[z%1000/100]); IOWR(SEG3_DISPLAY_BASE,0,seg_table[z%10000/1000]); IOWR(SEG4_DISPLAY_BASE,0,seg_table[z%100000/10000]); IOWR(SEG5_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG6_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG7_DISPLAY_BASE,0,seg_table[10]); } else if(z<1000000) { IOWR(SEG0_DISPLAY_BASE,0,seg_table[z%10]); IOWR(SEG1_DISPLAY_BASE,0,seg_table[z%100/10]); IOWR(SEG2_DISPLAY_BASE,0,seg_table[z%1000/100]); IOWR(SEG3_DISPLAY_BASE,0,seg_table[z%10000/1000]); IOWR(SEG4_DISPLAY_BASE,0,seg_table[z%100000/10000]); IOWR(SEG5_DISPLAY_BASE,0,seg_table[z%1000000/100000]); IOWR(SEG6_DISPLAY_BASE,0,seg_table[10]); IOWR(SEG7_DISPLAY_BASE,0,seg_table[10]); } else if(z<10000000) { IOWR(SEG0_DISPLAY_BASE,0,seg_table[z%10]); IOWR(SEG1_DISPLAY_BASE,0,seg_table[z%100/10]); IOWR(SEG2_DISPLAY_BASE,0,seg_table[z%1000/100]); IOWR(SEG3_DISPLAY_BASE,0,seg_table[z%10000/1000]); IOWR(SEG4_DISPLAY_BASE,0,seg_table[z%100000/10000]); IOWR(SEG5_DISPLAY_BASE,0,seg_table[z%1000000/100000]); IOWR(SEG6_DISPLAY_BASE,0,seg_table[z%10000000/1000000]); IOWR(SEG7_DISPLAY_BASE,0,seg_table[10]); } else if(z<100000000) { IOWR(SEG0_DISPLAY_BASE,0,seg_table[z%10]); IOWR(SEG1_DISPLAY_BASE,0,seg_table[z%100/10]); IOWR(SEG2_DISPLAY_BASE,0,seg_table[z%1000/100]); IOWR(SEG3_DISPLAY_BASE,0,seg_table[z%10000/1000]); IOWR(SEG4_DISPLAY_BASE,0,seg_table[z%100000/10000]); IOWR(SEG5_DISPLAY_BASE,0,seg_table[z%1000000/100000]); IOWR(SEG6_DISPLAY_BASE,0,seg_table[z%10000000/1000000]); IOWR(SEG7_DISPLAY_BASE,0,seg_table[z%100000000/10000000]); }}/*主函数*/int main(){ timer_1_init(); while(1) { seg_display(count); } } |