ZYNQ基本使用(1) PS的UART基本使用

目录

PS_UART

UART控制器简介

UART的MIO和EMIO管脚信号

设计指导

UART启动顺序

配置控制器功能

发送数据

接收数据

RXFIFO触发等级中断

寄存器概述

硬件系统

软件系统

基本使用

参考


PS_UART

UART控制器简介

UG585 – ch.19: UART Controller

ZYNQ的PS端有两个全双工异步串口收发器,支持广泛的可编程的波特率和I/O信号格式。

UART受配置寄存器和模式寄存器控制。独立的收发路径各自有一个64KB的FIFO,和一个模式开关支持配置回环。

UART0和UART1支持同样的特性。

ZYNQ基本使用(1) PS的UART基本使用_第1张图片

模块示意图

ZYNQ基本使用(1) PS的UART基本使用_第2张图片

 

UART的MIO和EMIO管脚信号

ZYNQ基本使用(1) PS的UART基本使用_第3张图片

 

设计指导

UART启动顺序

  1. 复位控制器;
  2. 配置I/O信号路由。Rx/Tx可使用MIO/EMIO。调制解调控制信号仅在EMIO接口可用;
  3. 配置UART参考时钟UART_Ref_Clk;
  4. 配置控制器功能;
  5. 配置中断;中断用于管理Tx/Rx FIFOs在所有模式下。
  6. 配置调制解调控制(可选);轮询和中断驱动选项。
  7. 管理收发数据。支持轮询Polling和中断Interrupt方式驱动。

配置控制器功能

这些示例配置字符帧、波特率、FIFO触发等级、RX超时机制和控制器使能。

所有的这些步骤必须的复位后完成,但在使能和关闭控制器之间不必要。

  1. 配置UART字符帧。
  2. 配置波特率。
  3. 设置RxFIFO出发等级。
  4. 使能控制器。
  5. 配置接收器超时机制。

发送数据

软件可以使用轮询polling或中断interrupt控制TxFIFO和RxFIFO数据流。

使用轮询polling方式

  1. 检查TxFIFO是否空;
  2. 写数据到TxFIFO;写64B数据
  3. 写更多数据。
    1. 检查TxFIFO是否有空间写下个B数据。
    2. 检查TxFIFO是否空。

 

使用中断interrupt方式

  1. 无效TxFIFO空中断。
  2. 写数据到TxFIFO;写64B数据;
  3. 检查TxFIFO是否有空间写下一个B数据;
  4. 重复步骤2和3;
  5. 使能中断;
  6. 等待直到TxFIFO为空。

接收数据

使用轮询方式

  1. 等待,直到RxFIFO被填充到触发数量级;
  2. 读RxFIFO数据。
  3. 重复步骤2直到FIFO空;
  4. 清除标志,如果Rx超时中断被触发。

使用中断方式

  1. 使能中断;
  2. 等待,直到RxFIFO被填充到触发数量级或Rx超时;;
  3. 读RxFIFO数据;
  4. 重复步骤2和3直到FIFO空;
  5. 清除标志,如果Rx超时中断被触发。

RXFIFO触发等级中断

设置RxFIFO触发等级和使能中断

  1. 配置触发等级;
  2. 使能RTIRG中断;
  3. 无效RTIRG中断;
  4. 清除RTRIG中断标志。

寄存器概述

ZYNQ基本使用(1) PS的UART基本使用_第4张图片

以上图文来源ug585 ch19

 

硬件系统

还是使用PS最小系统,仅使用UART1

 

软件系统

基本使用

在BSP界面选择导入示例工程

ZYNQ基本使用(1) PS的UART基本使用_第5张图片

选择hello_world_example和selftest_example导入

ZYNQ基本使用(1) PS的UART基本使用_第6张图片

在Explorer窗口可以看到导入的项目,以及代码主循环

ZYNQ基本使用(1) PS的UART基本使用_第7张图片

两个工程可以直接编译运行,自测试和打印输出。

从两个示例工程代码可以看到四个主要基本函数,初始化、自测试和发送。

打开xuartps.h可以看到Vitis提供的函数

ZYNQ基本使用(1) PS的UART基本使用_第8张图片

示例工程中使用的函数都在这里声明。

建立新的项目,添加几个.c和.h 文件。

代码如下

