NIOS II实现LED流水灯以及串口输出(DE2-115开发板)

前言

具体的软件和硬件配置流程看下方的博客很详细,我主要讲一下这些博客没说到的部分和我做的过程中遇到的一些错误,看了下面的博客做不出来可以看我的补充
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 具有以下特点和优势:

  1. 可编程性:NIOS II 处理器可以通过软件进行配置和编程,使其适应不同的应用需求。开发人员可以使用高级语言(如C/C++)编写应用程序,并通过软件开发工具链进行编译、调试和部署。

  2. 灵活性:NIOS II 处理器的各种参数(如指令集、存储器大小和外设接口等)可以根据特定应用的需求进行配置和定制。这使得 NIOS II 可以满足广泛的应用要求,从简单的控制任务到复杂的嵌入式系统设计。

  3. 可扩展性:NIOS II 处理器可以与其他外设和IP核集成,以实现更复杂的系统功能。它可以与各种外设接口(如UART、SPI、I2C等)和存储器接口(如SDRAM、Flash等)进行集成,并支持多个中断源和异常处理。

  4. 性能优化:NIOS II 处理器具有优化的指令集和流水线架构,可提供高性能的处理能力。它支持多级缓存和乱序执行等技术,以提高指令执行效率。

  5. 生态系统支持: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;
}
  • 15
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是实现代码: ``` #include "altera_up_avalon_parallel_port.h" // 导入并口操作库 #define LED_NUM 5 // LED 数量 alt_up_parallel_port_dev *leds; // 保存并口设备指针 void init_leds() { leds = alt_up_parallel_port_open_dev("/dev/leds"); // 打开并口设备 alt_up_parallel_port_set_direction(leds, 0x00); // 将并口设为输出模式 } void set_led(int led_num, int on) { int led_mask = 0x01 << led_num; // 根据 LED 编号计算掩码 if (on) { alt_up_parallel_port_write_data(leds, led_mask); // 点亮 LED } else { alt_up_parallel_port_write_data(leds, 0x00); // 先将所有 LED 熄灭,避免出错 // 按优先级顺序,逐个点亮优先级高的 LED for (int i = 0; i < LED_NUM; i++) { if ((led_mask << i) & (0x1F)) { // 根据 LED 掩码,判断该位是否需要点亮 alt_up_parallel_port_write_data(leds, led_mask << i); // 点亮 LED } } } } int main() { init_leds(); // 初始化并口 while (1) { // 不停运行 // 依次点亮 / 熄灭 LED。 // 优先级分别为 1~5,最高优先级为 5。 set_led(4, 1); set_led(3, 1); set_led(2, 1); set_led(1, 1); set_led(0, 1); usleep(500000); // 持续时间 500ms set_led(4, 0); usleep(20000); // 暂停 20ms,模拟优先级下降的时间 set_led(3, 0); usleep(20000); set_led(2, 0); usleep(20000); set_led(1, 0); usleep(20000); set_led(0, 0); usleep(500000); } return 0; } ``` 在本代码中,我们使用 Altera 公司的 Nios II 开发板,并通过并口控制 5 个 LED 灯的亮灭。每个 LED 都有一个优先级(在本代码中,优先级值越大,表示该 LED 的优先级越高)。当某个 LED 需要亮起时,根据其优先级,逐个点亮优先级高的 LED;当某个 LED 需要熄灭时,则先熄灭其优先级低的兄弟 LED,再一次熄灭该 LED。 在代码中,首先根据 LED 的编号计算出相应的 LED 掩码,然后通过 Altera 公司的并口库将 LED 控制信号写入硬件。函数 `usleep()` 用于控制 LED 点亮 / 熄灭的时间,从而模拟跑灯效果。 这个例子比较简单,但也展示了使用 C 语言开发嵌入式系统的基本方法。如果您有更多的问题,欢迎继续向我提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值