NIOS II 7:中断方式串口接收、发送。时序约束添加

本文详细介绍了在Quartus和NIOS II环境中实现串口接收与发送的步骤,包括设置中断、配置波特率、数据处理以及时序约束。通过实例展示了如何配置接收和发送中断,以及关键代码片段的实现和调试过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

quartus里边和NIOS II 6里边一摸一样

串口接收

1、使能接收中断 

      IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE,0x0080);            //使能接收中断

2、中断定义如下

        char *p;
        alt_ic_isr_register    (UART_0_IRQ_INTERRUPT_CONTROLLER_ID,      //ID
                                UART_0_IRQ,                              //中断号
                                uart_0_isr,                            //中断服务函数
                                p,                                        //传参
                                0);                                       //输出

 

3、最终程序如下,按键中断实际没使用暂时,

#include "sys/alt_stdio.h"
#include "altera_avalon_uart_regs.h"
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_irq.h"

alt_u8 rxbuff[100];
alt_u8 jj;
alt_isr_func uart_0_isr(void)
{
      alt_u16 status;
      status=IORD_ALTERA_AVALON_UART_STATUS(UART_0_BASE);      //读状态寄存器
      if(status&ALTERA_AVALON_UART_STATUS_RRDY_MSK)            //RRDY为1代表串口有数据
      {
          rxbuff[jj]=IORD_ALTERA_AVALON_UART_RXDATA(UART_0_BASE);    //读取串口数据
          jj++;
      }
    return 0;
}

void uart_0_int()
{
          alt_u8 rxdata;
        IOWR_ALTERA_AVALON_UART_STATUS(UART_0_BASE,0x0000);             //清状态寄存器
        rxdata=IORD_ALTERA_AVALON_UART_RXDATA(UART_0_BASE);               //清空rxdata寄存器
        IOWR_ALTERA_AVALON_UART_DIVISOR(UART_0_BASE,ALT_CPU_CPU_FREQ/115200-1);  //设置波特率
        IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE,0x0080);            //使能接收中断
        char *p;
        alt_ic_isr_register    (UART_0_IRQ_INTERRUPT_CONTROLLER_ID,      //ID
                                UART_0_IRQ,                              //中断号
                                uart_0_isr,                            //中断服务函数
                                p,                                        //传参
                                0);                                       //输出
}

alt_u8        led_en1;
alt_isr_func key_isr(void)                                      //按键中断入口函数
{
    alt_u8      data;
    IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PIO_LED_BASE,0x00);       //关闭所有中断,保护现场
    data=IORD_ALTERA_AVALON_PIO_EDGE_CAP(PIO_LED_BASE);       //读边沿捕获寄存器

    if(data&0x10)                                             //捕获到KEY1有上升沿
    {
       led_en1=0x00;
    }
    else if(data&0x20)                                        //捕获到KEY2有上升沿
    {
       led_en1=0x01;
    }
    else if(data&0x40)                                        //捕获到KEY3有上升沿
    {
       led_en1=0x02;
    }
    else if(data&0x80)                                        //捕获到KEY4有上升沿
    {
       led_en1=0x03;

    }
    IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_LED_BASE,0xf0);       //清零边沿捕获寄存器捕获位
    IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PIO_LED_BASE,0xf0);       //打开中断
    return  0;
}
void key_int()                                                              //按键LED初始化
{
        char *p;
        alt_ic_isr_register    (PIO_LED_IRQ_INTERRUPT_CONTROLLER_ID,      //ID
                                PIO_LED_IRQ,                              //中断号
                                key_isr,                                  //中断服务函数
                                p,                                        //传参
                                0);                                       //输出
        IOWR_ALTERA_AVALON_PIO_DIRECTION(PIO_LED_BASE,0x0f);            //高四位输入,低四位输出
        IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PIO_LED_BASE,0xf0);             //0:关闭中断,1打开中断。打开所有四个KEY中断
        IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_LED_BASE,0xf0);             //上电清零边沿捕获寄存器捕获位
}


int main()
{
  key_int()    ;
  uart_0_int();
  while (1)
  {
    if(led_en1==1)
    {
        led_en1=0;
        jj=0;
    }
    else
    {
        led_en1=0x55;
    }
  }
  return 0;
}


4、仿真看到结果如下,仿真的时候运行起来,然后发送串口数据,之后才能在 led_en1=0x55;这句话处打断点,这时候鼠标移动到 rxbuff上能看到数据如下图

 

 

4、也可以通过下图中memory,加号,然后写入rxbuff来看这个数。但是注意,运行以后一定要打断点停下来,才会更新数据

 

 

串口发送

1、上面基础上,file-new-nios II application

bsp选默认就可以如下

2、右键新建的工程,properties,把BSP关联起来,勾选上

3、拷贝1到2,之后如下图,删除原来的那个工程。只是描述一个新建过程,跟别的无关。

 

