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、完成