UART IP核
在qsys系统中调用UART IP核与上位机实现串口通信:上位机通过串口调试助手发送数据给fpga,FPGA通过串口接收数据并将接收到的数据发送给上位机,完成串口的数据环回。
4.UART IP核的设置
6.硬件将系统框图
5.代码
quartus代码
module qsys_uart(
input sys_clk ,
input sys_rst_n ,
input rxd , //uart 接收端
output txd //uart发送端
);
wire clk_100m; //100mHz时钟
//例化pll模块,用来产生
pll pll_inst (
.inclk0 ( sys_clk ),
.c0 ( clk_100m )
);
unsaved u0 (
.clk_clk (clk_100m), // clk.clk
.reset_reset_n (sys_rst_n), // reset.reset_n
.uart_rxd (rxd), // uart.rxd
.uart_txd (txd) // .txd
);
endmodule
PLL IP核的设置
eclipse软件代码
/*
* "Hello World" example.
*
* This example prints 'Hello from Nios II' to the STDOUT stream. It runs on
* the Nios II 'standard', 'full_featured', 'fast', and 'low_cost' example
* designs. It runs with or without the MicroC/OS-II RTOS and requires a STDOUT
* device in your system's hardware.
* The memory footprint of this hosted application is ~69 kbytes by default
* using the standard reference design.
*
* For a reduced footprint version of this template, and an explanation of how
* to reduce the memory footprint for a given application, see the
* "small_hello_world" template.
*
*/
#include <stdio.h>
#include "unistd.h"
#include "system.h"
#include "alt_types.h"
#include "altera_avalon_uart_regs.h" //描述uart IP核中的寄存器中、包括一些宏定义
#include "sys\alt_irq.h"
alt_u8 txdata =0; //发送数据
alt_u8 rxdata =0; //接收数据
void IRQ_UART_Interrupts(){ //uart中断服务函数
rxdata = IORD_ALTERA_AVALON_UART_RXDATA(UART_BASE); //将radata寄存器中存储的值读入变量rxdata中
txdata = rxdata; //进行串口自收发,将变量rxdata中的赋值给变量txdata。将接收到的数据在发送出去
while(!(IORD_ALTERA_AVALON_UART_STATUS(UART_BASE)& //查询发送准备好信号,如果没有准备好,则等待。IORD_ALTERA_AVALON_UART_STATUS(UART_BASE):读出状态寄存器state的值
ALTERA_AVALON_UART_STATUS_TRDY_MSK)); //ALTERA_AVALON_UART_STATUS_TRDY_MSK:(0x40),二进制是0000_0000_0100_0000,这参数的功能就是将state寄存器对应的位使能出来(TRDY),二进制可对应state寄存器的各个位。与state寄存器的值相与
IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE,txdata); //发送准备好,发送txdata
}
void IRQ_init(){ //中断初始化函数
IOWR_ALTERA_AVALON_UART_STATUS(UART_BASE,0); //清除状态寄存器,写0,将状态寄存器的各个位清零
IOWR_ALTERA_AVALON_UART_CONTROL(UART_BASE,0X80); //使能接收准备中断,给控制器寄存器相应位写1;
alt_ic_isr_register( //注册ISR
UART_IRQ_INTERRUPT_CONTROLLER_ID, //中断控制器标号,从system.h复制
UART_IRQ , //硬件中断号,从system.h复制
IRQ_UART_Interrupts , //中断服务子函数
0x0 , //指向与设备驱动实例相关的函数结构体
0x0 //flags,保留未使用
);
}
int main()
{
IRQ_init();
while(1); //死循环,循环里面什么也没做,纯属使程序一直运行
return 0;
}
代码解释:
while(!(IORD_ALTERA_AVALON_UART_STATUS(UART_BASE)&ALTERA_AVALON_UART_STATUS_TRDY_MSK)); //查询发送准备好信号,如果没有准备好,则等待。IORD_ALTERA_AVALON_UART_STATUS(UART_BASE):读出状态寄存器state的值
//ALTERA_AVALON_UART_STATUS_TRDY_MSK:(0x40),二进制是0000_0000_0100_0000,这参数的功能就是将state寄存器对应的位使能出来(TRDY),二进制可对应state寄存器的各个位。与state寄存器的值相与
IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE,txdata); //发送准备好,发送txdata
代码解释:
(1)
“while();”,当括号里面的值为0的时候跳出while循环执行第三行代码,当括号里面的值为1的时候一直在循环里面。因此,当“!(IORD_ALTERA_AVALON_UART_STATUS(UART_BASE)&ALTERA_AVALON_UART_STATUS_TRDY_MSK)”的值为1时跳出循环执行后面第三行代码,
(2)
!(IORD_ALTERA_AVALON_UART_STATUS(UART_BASE)&ALTERA_AVALON_UART_STATUS_TRDY_MSK):IORD_ALTERA_AVALON_UART_STATUS(UART_BASE)函数是取出状态寄存器state的值;ALTERA_AVALON_UART_STATUS_TRDY_MSK是对状态寄存器的TRDY位进行使能(0x40),二进制是0000_0000_0100_0000;两个值相与“&”的结果为IORD_ALTERA_AVALON_UART_STATUS(UART_BASE)的值,即取出state寄存器的值;“!”将相与的结果取反。
ALTERA_AVALON_UART_STATUS_TRDY_MSK对应的state使能后的值,如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DVCxXw0X-1682683118378)(C:/Users/xzs/AppData/Roaming/Typora/typora-user-images/image-20230428185900226.png)]
IOWR_ALTERA_AVALON_UART_CONTROL(UART_BASE,0X80); //使能接收准备中断,给控制器寄存器相应位写1;
解释:
给中断控制寄存器写0x80,对应的二进制为0000_0000_1000_0000,使能IRRDY中断,输出中断。对应的示意图如下图,将IRRDY使能了。
6.管脚分配:
7.实验结果
注意:quatus II建立工程时,有三个名称必须保持一致,否则将会出现错误,分别是:工程名字、顶层文件名称、顶层文件的module名称
链接:
【一】Qsys的软核知识记录
【二】软核学习
【三】FPGA软核学习常见的错误(qsys、eclipse)
--晓凡 2023年4月28日于桂林书