3、使能接收和发送中断

IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE,0x00C0);            //使能接收和发送中断

4、程序如下,过程就是使能发送中断,开始发送以后记录发送长度,长度够了以后,关闭发送中断即可。

#include "sys/alt_stdio.h"
#include "altera_avalon_uart_regs.h"
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "sys/alt_irq.h"

alt_u8 rxbuff[100];
alt_u8 txbuff[100];
alt_u8 txlen;
alt_u8 jj;
alt_isr_func uart_0_isr(void)
{
      alt_u16 status;
      status=IORD_ALTERA_AVALON_UART_STATUS(UART_0_BASE);      //读状态寄存器
      if(status&ALTERA_AVALON_UART_STATUS_RRDY_MSK)            //RRDY为1代表串口有数据
      {
          rxbuff[jj]=IORD_ALTERA_AVALON_UART_RXDATA(UART_0_BASE);    //读取串口数据
          jj++;
      }
      if(status&ALTERA_AVALON_UART_STATUS_TRDY_MSK)            //发送中断
      {
          if(txlen>0)
          {
              IOWR_ALTERA_AVALON_UART_TXDATA(UART_0_BASE, txbuff[txlen]);
              txlen--;
              if(txlen==0)
              {
                  IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE,0x0080);            //关闭发送中断,但是不能影响接收中断
              }
          }
      }
    return 0;
}

void uart_0_int()
{
          alt_u8 rxdata;
        IOWR_ALTERA_AVALON_UART_STATUS(UART_0_BASE,0x0000);                 //清状态寄存器
        rxdata=IORD_ALTERA_AVALON_UART_RXDATA(UART_0_BASE);                   //清空rxdata寄存器
        IOWR_ALTERA_AVALON_UART_DIVISOR(UART_0_BASE,ALT_CPU_CPU_FREQ/115200-1);  //设置波特率
        IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE,0x0080);            //使能接收中断\使能发送中断
        char *p;
        alt_ic_isr_register    (UART_0_IRQ_INTERRUPT_CONTROLLER_ID,          //ID
                                UART_0_IRQ,                                  //中断号
                                uart_0_isr,                                    //中断服务函数
                                p,                                            //传参
                                0);                                           //输出
}

void uart_tx(alt_u8 *data,alt_u8 length)
{
    alt_u8 i;
    for(i=0;i<length;i++)
    {
        txbuff[length-i]=data[i];                                       //倒过来赋值,是为了发送时候方便一些
    }
    txlen=length;
    IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE,0x0080|0x0040);            //使能接收中断\使能发送中断

}

alt_u8        led_en1;
alt_isr_func key_isr(void)                                      //按键中断入口函数
{
    alt_u8      data;
    IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PIO_LED_BASE,0x00);       //关闭所有中断,保护现场
    data=IORD_ALTERA_AVALON_PIO_EDGE_CAP(PIO_LED_BASE);       //读边沿捕获寄存器

    if(data&0x10)                                             //捕获到KEY1有上升沿
    {
       led_en1=0x00;
    }
    else if(data&0x20)                                        //捕获到KEY2有上升沿
    {
       led_en1=0x01;
    }
    else if(data&0x40)                                        //捕获到KEY3有上升沿
    {
       led_en1=0x02;
    }
    else if(data&0x80)                                        //捕获到KEY4有上升沿
    {
       led_en1=0x03;

    }
    IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_LED_BASE,0xf0);       //清零边沿捕获寄存器捕获位
    IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PIO_LED_BASE,0xf0);       //打开中断
    return  0;
}
void key_int()                                                              //按键LED初始化
{
        char *p;
        alt_ic_isr_register    (PIO_LED_IRQ_INTERRUPT_CONTROLLER_ID,      //ID
                                PIO_LED_IRQ,                              //中断号
                                key_isr,                                  //中断服务函数
                                p,                                        //传参
                                0);                                       //输出
        IOWR_ALTERA_AVALON_PIO_DIRECTION(PIO_LED_BASE,0x0f);            //高四位输入,低四位输出
        IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PIO_LED_BASE,0xf0);             //0:关闭中断,1打开中断。打开所有四个KEY中断
        IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_LED_BASE,0xf0);             //上电清零边沿捕获寄存器捕获位
}


int main()
{
  alt_u8      data[100]={0x55,0x66,0x77,0x88,0x99};
  alt_u32   kk;
  key_int()    ;
  uart_0_int();
  while (1)
  {
        led_en1=0x55;
        uart_tx(data,5);
        kk=0; while(kk<500000) {kk++;}
  }
  return 0;
}


 

5、结果如下。此时debug测试接收中断也是没问题的

 

 

时序约束

1、tools---打开如下界面

2、contraints---create clock

3、弹出界面点击ok

4、约束文件加入工程

5、完成

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值