基于DE2-115的Nios V工程(三)——按键和定时器中断控制的时钟(二)

本文将接着《基于DE2-115的Nios V工程—按键和定时器中断控制的时钟(一)》继续介绍实验的详细操作步骤,包括创建Quartus硬件工程、Nios V系统、Nios V软件工程以及配置FPGA上板测试。

一、创建Quartus工程

1. 参考《基于DE1-SOC的Nios V工程——My First Nios V》四、Quartus工程设计这一节的步骤,使用Quartus Standard Edition v22.1创建Quartus硬件工程KEY_Timer,FPGA器件选择DE2-115的Cyclone IV E EP4CE115F29C7,打开Quartus硬件工程。

图片

2. 在Quartus工程路径下创建一个文件夹命名为ip,再将《基于DE2-115的Nios V工程—数码管显示》Quartus工程里的TERASIC_SEG7文件夹复制到刚才创建的ip文件夹里。

图片

二、创建Nios V系统

1. 参考《基于DE1-SOC的Nios V工程——My First Nios V》,添加Nios V/m Processor Intel FPGA IP、On-Chip Memory (RAM or ROM) Intel FPGA IP以及JTAG UART Intel FPGA IP。其中On-Chip Memory (RAM or ROM) Intel FPGA IP的Total Memory Size修改为204800,其余IP等参数不变。

图片

2. 添加自定义Seg7_IF IP组件:在Terasic Technologies Inc./DE2-115里可以看到自定义创建的SEG7_IF IP组件,双击添加该IP,保持默认参数不变。

图片

3. 搜索PIO Intel FPGA IP并双击添加,width改为4,direction为Input;并勾选Synchronously capture,Edge Type为FALLING,勾选Generate IRQ,IRQ Type为EDGE。

图片

4. 搜索并添加Interval Timer IP组件,保持默认参数设置不变。

图片

5. 依次将clk_0、intel_niosv_m_0、onchip_memory2_0、jtag_uart_0、SEG7_IF_0、pio_0以及timer_0重命名为clk、intel_niosv_m、onchip_memory2、jtag_uart、SEG7、key以及timer。

图片

6. 按下图所示连接各IP,最后双击箭头处将SEG7以及key导出。

图片

7. 修改Nios V/m IP的参数设置,勾选Enable Reset from Debug Module,Reset Agent选择onchip_memory2.s1。

图片

8. 点击Platform Designer的菜单System—— Assign Base Addresses给每个模块分配地址空间。

图片

9. Message栏仍然有错误提示,将intel_niosv_m的ndm_reset_in信号与系统rest信号连接起来。最后点击窗口右下角的Generate HDL按钮生成qsys文件。

10. 将Nios V系统添加到顶层设计,点击Quartus菜单Project——Add/remove Files in Project...,将niosv.qsys文件就可以将该文件添加进工程里面去。

图片

11. 点击Quartus菜单File——>New——>Verilog HDL File——>OK,创建niosv_hex.v顶层文件。在该.v文件里面输入如下代码并保存。

module KEY_Timer(
  input CLOCK_50,
  input  [3:0] KEY,
  output [6:0] HEX0,
  output [6:0] HEX1,
  output [6:0] HEX2,
  output [6:0] HEX3,
  output [6:0] HEX4,
  output [6:0] HEX5,
  output [6:0] HEX6,
  output [6:0] HEX7
);

 7-SEG //
wire HEX0P;
wire HEX1P;
wire HEX2P;
wire HEX3P;
wire HEX4P;
wire HEX5P;
wire HEX6P;
wire HEX7P;

