NIOS II实现LED流水灯以及串口输出(DE2-115开发板)
- 前言
- 什么是Qsys?
- 什么是NIOSII?
- 注意事项
- 1、管脚配置
- 2、配置NIOSII时的连接
- 3、注意中断配置好后是这样的
- 4、注意名称的配置
- 5、设置双功能引脚
- NIOS II的报错
- 代码以及效果演示
- 流水灯
- 输出到电脑串口助手
前言
具体的软件和硬件配置流程看下方的博客很详细,我主要讲一下这些博客没说到的部分和我做的过程中遇到的一些错误,看了下面的博客做不出来可以看我的补充
https://blog.csdn.net/qq_43279579/article/details/115953871
https://blog.csdn.net/qq_57160761/article/details/129989171
https://blog.csdn.net/weixin_54435584/article/details/130025896
https://www.bilibili.com/video/BV1Lc411y7o6/
什么是Qsys?
Qsys(前身为 SOPC Builder)是一种用于硬件系统设计的集成开发环境(IDE),由英特尔(Intel)提供。它是一种可视化工具,用于在FPGA(可编程逻辑器件)中构建和配置嵌入式系统的硬件组件。
通过 Qsys,开发人员可以通过图形界面进行硬件组件的选择、连接和配置,而无需手动编写HDL(硬件描述语言)代码。Qsys 提供了丰富的硬件组件库,其中包括处理器核、存储器控制器、外设接口等,开发人员可以根据项目需求选择合适的组件。
Qsys中的硬件组件库中包含了NIOS II处理器核,因此可以在Qsys中选择和配置NIOS II作为嵌入式系统的处理器。通过Qsys,开发人员可以将NIOS II与其他硬件组件进行连接和集成,构建一个完整的嵌入式系统。Qsys会自动生成与NIOS II相关的硬件描述语言代码,并与软件开发工具链进行集成,使得软硬件开发可以无缝配合。
什么是NIOSII?
NIOS II(New Integrated Open System Architecture II)是一种基于软件可编程的嵌入式处理器架构,由英特尔(Intel)提供。它是一种可在可编程逻辑器件(如FPGA)中实现的32位RISC(精简指令集计算机)处理器。
NIOS II 具有以下特点和优势:
-
可编程性:NIOS II 处理器可以通过软件进行配置和编程,使其适应不同的应用需求。开发人员可以使用高级语言(如C/C++)编写应用程序,并通过软件开发工具链进行编译、调试和部署。
-
灵活性:NIOS II 处理器的各种参数(如指令集、存储器大小和外设接口等)可以根据特定应用的需求进行配置和定制。这使得 NIOS II 可以满足广泛的应用要求,从简单的控制任务到复杂的嵌入式系统设计。
-
可扩展性:NIOS II 处理器可以与其他外设和IP核集成,以实现更复杂的系统功能。它可以与各种外设接口(如UART、SPI、I2C等)和存储器接口(如SDRAM、Flash等)进行集成,并支持多个中断源和异常处理。
-
性能优化:NIOS II 处理器具有优化的指令集和流水线架构,可提供高性能的处理能力。它支持多级缓存和乱序执行等技术,以提高指令执行效率。
-
生态系统支持:NIOS II 处理器拥有丰富的生态系统支持,包括软件开发工具、开发板、外设驱动库和参考设计等。这些资源使得开发人员能够更快速、高效地进行嵌入式系统开发。
NIOS II 处理器广泛应用于各种嵌入式系统领域,例如工业自动化、网络通信、医疗设备、汽车电子、消费类电子产品等。它提供了一种灵活可靠的解决方案,帮助开发人员构建高性能、低功耗的嵌入式系统。
注意事项
1、管脚配置
开发板上有个RS232的接口,我想用电脑串口输出,因为手头没有RS232所以需要引出RX和TX用TTL-USB,这里我查阅原理图引到IO_D0和IO_D1
2、配置NIOSII时的连接
注意这里是需要export的用于配置RX和TX引脚,export之后会有一个小标签,
3、注意中断配置好后是这样的
4、注意名称的配置
如果你的PIO名字没有设置好,这个位置可能会报错
到头文件里找到宏定义后替换即可
5、设置双功能引脚
NIOS II的报错
build project之后要注意看这两个位置有没有爆红,这个不会在console控制台提示报错,一般build得很快就有问题
代码以及效果演示
流水灯
nios2_flow_led
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "alt_types.h"
const alt_u8
led_data[8]={0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF};
int main (void)
{
int count=0;
alt_u8 led;
volatile int i;
while (1)
{ if (count==7)
{count=0;}
else
{count++;}
led=led_data[count];
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, led);
i = 0;
while (i<500000)
i++;
}
return 0;
}
输出到电脑串口助手
#include <stdio.h>
#include "unistd.h"
#include "system.h"
#include "alt_types.h"
#include "altera_avalon_uart_regs.h"
#include "sys/alt_irq.h"
alt_u8 txdata[] = "hello nios2\n";
int index = 0;
// UART中断服务函数
void IRQ_UART_Interrupts(void* context)
{
alt_u32 status = IORD_ALTERA_AVALON_UART_STATUS(UART_BASE);
if (status & ALTERA_AVALON_UART_STATUS_RRDY_MSK)
{
//rxdata = IORD_ALTERA_AVALON_UART_RXDATA(UART_BASE);
//txdata = rxdata; // 串口自收发,将变量rxdata的值赋给txdata
while (!(IORD_ALTERA_AVALON_UART_STATUS(UART_BASE) & ALTERA_AVALON_UART_STATUS_TRDY_MSK));
// 查询发送准备接收信号,如果没有准备好,则等待
IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE, txdata); // 发送准备好,发送txdata
}
}
// 中断初始化函数
void IRQ_init()
{
// 清除状态寄存器
IOWR_ALTERA_AVALON_UART_STATUS(UART_BASE, 0);
// 使能接收准备中断,给控制寄存器相应位写1
IOWR_ALTERA_AVALON_UART_CONTROL(UART_BASE, ALTERA_AVALON_UART_CONTROL_RRDY_MSK);
alt_ic_isr_register(
UART_IRQ_INTERRUPT_CONTROLLER_ID, // 注册ISR
UART_IRQ, // 中断控制器标号,从system.h复制
IRQ_UART_Interrupts, // UART中断服务函数
NULL, // 指向与设备驱动实例相关的数据结构体
NULL); // flags,保留未用
}
int main()
{
IRQ_init();
while (1)
{
IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE, txdata[index]);
index++;
if (txdata[index] == '\0')
index = 0;
usleep(100000); // 延时等待
}
return 0;
}