ZYNQ的UART
ZYNQ的串口模块是一个全双工的异步接收和发送器,支持宽范围广的软件可编程模块,支持编程配置波特率和数据格式,同时提供自动的奇偶校验和错误检测方案,此外,还为APU提供了接收和发送FIFO。
ZYNQ有两个UART器件,具有以下特性:
其结构框如图1所示:
图1 UART的结构体系
APB接口:
通过APB接口,PS可以对UART控制器内部寄存器进行读写操作;
Tx FIFO
Tx FIFO用于保存来自APB接口的写数据,直到发送器模块将其取出并送到发送移位寄存器中,Tx FIFO通过满和空标志来控制流量,此外,还可以设置Tx FIFO的触发等级;
Rx FIFO:
Rx FIFO用于保存来自接收移位寄存器的数据,Rx FIFO的满空标志用于接收数据流量控制,此外,还可以设置Rx FIFO的触发等级;
发送器:
发送器取出发送FIFO中的数据,并将其加载到发送移位寄存器中,将并行数据串行化处理;
接收器:
UART连续采样ua_rxd信号,当检测到低的电平变化时,表示接收数据的开始;
控制和状态模块:
控制寄存器用于使能,禁止和发布软件复位给接收器和发送器模块,还可以配置接收超时和发送断开等特性;模式寄存器通过波特率生成器选择时钟,它也负责选择发送和所接收数据的位的长度,奇偶校验位和停止位,还可以选择UART的工作模式,包含自动回应,本地环路以及远程环路等;
中断控制:
通过通道中断状态寄存器和通道状态寄存器,以及中断控制模块检测来自其他UART模块的事件;通过使用中断使能寄存器和中断禁止寄存器,使能或禁用中断,中断使能或者禁用的状态反映在中断屏蔽寄存器当中;
波特率发生器:
图2给出了波特率发生器的原理,图中CD是波特率发生器的一个位域,用于生成采样率时钟band_sample。
图2 波特率发送器
波特率最后生成主要包括以下3个步骤:
baud_sample = sel_clk/CD
baud_rate = sel_clk/(CD*(BDIV + 1))
UART Ref clock,CD和BDIV的值决定了UART的波特率,如果UART_Ref_Clk=50MHz,Uart_ref_clk/8=6.25MHz。图3表示典型的波特率对应的CD和eBDIV值;
图3 CD和eBDIV对应波特率
实例内容:配置好ZYNQ的UART中断,实现中断服务函数,在接收中断中将接收到的数据通过UART发送出来;
配置UART的步骤如下:
配置UART的GIC中断步骤如下:
程序源码:
//UART的GIC初始化
void Init_Gic_Uart(void)
{
XScuGic_Config *IntcConfig;
//connect hardware
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
(void *)&Intc);
//find XScuGic device
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
//config XScuGic data
XScuGic_CfgInitialize(&Intc,IntcConfig,IntcConfig->CpuBaseAddress);
//GIC Connect to handler function
XScuGic_Connect(&Intc,UART_IRPT_INTR,(Xil_InterruptHandler)UartIntrHandler, (void *)&Uart);
//enable XScuGic
XScuGic_Enable(&Intc,UART_IRPT_INTR);
//enable exception
Xil_ExceptionEnable();
Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
}
//UART初始化
void Init_Uart(void)
{
XUartPs_Config * UartConfigPtr;
//fined uart device
UartConfigPtr = XUartPs_LookupConfig(UART_DEVICE_ID);
//config XUartPs data
XUartPs_CfgInitialize(&Uart,UartConfigPtr,UartConfigPtr->BaseAddress);
//set uart mask
XUartPs_SetInterruptMask(&Uart,XUARTPS_IXR_RXOVR);
XUartPs_SetFifoThreshold(&Uart,10);
//enable uart
XUartPs_EnableUart(&Uart);
}
//UART中断服务函数
void UartIntrHandler(void *CallBackRef)
{
XUartPs *InstancePrt = (XUartPs *)CallBackRef;
u32 IsrStatus;
u32 ReceivedCount = 0;
u32 CsrRegister;
IsrStatus = XUartPs_ReadReg(InstancePrt->Config.BaseAddress,XUARTPS_IMR_OFFSET);
IsrStatus &= XUartPs_ReadReg(InstancePrt->Config.BaseAddress,XUARTPS_ISR_OFFSET);
if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY | (u32)XUARTPS_IXR_RXFULL)) != (u32)0)
{
CsrRegister = XUartPs_ReadReg(InstancePrt->Config.BaseAddress,XUARTPS_SR_OFFSET);
while((CsrRegister & XUARTPS_SR_RXEMPTY) == (u32)0)
{
XUartPs_WriteReg(InstancePrt->Config.BaseAddress,XUARTPS_FIFO_OFFSET,XUartPs_ReadReg(InstancePrt->Config.BaseAddress,XUARTPS_FIFO_OFFSET));
ReceivedCount++;
CsrRegister = XUartPs_ReadReg(InstancePrt->Config.BaseAddress,XUARTPS_SR_OFFSET);
}
}
// printf("thistimeReceivedCount=%d\r\n",ReceivedCount);
XUartPs_WriteReg(InstancePrt->Config.BaseAddress,XUARTPS_ISR_OFFSET,IsrStatus);
}