|
ZYNQ的UART
1 UART的特点
ZYNQ的串口模块是一个全双工的异步接收和发送器,支持宽范围广的软件可编程模块,支持编程配置波特率和数据格式,同时提供自动的奇偶校验和错误检测方案,此外,还为APU提供了接收和发送FIFO。
ZYNQ有两个UART器件,具有以下特性:
可编程波特率发送器;
64个字节接收和发送FIFO;
数据位6,7或者8个比特位;
奇,偶,空格,标记或者没有校验;
1,1.5或者2个停止位;
支持校验,帧和超限错误检测;
支持自动回应,本地环路和远程环路通道模式;
支持产生中断;
在EMIO上,可以使用调制解调器控制信号CTS,RTS,DSR,DTR,RI和DCD;
其结构框如图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个步骤:
UART的时钟选择,可以直接是UART Ref clock,也可以通过旁路进行8分频,该设置在uart.mode_reg0[0]中进行;
对UART时钟进行分频,产生band_sample的频率计算公式如下:
baud_sample = sel_clk/CD
对baud_sample进行再次分频,产生Rx和Tx波特率,该步骤是通过设置BDIV值完成,也就是对uart.Baud_rate_Divider_reg0[7:0]进行设置,波特率计算公式如下:
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对应波特率
2 UART使用实例
实例内容:配置好ZYNQ的UART中断,实现中断服务函数,在接收中断中将接收到的数据通过UART发送出来;
配置UART的步骤如下:
通过UART的外设ID找到对应的外设信息;
填充UART外设寄存器基地址和一些相关信息;
配置UART的的GIC中断;
配置UART的中断触发方式(接收或者发送中断);
设置UART的FIFO触发等级;
使能UART外设;
配置UART的GIC中断步骤如下:
连接到硬件,把对应中断映射到GIC中断请求上;
找到GIC中断,填充GIC中断寄存器基地址和一些相关信息;
找到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);
}
————————————————
版权声明:本文为CSDN博主「youbin2013」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/youbin2013/article/details/89252618 |
|