/*
 * uart_main.c
 *
 *  Created on: 2020/2/20
 *      Author: liny
 */

/***************************** Include Files *********************************/
#include "uart_ps.h"

/************************** Variable Definitions *****************************/
XUartPs Uart_Ps;		/* The instance of the UART Driver */


/*****************************************************************************\
* Main function to call the Hello World example.
* @param	None
* @return
*		- XST_FAILURE if the Test Failed .
*		- A non-negative number indicating the number of characters
*		  sent.
* @note		None
\*****************************************************************************/
int main(void)
{
	u8 SendBuf[] = "Hello World!\n";
	u8 RecvBuf[255] ;
	int Status ;
	u32 RecvCount =0;

	/* PS UART1 Initialization */
	Status = Uart_Init(&Uart_Ps, UART1_PS_DEVICE_ID);
	if (Status != XST_SUCCESS) {
		xil_printf("Uart PS initialization failed!%d\n",1);
		return XST_FAILURE;
	}
	else{
		xil_printf("Uart PS initialization completed!\r\n");
	}
	xil_printf("length : %d \n", (sizeof(SendBuf) ));

	/* forever transmit */
	while(1){
		sleep(1);
		//Status = Uart_Send(&Uart_Ps, SendBuf, (sizeof(SendBuf)));
		//xil_printf("SendCount : %d \n", Status );
		RecvCount = Uart_Recv(&Uart_Ps, RecvBuf, 16);
		Status = Uart_Send(&Uart_Ps, RecvBuf, RecvCount);
	}

	/* Never */
	return Status;
}
/*
 * uart.c
 *
 *  Created on: 2020/02/20
 *      Author: liny
 */

#include "uart_ps.h"

/************************** Function Definition ******************************/
/*************************** Device Initialize *******************************/
int Uart_Init(XUartPs* Uart_Ps, u16 DeviceId){
	int Status;
	XUartPs_Config *Config;

	/*
	 * Initialize the UART driver so that it's ready to use
	 * Look up the configuration in the config table,
	 * then initialize it.
	 */
	Config = XUartPs_LookupConfig(DeviceId);
	if (NULL == Config) {
		return XST_FAILURE;
	}

	Status = XUartPs_CfgInitialize(Uart_Ps, Config, Config->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/* Perform a self-test to check hardware build. */
	Status = XUartPs_SelfTest(Uart_Ps);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/* Set BaudRate */
	XUartPs_SetBaudRate(Uart_Ps, 115200);

	return XST_SUCCESS;
}

/******************************* Date Send ***********************************/
int Uart_Send(XUartPs* Uart_Ps, u8 *sendbuf, int length){
	int SentCount = 0;

	//while (SentCount < length - 1) {
	while (SentCount < length ) {
		/* Transmit the data */
		SentCount += XUartPs_Send(Uart_Ps,
					   &sendbuf[SentCount], 1);
	}

	return SentCount;
}

/******************************* Date Recv ***********************************/
u32 Uart_Recv(XUartPs* Uart_Ps, u8 *recvbuf, u32 length){
	u32 RecvCount = 0;
	//u32 XUartPs_Recv(XUartPs *InstancePtr, u8 *BufferPtr, u32 NumBytes)
	RecvCount = XUartPs_Recv(Uart_Ps, recvbuf, length);

	return RecvCount;
}
/*
 * uart_ps.h
 *
 *  Created on: 2020/02/20
 *      Author: liny
 */

#ifndef SRC_UART_PS_H_
#define SRC_UART_PS_H_


/***************************** Include Files *********************************/
#include "xparameters.h"
#include "xuartps.h"
#include "xil_printf.h"
#include "sleep.h"


/**************************** Constant Define ********************************/
#define UART1_PS_DEVICE_ID XPAR_PS7_UART_1_DEVICE_ID
/************************** Function Prototypes ******************************/
int Uart_Init(XUartPs* Uart_Ps, u16 DeviceId);
int Uart_Send(XUartPs* Uart_Ps, u8 *sendbuf, int length);
u32 Uart_Recv();

#endif /* SRC_UART_PS_H_ */

 

Debug模式下运行,通过接收一定长度的数据,进行回发。

ZYNQ基本使用(1) PS的UART基本使用_第9张图片完成!

 

参考

UG585:Zynq-7000 SoC Technical Reference Manual

 

你可能感兴趣的:(Zynq)