第六节,ZYNQ的UART

ZYNQUART

1 UART的特点

ZYNQ的串口模块是一个全双工的异步接收和发送器,支持宽范围广的软件可编程模块,支持编程配置波特率和数据格式,同时提供自动的奇偶校验和错误检测方案,此外,还为APU提供了接收和发送FIFO。

ZYNQ有两个UART器件,具有以下特性:

  1. 可编程波特率发送器;
  2. 64个字节接收和发送FIFO;
  3. 数据位6,7或者8个比特位;
  4. 奇,偶,空格,标记或者没有校验;
  5. 1,1.5或者2个停止位;
  6. 支持校验,帧和超限错误检测;
  7. 支持自动回应,本地环路和远程环路通道模式;
  8. 支持产生中断;
  9. 在EMIO上,可以使用调制解调器控制信号CTS,RTS,DSR,DTR,RI和DCD;

其结构框如图1所示:

第六节,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。

第六节,ZYNQ的UART_第2张图片

图2 波特率发送器

波特率最后生成主要包括以下3个步骤:

  1. UART的时钟选择,可以直接是UART Ref clock,也可以通过旁路进行8分频,该设置在uart.mode_reg0[0]中进行;
  2. 对UART时钟进行分频,产生band_sample的频率计算公式如下:

baud_sample = sel_clk/CD

  1. 对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值;

第六节,ZYNQ的UART_第3张图片

图3 CD和eBDIV对应波特率

2 UART使用实例

实例内容:配置好ZYNQ的UART中断,实现中断服务函数,在接收中断中将接收到的数据通过UART发送出来;

配置UART的步骤如下:

  1. 通过UART的外设ID找到对应的外设信息;
  2. 填充UART外设寄存器基地址和一些相关信息;
  3. 配置UART的的GIC中断;
  4. 配置UART的中断触发方式(接收或者发送中断);
  5. 设置UART的FIFO触发等级;
  6. 使能UART外设;

配置UART的GIC中断步骤如下:

  1. 连接到硬件,把对应中断映射到GIC中断请求上;
  2. 找到GIC中断,填充GIC中断寄存器基地址和一些相关信息;
  3. 找到UART中断源,填充定时器中断寄存器基地址和一些相关信息;
  4. 将UART中断映射到定时器中断的中断服务函数上;
  5. 使能GIC中断;
  6. 使能中断向量表和中断向量表的映射;

程序源码:

//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);

}

 

你可能感兴趣的:(zynq学习)