基于nios的串口通信uart设计
0赞开发环境:Quartus II 13.1 (64-Bit) + Nios II 13.1 Software Build Tools for Eclipse
Uart(通用异步收发器,也称异步串口)主要用于作通信,既然有异步通信,那一定有同步通信,对,确实有,同步串口,也就是所谓的Usrt,Usrt带一个时钟信号,一般来说,usrt比uart通信速率要快,但uart使用更简单,因此应用非常广泛。
对于RS-232通信,只需两根信号线(对应收发),一根地线即可完成通信,但传输距离较短,一般近距离(10m内)都没有问题;RS-485通信更简单,两线传输(差分信号),半双工,传输距离可以达到1000m;RS-422为4线传输,全双工模式,采用差分传输,传输距离与RS-485差不多。
初学者很容易陷入误区,通常说的Uart包括RS-232、RS-485、RS-422,比如RS-422属于Uart,但不等同于Uart。
最开始写uart的Verilog代码是参考大神特权同学的教程,用起来也是相当的方便,共需编写3个模块,分别为比特率生成模块、串口发送模块、串口接收模块,综合后RTL视图如下:
学习nios后发现可以直接用qsys中的uart核,用起来也是相当的方便啊,在qsys中添加相关Uart核来做串口通信其实很简单,如下图所示,只需添加on-chip memory核、nios核、uart核即可,将uart核的输出连出来。
Altpll输入时钟为50MHz,输出时钟100MHz,nios在100MHz时钟下运行。
在quartus工程中例化qsys,如下图所示,代码很简单,有么有!!!
module nios_uart( input clk, input rst_n, input uart_rxd, output uart_txd ); small_nios small_nios_inst( .clk_clk(clk), // clk.clk .reset_reset_n(rst_n), // reset.reset_n .uart_rxd(uart_rxd), // uart.rxd .uart_txd(uart_txd) // .txd ); endmodule
新建nios工程,添加如下代码,使用中断的方式进行串口通信,即FPGA每通过串口接收到一次数据,就进行一次中断,我们可以将要控制的部分写入串口中断服务程序中。
#include <stdio.h> #include "unistd.h" #include "system.h" #include "alt_types.h" #include "altera_avalon_uart_regs.h" #include "sys\alt_irq.h" #include "stddef.h" static alt_u8 txdata = 0; static alt_u8 rxdata = 0; //UART中断服务函数 static void uart_isr(void * context,alt_u32 id) { rxdata = IORD_ALTERA_AVALON_UART_RXDATA(UART_BASE); txdata = rxdata; //进行串口自收发 //查询发送准备好信号,如果没有准备好,则等待 while(!((IORD_ALTERA_AVALON_UART_STATUS(UART_BASE)&ALTERA_AVALON_UART_STATUS_TRDY_MSK))); //发送准备好,发送txdata IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE,txdata); } void uart_init() { //清除状态寄存器 IOWR_ALTERA_AVALON_UART_STATUS(UART_BASE,0); //使能接受准备好中断 IOWR_ALTERA_AVALON_UART_CONTROL(UART_BASE,0X80); } int main() { printf("Hello from Nios II!\n"); //注册UART中断服务函数 alt_irq_register(UART_IRQ,NULL,uart_isr); uart_init(); return 0; }
编译quartus工程和nios工程,通过后进行管脚分配,再编译一次quartus工程,下载逻辑和nios至FPGA,使用串口调试助手进行测试,打开串口后,发送数据至FPGA,FPGA接收到数据后进入中断服务程序,中断服务程序中txdata = rxdata;部分代码将接收到的数据发送出去,这样就完成了串口的自收发,结果如下。
当然,对于一些简单的控制(少于256种方式),比较简单的协议(发送一个字节)完全可以搞定问题,比如发送01,执行一种操作,……,ff执行另外一种操作。但是当控制项比较多时,就需要制定比较复杂的协议了,一般的串口控制协议如下图所示,n等于8时,发送10个byte,为了提高准确率,需要加入包头、包尾和校验字。
综合来看,不管是用逻辑还是用nios的方式,都可以实现串口通信,对于不太复杂的系统,完全可以只用逻辑来搭建,当然也就不需要用基于nios的串口通信了,但是,如果系统比较复杂,需要有稍复杂一些的通信协议时,还是有必要跑nios来做管理的,此时使用基于nios的串口通信就变得非常合适了!!!