UART 控制器是一个全双工异步收发控制器, MPSoC 内部包含两个 UART 控制器, UART0 和 UART1。每一个 UART 控制器支持可编程的波特率发生器、 64 字节的接收 FIFO 和发送 FIFO、产生中断、 RXD 和TXD 信号的环回模式设置以及可配置的数据位长度、停止位和校验方式等。UART 控制器的配置以及状态的获取由控制(Control)和状态寄存器(Status Registers完成。另外,UART 控制器不仅可以连接至 MIO,也可以映射到 EMIO,从而使用 PL 的端口来实现串口通信的功能。当 UART 控制器连接到 MIO 时,只有 Tx(发送)和 Rx(接收)两个引脚;而当连接 EMIO 时,除 Tx 和Rx 引脚外,可选的还有 CTS、 RTS、 DSR、 DCD、 RI、 DTR 等引脚,这些引脚用于串口的流控制,即调制解调器的数据通讯中。UART 控制器采用独立的接收和发送数据路径,每个路径包含一个 64 字节的 FIFO,控制器对发送和接收 FIFO 中的数据进行串并转换操作。 FIFO 的中断标志支持轮询处理或中断驱动处理两种方式。 另外,控制器中还有一个模式开关,支持 RXD 和 TXD 信号的各种环回配置。 UART 控制器内部框图如下图所示:
main.c
#include "xparameters.h" //器件参数信息
#include "xuartps.h" //包含 PS UART 的函数声明
#include "xil_printf.h" //包含 print()函数
#include "xscugic.h" //包含中断的函数声明
#include "stdio.h" //包含 printf 函数的声明
#include "xscugic.h" //
#include "uart.h"
#include "intr.h"
//定义结构体
XUartPs Uartps ;
XScuGic Intc ;
int main(){
uart_config(&Uartps);
intr_config(&Intc,&Uartps);
while(1){
}
}
uart.c
#include "xparameters.h" //器件参数信息
#include "xuartps.h" //包含 PS UART 的函数声明
#include "xil_printf.h" //包含 print()函数
#include "xscugic.h" //包含中断的函数声明
#include "stdio.h" //包含 printf 函数的声明
#include "uart.h"
#define UART_DEVICE_ID XPAR_PS7_UART_0_DEVICE_ID //串口设备 ID
void uart_config(XUartPs *uartps){
XUartPs_Config *uart_cfg;
//查找配置信息
uart_cfg = XUartPs_LookupConfig(UART_DEVICE_ID);
//串口初始化
XUartPs_CfgInitialize(uartps,uart_cfg,uart_cfg->BaseAddress);
//UART参数设置
//波特率 115200
XUartPs_SetBaudRate(uartps,115200);
//模式设置 正常模式
XUartPs_SetOperMode(uartps,XUARTPS_OPER_MODE_NORMAL);
//设置触发数量:1
XUartPs_SetFifoThreshold(uartps, 1);
}
uart.h
#include "xparameters.h" //器件参数信息
#include "xuartps.h" //包含 PS UART 的函数声明
#include "xil_printf.h" //包含 print()函数
#include "xscugic.h" //包含中断的函数声明
#include "stdio.h" //包含 printf 函数的声明
#include "xscugic.h" //
void uart_config(XUartPs *uartps);
init.c
#include "xparameters.h" //器件参数信息
#include "xuartps.h" //包含 PS UART 的函数声明
#include "xil_printf.h" //包含 print()函数
#include "xscugic.h" //包含中断的函数声明
#include "stdio.h" //包含 printf 函数的声明
#include "intr.h"
#define UART_INT_IRQ_ID XPAR_XUARTPS_0_INTR //串口中断 ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //中断控制器 ID
void intr_config(XScuGic *Intc,XUartPs *Uartps){
SetupInterruptSystem(Intc,Uartps); //设置中断系统
}
void SetupInterruptSystem(XScuGic *Intc, XUartPs *Uartps)
{
XScuGic_Config *IntcConfig;
//查找GIC配置信息,进行初始化
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
XScuGic_CfgInitialize(Intc, IntcConfig,IntcConfig->CpuBaseAddress);
//配置UART中断
XUartPs_SetInterruptMask(Uartps,XUARTPS_IXR_RXOVR);
/*********************************************************************************************************************/
//初始化ARM处理器异常句柄
Xil_ExceptionInit();
//给IRQ异常注册处理程序
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,Intc);
//使能处理器中断
Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
/*********************************************************************************************************************/
//关联IQC异常处理函数
XScuGic_Connect(Intc,UART_INT_IRQ_ID,(Xil_ExceptionHandler)IntrHandler,(void *)Uartps);
//使能GIC控制器对应ID中断
XScuGic_Enable(Intc, UART_INT_IRQ_ID);
}
void IntrHandler(void *call_back_ref){
u32 int_state;
u8 rxdata;
XUartPs *uart_ps = (XUartPs *) call_back_ref;
//获取中断配置信息
int_state = XUartPs_GetInterruptMask(uart_ps);
//读取中断状态
int_state &= XUartPs_ReadReg(uart_ps->Config.BaseAddress,XUARTPS_ISR_OFFSET); //中断状态
//判断是否为rxfifo中断
if(int_state & XUARTPS_IXR_RXOVR){ //RXFIFO缓冲区中断
//读取RXFIFO数据
rxdata = XUartPs_RecvByte(uart_ps->Config.BaseAddress);
//清除中断标志
XUartPs_WriteReg(uart_ps->Config.BaseAddress,XUARTPS_ISR_OFFSET,1);
//发送数据
XUartPs_SendByte(uart_ps->Config.BaseAddress,rxdata);
}
}
inrt.h
#include "xparameters.h" //器件参数信息
#include "xuartps.h" //包含 PS UART 的函数声明
#include "xil_printf.h" //包含 print()函数
#include "xscugic.h" //包含中断的函数声明
#include "stdio.h" //包含 printf 函数的声明
void intr_config(XScuGic *Intc,XUartPs *Uartps);
void SetupInterruptSystem(XScuGic *Intc, XUartPs *Uartps);
void IntrHandler();
使用printf函数要注意在初始化函数之后使用
更换UART1