niosv u0 (
  .clk_clk(CLOCK_50),             //clk.clk
  .reset_reset_n(1'b1),           //reset.reset_n
  .seg7_conduit_end_export({
              HEX7P,HEX7,HEX6P,HEX6,
              HEX5P,HEX5,HEX4P,HEX4,
              HEX3P,HEX3,HEX2P,HEX2,
              HEX1P,HEX1,HEX0P,HEX0}),        //seg7_conduit_end.export
  .key_external_connection_export (KEY)  // key_external_connection.export
);

endmodule

12. 点击Analysis & Synthesis进行分析与综合。

图片

13. 按DE2-115开发板的相关引脚进行引脚分配,具体内容如下;最后再点击Start Compilation图标编译Quartus工程,最终生成.sof文件。

图片

图片

三、创建Nios V软件工程

1. 参考《基于DE1-SOC的Nios V工程——My First Nios V》五、创建Nios V 软件工程这一节步骤,在KEY_Timer工程文件夹路径下新建software文件。

2. 运行niosv-bsp -c -t=hal --sopcinfo=niosv.sopcinfo software/interrupt_clock_bsp/settings.bsp命令在software文件夹创建Nios V BSP。

图片

图片

3. 在software文件夹路径下再创建interrupt_clock文件夹,并在interrupt_clock文件夹下创建空白main.c文件。

4. 运行niosv-app -a=software/interrupt_clock -b=software/interrupt_clock_bsp -s=software/interrupt_clock/main.c命令在interrupt_clock文件夹生成CMakeLists.txt文件。

图片

图片

5. 打开Quartus v22.1.2下的RiscFree IDE,workspace指向software文件夹路径。然后点击Launch启动软件。

图片

6. 点击Create a project,在New Project窗口,选择C/C++下的C Project;在打开的C Project窗口,Project name命名为interrupt_clock,Location指向interrupt_clock所在文件夹,Project Type选择CMake driven下的Empty Project;接下来的Select Configurations窗口保持默认设置不变,点击Finish即可。

图片

7. 在main.c文件里面添加上一期1.3.2小节的代码1并保存。如下所示代码:

#include <stdio.h>
#include "system.h"
#include "alt_types.h"
#include "sys/alt_irq.h"
#include "altera_avalon_pio_regs.h"
#include "altera_avalon_timer_regs.h"

alt_u16 flag_second;        //计时器1s标志位
alt_u8  edge_capture_value;      //存储按键边沿捕获寄存器中的值
alt_u16 second;            //计时60s判断
alt_u16 minute;            //计时60分钟
alt_u16 hour;            //计时24小时
alt_u16 running=1;          //时钟运行状态,1表示运行,0表示暂停
alt_u8 seg[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};  //数码管段显示0~9定义

/*按键中断服务程序*/
static void key_interrupts(void* isr_context){
  edge_capture_value = IORD(KEY_BASE, 3);  //读取边沿捕获寄存器中的值,存到edge_capture_value
  IOWR(KEY_BASE, 3, 0x0);              //清除边沿捕获寄存器
    if (edge_capture_value) {           //edge_capture_value为非0
        running = !running;           //切换Timer运行状态
    }
}

/*按键I/O初始化*/
void init_key(){
  edge_capture_value = 0x00;          //edge_capture_value清0
  IOWR(KEY_BASE, 2, 0xf);              //使能4个按键中断
  IOWR(KEY_BASE, 3, 0x0);              //清除边沿捕获寄存器
  alt_ic_isr_register(            //注册中断函数
    KEY_IRQ_INTERRUPT_CONTROLLER_ID,
    KEY_IRQ,
    key_interrupts,
    NULL, 0x0);
}

//定时器中断服务程序
static void handle_Timer_interrupts(void* isr_context)
{
  IOWR(TIMER_BASE, 0, 0x00);      //清除状态寄存器
  if(running){
    if(flag_second < 1000)
      flag_second++;  //计时1s,定时器中断默认周期值为1ms,则计数1000次就为1s
  else
  {
    flag_second = 0;
    second++;
  }                  //每计时1s,second递增1
  if(second > 59)
  {
    second = 0;
    minute++;
  }                  //计时60秒
  if(minute > 59)
  {
    minute = 0;
    hour++;
  }                  //计时60分钟
  if(hour > 23)
  {
    hour = 0;
  }                  //计时24小时
  }
}

//定时器初始化
void init_timer(void)
{
  IOWR(TIMER_BASE, 0, 0x00);      //清除状态寄存器
  IOWR(TIMER_BASE, 1, 0x07);      //使能中断,启动计数器开始计数并连续运行
  alt_ic_isr_register(        //注册中断函数
    TIMER_IRQ_INTERRUPT_CONTROLLER_ID,
    TIMER_IRQ,
    handle_Timer_interrupts,
    NULL, 0x00);
}

//主函数
int main (void)
{
  printf("Use the Interval Timer to implement a 24-hour clock and display on the 7-segment displays.\n");      //在Nios V Command Shell窗口打印信息
  flag_second = 0;

    init_timer();                  //初始化定时器
  init_key();                  //初始化按键I/O

    while(1)
    {
      IOWR(SEG7_BASE, 0, seg[second%10]);    //将时钟的秒钟的个位显示在HEX0上
      IOWR(SEG7_BASE, 1, seg[second/10]);    //将时钟的秒钟的十位显示在HEX1上
      IOWR(SEG7_BASE, 2, seg[minute%10]);    //将时钟的分钟的个位显示在HEX2上
      IOWR(SEG7_BASE, 3, seg[minute/10]);    //将时钟的分钟的十位显示在HEX3上
      IOWR(SEG7_BASE, 4, seg[hour%10]);    //将时钟的小时的个位显示在HEX4上
      IOWR(SEG7_BASE, 5, seg[hour/10]);    //将时钟的小时的十位显示在HEX5上
    }
    return 0;
}

图片

8. 左键选中interrupt_clock,点击Build Project编译main.c,编译完成可以看到生成interrupt_clock.elf文件。

图片

四、配置FPGA与测试

1. 点击Quartus软件工具栏的Tools--> Programmer,烧录Quartus硬件工程的KEY_Timer.sof文件。

图片

2. 在Nios V Command Shell里运行juart-terminal。

图片

3. 在RiscFree IDE窗口左键选中interrupt_clock,选择菜单里的Run As-->3 Ashling RISC-V(auto-detect)Hardware Debugging,烧录.elf并运行程序。

图片

图片

4. 运行完成后在Nios V Command Shell会打印输出:Use the Interval Timer to implement a 24-hour clock and display on the 7-segment displays.

图片

5. 在DE2-115开发板会观察到以下现象:

  • HEX[1:0]显示时钟的秒,每隔一秒计数值加1,从0~59循环计数;

  • HEX[3:2]显示时钟的分,秒钟计数每计数60秒,分钟的值加1,从0~59循环计数;

  • HEX[5:4]显示时钟的时,分钟每计数60分,时钟的值加1,从0~24循环计数。

  • 按KEY[3:0]中的任意一个,时钟暂停运行;再按任意一个,时钟从暂停的时间开始恢复运行。

图片

  • 31
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值