[FPGA开发] 【工程源码】NIOS II下基于中断的UART接收和发送设计示例代码

小梅哥   2020-2-25 18:58 楼主

本文和设计代码由FPGA爱好者小梅哥编写,未经作者许可,本文仅允许网络论坛复制转载,且转载时请标明原作者。
 

 

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

alt_u8 uart_en = 0;
alt_u8 i=0;
alt_u8 rx_data[256],tx_data[256];
alt_u8 tx_len,rx_len;

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 == 0x30)
    {

    }
    else if(data & 0x10)
    {
        uart_en = 1;
    }
    else if(data & 0x20)
    {

    }
    IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_LED_BASE, 0x30);    //清零所有的捕获位
    IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PIO_LED_BASE, 0x30);    //关闭按键中断
    return 0;
}

void key_init()
{
    char *p;
    alt_ic_isr_register(PIO_LED_IRQ_INTERRUPT_CONTROLLER_ID,
                        PIO_LED_IRQ,
                        key_isr,
                        p,
                        0);

    IOWR_ALTERA_AVALON_PIO_DIRECTION(PIO_LED_BASE, 0x0f);    //设置低4位为输出,高2位为输入
    IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PIO_LED_BASE, 0x30);    //清零所有的捕获位
    IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PIO_LED_BASE, 0x30);    //打开按键中断
}

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)
    {
        rx_data[rx_len] = IORD_ALTERA_AVALON_UART_RXDATA(UART_0_BASE);
        rx_len ++ ;
    }

    if(status & ALTERA_AVALON_UART_STATUS_TRDY_MSK)
    {
        if(tx_len)
        {
            IOWR_ALTERA_AVALON_UART_TXDATA(UART_0_BASE, tx_data[tx_len]);
            tx_len--;
            if(!tx_len)
            {
                IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE,0x80);    //关闭发送中断

            }
        }
    }
    return 0;
}

void uart_0_init()
{
    char *p;
    alt_ic_isr_register(UART_0_IRQ_INTERRUPT_CONTROLLER_ID,
                        UART_0_IRQ,
                        uart_0_isr,
                        p,
                        0);

    IOWR_ALTERA_AVALON_UART_STATUS(UART_0_BASE, 0x0);    //清零状态寄存器
    IORD_ALTERA_AVALON_UART_RXDATA(UART_0_BASE);    //读空接收寄存器中的无用值
    IOWR_ALTERA_AVALON_UART_DIVISOR(UART_0_BASE, UART_0_FREQ/9600 - 1);//设置波特率为115200
    IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x80);    //使能接收中断
}

void uart_tx(alt_u8 *data, alt_u8 len)
{
    tx_len = len;
    while(len)
    {
        tx_data[len] = *data;
        data++;
        len -- ;
    }
    IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x80 | 0x40);    //使能发送中断
}

int main()
{
    key_init();
    uart_0_init();

    while(1)
    {
        if(uart_en)
        {
            uart_tx(rx_data, rx_len);
            rx_len = 0;
            uart_en = 0;
        }
    }

  return 0;
}

注意,使用自定义的驱动来完成对UART IP的操作,请将软件自带的UART驱动关闭,如下图:

001.png

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复