nios 常见错误0.docx
《nios 常见错误0.docx》由会员分享,可在线阅读,更多相关《nios 常见错误0.docx(21页珍藏版)》请在冰豆网上搜索。
nios常见错误0
NIOSII常见错误:
1.这个错误是由什么引起?
提示LED_PIO_BASE没有声明
答:
这是因为名字不一致引起的比如,在生成SOPC系统时,双击PIO(ParallelI/O)(在AvalonModules->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赋值,如#defineLED_PIO_BASE0x00001800,后面的这个地址要与SOPC中的地址对应.
2.怎样在NIOSII中操作PIO,提供一种参考方法。
答:
hello_led.c是这样写IO口的:
IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE,led);
首先在altera_avalon_pio_regs.h找到定义
#include
#defineIORD_ALTERA_AVALON_PIO_DATA(base)IORD(base,0)
#defineIOWR_ALTERA_AVALON_PIO_DATA(base,data)IOWR(base,0,data)
因此在NIOSII中可以调用#include库函数IORD/IOWR来操作PIO。
在smallsoftwarehello_led_0_syslibDebugsystem_description下的system.h中,有以下内容:
#defineLED_PIO_TYPE"altera_avalon_pio"
#defineLED_PIO_BASE0x00004000
其中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.出错信息如下:
Linkinghello_world_0.elf...
/cygdrive/e/DE2Project_restored/software/hello_world_0_syslib/Debug/libhello_world_0_syslib.a(alt_main.o)(.text+0x60):
Infunction`alt_main':
/cygdrive/c/altera/72/nios2eds/components/altera_hal/HAL/src/alt_main.c:
163:
undefinedreferenceto`main'
collect2:
ldreturned1exitstatus
make:
***[hello_world_0.elf]Error1
Buildcompletedin1.953seconds
答:
将主函数名字写错了.
应该写成intmain(void),结果写成了intmian()
4.IOWR_ALTERA_AVALON_PIO_DATA怎么使用?
答:
IOWR_ALTERA_AVALON_PIO_DATA是一个宏定义,其位置在altera_avalon_pio_regs.h中,另外还要参考io.h头文件。
NiosIIIDE为了避开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的官方网站上下载。
NIOS_II学习笔记:
在这里先简单介绍一下各头文件的作用,
这个头文件包含了标准输入、输出、错误函数库;"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"中有如下定义
#defineIOWR_ALTERA_AVALON_PIO_IRQ_MASK(base,data)IOWR(base,2,data)
#defineIOWR_ALTERA_AVALON_PIO_EDGE_CAP(base,data)IOWR(base,3,data)
#defineIORD_ALTERA_AVALON_PIO_EDGE_CAP(base)IORD(base,3)
第一个函数是使能中断函数,是按位来势能的,比如0xf表示四位全部使能,而0x7表示使能低3位中断;
第二个函数是设置边沿捕获寄存器函数,用来重新设定寄存器的值;一般在读取之后会重新设定为0;
第三个函数是读取边沿捕获寄存器函数,用来读取寄存器的值;
下面是alt_irq_register函数的原形,此函数用来声明ISR,在软使用IRS之前一定要先声明;
externintalt_irq_register(alt_u32id,
void*context,
void(*irq_handler)(void*,alt_u32));
一般在开发按键中断程序时,handle_button_interrupts()和init_button_pio()这两个函数直接使用,不用再编辑。
系统配置文件如下:
1.流水灯
#include"system.h"
#include"altera_avalon_pio_regs.h"
#include"alt_types.h"
#include"stdio.h"
#include"unistd.h"
intmain(void)__attribute__((weak,alias("alt_main")));
intalt_main(void)
{
unsignedcharled=0;while
(1)
{
for(led=0;led<8;led++)
{
IOWR_ALTERA_AVALON_PIO_DATA(LED_GREEN_BASE,1< usleep(500000);//延时0.5秒
}
}
return0;
}
2.流水灯
count_binary.h文件#ifndefCOUNT_BINARY_H_
#defineCOUNT_BINARY_H_
#include"alt_types.h"
#include
#include
#include"system.h"
#include"sys/alt_irq.h"
#include"altera_avalon_pio_regs.h"
#defineESC27
#defineESC_TOP_LEFT"[1;0H"
#defineESC_COL2_INDENT5"[2;5H"
#defineESC_CLEAR"K"
#defineECS_COL1_INDENT5"[1;5H"
#endif/*COUNT_BINARY_H_*/main.c文件:
#include"count_binary.h"
intmain(void)
{
inti;
intdata;
while
(1)
{
i=0;
data=
for(i=0;i<8;i++)
{
IOWR(LED_GREEN_BASE,0,data);
data>>=1;
usleep(500000);
}
}
}/*注:
函数原型:
IOWR(BASE,REGNUM,DATA)
输入参数:
BASE为寄存器的基地址,REGNUM为寄存器的偏移量,DATA为要写入的数据
函数说明:
往偏移量为REGNUM寄存器中写入数据。
寄存器的值在地址总线的范围之内。
返回值:
*/
3.独立键盘
count_binary.h文件见上
main.c文件
/*
硬件环境:
DE2开发板
按键未按时是高电平
按下后是低电平
4个按键控制4个灯(配置的系统有八个灯,4个键只点亮高四位的灯)
*/
#include"count_binary.h"
intalt_main()
{
intkey,data;
data=
while
(1)
{
key=IORD(BUTTON_PIO_BASE,0);
if(key==0x7)
data=
key=IORD(BUTTON_PIO_BASE,0);
if(key==0xb)
data=
key=IORD(BUTTON_PIO_BASE,0);
if(key==0xd)
data=
key=IORD(BUTTON_PIO_BASE,0);
if(key==0xe)
data=
IOWR(LED_GREEN_BASE,0,data);
}
}
/*
IO操作函数
函数原型:
IORD(BASE,REGNUM)
输入参数:
BASE为寄存器的基地址,REGNUM为寄存器的偏移量
函数说明:
从基地址为BASE的设备中读取寄存器中偏移量为REGNUM的单元里面的值。
寄存器的值在地址总线的范围之内。
返回值:
-
*/说明:
下面的程序采用的是另一套配置文件,即ptf文件同上面的不同,是DE2开发板自带的,用起来挺方便!
4.外部中断点亮数码管
/*
硬件环境:
DE2开发板
四个按键对应着四个不同的外部中断
通过不同的按键在数码管上面显示不同的数字
*/
#include"count_binary.h"
volatileintedge_capture;
/*外部中断服务子函数声明(与单片机不同,这里需要声明一下)*/
staticvoidhandle_button_interrupts(void*context,alt_u32id);
/*按键初始化*/
staticvoidinit_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);
}
/*主函数*/
intmain(void)
{
init_button_pio();
while
(1)
{
switch(edge_capture)
{
/*按键3按下时8个数码管全部显示1*/
case0x08:
IOWR(SEG7_DISPLAY_BASE,0,0x11111111);
break;
case0x04:
IOWR(SEG7_DISPLAY_BASE,0,0X22222222);
break;
case0x02:
IOWR(SEG7_DISPLAY_BASE,0,0X33333333);
break;
/*按键0按下时8个数码管全部显示4*/
case0x01:
IOWR(SEG7_DISPLAY_BASE,0,0x44444444);
break;
}
}
}
/*外部中断服务子函数*/
staticvoidhandle_button_interrupts(void*context,alt_u32id)
{
volatileint*edge_capture_ptr=(volatileint*)context;
/*键按键的值存储到边沿捕获寄存器中*/
*edge_capture_ptr=IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE);
/*复位边沿捕获寄存器*/
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE,0);
}5.定时器
#include"count_binary.h"
intalt_main()
{
intsecond=0;
while
(1)
{
usleep(100000);
second++;
IOWR(SEG7_DISPLAY_BASE,0,second);
}
}
6.1602液晶驱动程序
lcd.h文件#ifndefLCD_H_
#defineLCD_H_
#definelcd_write_cmd(base,data)IOWR(base,0,data)
#definelcd_read_cmd(base)IORD(base,1)
#definelcd_write_data(base,data)IOWR(base,2,data)
#definelcd_read_data(base)IORD(base,3)
voidlcd_init();
voidlcd_show_text(char*text);
voidlcd_line2();
voidlcd_test();
#endif/*LCD_H_*/
main.c文件/*硬件环境:
DE2开发板
*软件环境:
quatersII7.2,NIOSII7.2
*函数功能:
1602液晶驱动程序
*/
#include
#include
#include
#include"system.h"
#include"lcd.h"
voidlcd_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);
}
/*显示一行字符*/
voidlcd_show_text(char*text)
{
inti;
for(i=0;i {
lcd_write_data(LCD_16207_0_BASE,text[i]);
usleep(2000);
}
}
voidlcd_line1()
{
lcd_write_cmd(LCD_16207_0_BASE,0X80);
usleep(2000);
}
/*换行,即切换到第二行*/
voidlcd_line2()
{
lcd_write_cmd(LCD_16207_0_BASE,0XC0);
usleep(2000);
}
intmain()
{
chartext1[16]="WuQinDeShi";
chartext2[16]="Jie,WuQinDeNi";
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("LiuYaLi,");
lcd_line2();
/*显示第二行字符*/
lcd_show_text("ILoveYou!
");
usleep(4000000);
}
return0;
}7.1602用NIOSII的fprintf标准函数控制显示
/*硬件环境:
DE2开发板
*软件环境:
quatersII7.2,NIOSII7.2
*函数功能:
1602液晶驱动程序
*使用NIOSII的fprintf标准函数对lcd编程比较简单!
*/
#include
#include
#include
#include
#include"system.h"
intmain(void)
{
FILE*lcd;
lcd=fopen("/dev/lcd_16207_0","w");
/*1602液晶第一行显示的内容*/
fprintf(lcd,"IloveNIOSII!
\n");
/*1602液晶第二行显示的内容*/
fprintf(lcd,"Iloveyou!
");
fclose(lcd);
return0;
}
8.综合例程
count_binary.h文件#ifndefCOUNT_BINARY_H_
#defineCOUNT_BINARY_H_
#include"alt_types.h"
#include
#include
#include"system.h"
#include"sys/alt_irq.h"
#include"altera_avalon_pio_regs.