简介
UART 控制器是一个全双工异步收发控制器,ZYNQ 内部包含两个 UART 控制器,UART0 和 UART1。
每一个 UART 控制器支持可编程的波特率发生器、64 字节的接收 FIFO 和发送 FIFO、产生中断、RXD 和TXD 信号的环回模式设置以及可配置的数据位长度、停止位和校验方式等。
UART 控制器系统框图如图所示:
由上图可知,UART 控制器和 IO 端口由参考时钟(UART REF_CLK)驱动,同时控制器也需要连接
APB 总线时钟(CPU_1x clock),UART REF_CLK 和 CPU_1x clock 都是来自于 PS 时钟子系统。UART 控制器的配置以及状态的获取由控制(Control)和状态寄存器(Status Registers)完成。另外,UART 控制器不仅可以连接至 MIO,也可以映射到 EMIO,从而使用 PL 的端口来实现串口通信的功能。当 UART 控制器连接到 MIO 时,只有 Tx(发送)和 Rx(接收)两个引脚;而当连接 EMIO 时,除 Tx 和 Rx 引脚外,可选的还有 CTSN、DSDN、DSRN 等引脚,这些引脚用于串口的流控制,即调制解调器的数据通讯中。UART 控制器采用独立的接收和发送数据路径,每个路径包含一个 64 字节的 FIFO,控制器对发送和接收 FIFO 中的数据进行串并转换操作。FIFO 的中断标志支持轮询处理或中断驱动处理两种方式。另外,控制器中还有一个模式开关,支持 RXD 和 TXD 信号的各种环回配置。
UART 控制器的寄存器通过 APB 从机接口和 PS AXI 总线互联,控制器的寄存器用于对 UART 控制器
进行配置和获取状态。波特率发生器(Baud Rate Generator)为 UART 控制器的接收端和发送端提供位周期时钟;中断控制器(GIC)为串口的收发提供了中断服务的功能。
APB 总线接口通过向 TxFIFO 寄存器写值,将数据加载到 TxFIFO 存储器中。当数据加载至 TxFIFO 后,TxFIFO 的空标志变成无效的状态,直到最后一个数据从 TxFIFO 中移出,加载至传输移位寄存器,TxFIFO恢复空的标志位。同时 TxFIFO 使用 TFULL(满中断状态)用于表示当前 TxFIFO 已经写满,并且会阻止数据继续写入。如果此时继续执行写操作,那么会触发溢出,数据不会加载到 TxFIFO 中。
RxFIFO 存储器接收来自接收移位寄存器的数据,当接收完数据后,RxFIFO 空标志信号同样变成无效
的状态,直到所有的数据通过 APB 总线发送出去。RxFIFO 的满标志状态用于表示 RxFIFO 已经写满,并且会阻止更多的数据写入。图中的模式切换(Mode Switch)控制 RxD 和 TxD 的信号连接方式,总共分为四种模式,分别为:正常模式(Normal Mode)、自动回音模式(Automatic Echo Mode)、本地环回模式(Local LoopbackMode)和远程环回模式(Remote Loopback Mode)。
BD设计
只需要对ZYNQ核进行配置即可。
软件设计
/*
* main.c
*/
#include "xparameters.h"
#include "xplatform_info.h"
#include "xuartps.h"
#include "xil_exception.h"
#include "xil_printf.h"
#include "xscugic.h"
char hh[] = "UART TEST\n";
#define UART_ID XPAR_PS7_UART_1_DEVICE_ID
#define UART_INT_ID XPAR_XUARTPS_1_INTR
#define SCU_ID XPAR_SCUGIC_0_DEVICE_ID
XUartPs_Config *uart_config;
XUartPs uart_inst;
XScuGic_Config *xscu_config;
XScuGic scu_inst;
void uart_Handler(void *callback){
XUartPs *psuart = (XUartPs *)callback;
u8 dec_rec;
u32 status;
//XUartPs_SendByte(XPAR_PS7_UART_1_BASEADDR,25);
status = XUartPs_ReadReg(psuart->Config.BaseAddress,XUARTPS_IMR_OFFSET);
status&= XUartPs_ReadReg(psuart->Config.BaseAddress,XUARTPS_ISR_OFFSET);
if(status&XUARTPS_IXR_RXOVR){
dec_rec = XUartPs_RecvByte(XPAR_PS7_UART_1_BASEADDR);
XUartPs_SendByte(XPAR_PS7_UART_1_BASEADDR,dec_rec);
//清除中断标志位
XUartPs_WriteReg(psuart->Config.BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_RXOVR);
xil_printf("%x",XUartPs_ReadReg(psuart->Config.BaseAddress,XUARTPS_ISR_OFFSET));
}
}
int main()
{
int status;
//print("UART TEST\n");
//串口初始化
uart_config = XUartPs_LookupConfig(UART_ID);
status = XUartPs_CfgInitialize(&uart_inst,
uart_config, uart_config->BaseAddress);
if(status!=XST_SUCCESS){
print("failed\n");
return XST_FAILURE;
}
XUartPs_EnableUart(&uart_inst);
//设置串口模式
XUartPs_SetOperMode(&uart_inst, XUARTPS_OPER_MODE_NORMAL);
//速率设置
status = XUartPs_SetBaudRate(&uart_inst, 115200);
//设置FIFO溢出个数
XUartPs_SetFifoThreshold(&uart_inst, 1);
if(status!=XST_SUCCESS){
print("failed\n");
return XST_FAILURE;
}
//查找中断控制器
xscu_config = XScuGic_LookupConfig(SCU_ID);
status = XScuGic_CfgInitialize(&scu_inst,xscu_config,
xscu_config->CpuBaseAddress);
if(status!=XST_SUCCESS){
print("failed\n");
return XST_FAILURE;
}
//老规矩,打开中断控制器后打开异常中断的处理函数
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
(void *)&scu_inst);
Xil_ExceptionEnable();
//设置回调函数
XScuGic_Connect(&scu_inst, UART_INT_ID,
(Xil_InterruptHandler)uart_Handler, (void *)&uart_inst);
//设置中断的触发方式
XUartPs_SetInterruptMask(&uart_inst, XUARTPS_IXR_RXOVR);
//打开中断控制器的使能
XScuGic_Enable(&scu_inst, UART_INT_ID);
//XUartPs_Send(&uart_inst, (u8*)hh, (u32)strlen(hh));
print("UART TEST\n");
while(1){
}
return 0;
}
利用串口中断实现环回功能。