基于NIOS的串口发送实验
基于NIOS的串口发送实验
主控芯片:EP4C6F17C8
Qsys系统的搭建
新建一个项目,芯片选择EP4C6F17C8N,其他设置都是选择默认。
![](https://img2023.cnblogs.com/blog/2126010/202302/2126010-20230221170412748-954443086.png)
在菜单栏上选择Tools-Qsys,进行Qsys系统的搭建,在图中箭头所指的地方输入组件名称,选择对应的组件。
添加NIOS处理器,由于EP4C6F17C8资源有限,选择Nios II/s(标准型)。
![](https://img2023.cnblogs.com/blog/2126010/202302/2126010-20230221170413148-618207412.png)
连接相应的信号。
![](https://img2023.cnblogs.com/blog/2126010/202302/2126010-20230221170413577-535355880.png)
添加RAM,搜索框输入On_chip,选择对应的组件,总容量设置为20480 bytes(20KB)。
重名为ram,并进行连接。
点击nios,进行如下设置:
添加system id,搜索框输入system id,选择对应的组件,System ID可以设置为0x11223344。
添加jtag uart。
添加Timer、两个Uart。
分配地址,点击System-Assign Base Adress,点击Generate生成sopconfig文件,点击Generate-HDL Example生成Verilog语言。copy代码后在.v中引用该模块。
FPGA设计
在uart_test.v文件编写verilog代码
module uart_test(
clk,
rst_n,
uart0_rx,
uart0_tx,
uart1_rx,
uart1_tx
);
input clk;
input rst_n;
input uart0_rx;
output uart0_tx;
input uart1_rx;
output uart1_tx;
//qsys系统的verilog代码
uart_qsys u0 (
.clk_clk (clk), // clk.clk
.reset_reset_n (rst_n), // reset.reset_n
.uart0_external_rxd (uart0_rx), // uart0_external.rxd
.uart0_external_txd (uart0_tx), // .txd
.uart1_external_rxd (uart1_rx), // uart1_external.rxd
.uart1_external_txd (uart1_tx) // .txd
);
endmodule
在项目中添加.qip文件。
qip文件在和qsys系统同名的文件夹下 /synthesis/uart_qsys.qip
点击Assignments-Pin Planer,分配引脚。
编译.v文件。
EDS设计
在Quartus II中点击tools-Nios II Software Bulid Tools for Eclipse(简称EDS)。
创建BSP文件和项目文件。
![](https://img2023.cnblogs.com/blog/2126010/202302/2126010-20230221170413939-319835356.png)
选择sopcinfo文件,点击finish会生成两个项目。
![](https://img2023.cnblogs.com/blog/2126010/202302/2126010-20230221170414300-142556777.png)
编写main.C中编写程序。
#include <stdio.h>
#include <sys/unistd.h>
#include "myuart.h"
int main(void)
{
printf("Hellow!\n");
UART_ISR_Init(); //串口初始化
Uart_sendString("AT+WJAP\r\n",9);
usleep(3000000);//延时3s
Uart_sendString("AT+MQTT\r\n",9);
while(1)
{
}
return 0;
}
myuart.h
#ifndef MYUART_H_
#define MYUART_H_
void Uart_tx(unsigned char txdb);
void UART_ISR_Init(void); //初始化串口
void UART_Irq_Handler(void); //串口中断
void Uart_sendString(char *data, unsigned int len); //发送字符串
#endif
myuart.c
#include "myuart.h"
#include "system.h"
#include "sys/alt_irq.h"
#include "altera_avalon_uart_regs.h"
#include <stdio.h>
/*
* 串口发送数据函数
*/
void Uart_tx(unsigned char txdb)
{
alt_u16 uart_status; //状态寄存器是13位
do{
uart_status = IORD_ALTERA_AVALON_UART_STATUS(UART_1_BASE);//读状态寄存器
}while((uart_status & 0x40)!=0x40); //判断数据(TRDY==1时发送完毕)是否发送完毕 TRDY是状态寄存器的第6位(从0开始)
//0100 0000=0x40
uart_status = IORD_ALTERA_AVALON_UART_STATUS(UART_1_BASE);//再读状态寄存器
IOWR_ALTERA_AVALON_UART_TXDATA(UART_1_BASE, txdb); //发送数据
}
/*
* 串口发送字符串函数
* */
void Uart_sendString(char *data, unsigned int len)
{
alt_u8 i;
for(i=0;i<len;i++)
{
IOWR_ALTERA_AVALON_UART_TXDATA(UART_1_BASE, data[i]); //数据发送完,将TRDY置为1
while((IORD_ALTERA_AVALON_UART_STATUS(UART_1_BASE) & 0x40)!=0x40); //判断数据(TRDY==1)是否发送完毕
}
}
/*
* 串口初始化函数
* */
void UART_ISR_Init(void)
{ //清除中断标志寄存器
IOWR_ALTERA_AVALON_UART_STATUS(UART_1_BASE, 0x0);
//注册中断
alt_ic_isr_register(UART_1_IRQ_INTERRUPT_CONTROLLER_ID,
UART_1_IRQ,
UART_Irq_Handler,
NULL,
NULL);
//允许UART接收中断
IOWR_ALTERA_AVALON_UART_CONTROL(UART_1_BASE, 0x0080);
}
/*
* 串口中断函数,接收到数据时触发
* */
void UART_Irq_Handler(void)
{
alt_u8 rx_dat;
//读取接收数据
rx_dat = IORD_ALTERA_AVALON_UART_RXDATA(UART_1_BASE);
//发送接收数据
IOWR_ALTERA_AVALON_UART_TXDATA(UART_1_BASE, rx_dat);
//清除中断标志寄存器
IOWR_ALTERA_AVALON_UART_STATUS(UART_1_BASE, 0x0);
}
编辑Bsp项目。
![](https://img2023.cnblogs.com/blog/2126010/202302/2126010-20230221170414697-1709067455.png)
进行如图所示的设置,减少ram资源的消耗。
两个项目都要进行Build。
EDS中容易出现各种错误。有时候重新打开EDS可以解决这个问题。
测试
Quartus II中点击Promgrammer。添加sof文件,在项目的output_files文件下。
![](https://img2023.cnblogs.com/blog/2126010/202302/2126010-20230221170415046-923263958.png)
在EDS中,点击run as Nios ii hardware ,进行软件的烧录,出现如图的错误,则点击refersh,选择USB-Blaster。
测试结果:
![](https://img2023.cnblogs.com/blog/2126010/202302/2126010-20230221170415437-1514463017.png)