sdk例程:PS_UART相关的应用函数 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

PS_UART.h

#ifndef PS_UART_PS_UART_H_
#define PS_UART_PS_UART_H_

#include "COMMON.h"
#include "xuartps.h"

#define PS_UART0_IRQ_ID		XPAR_XUARTPS_0_INTR
#define PS_UART1_IRQ_ID		XPAR_XUARTPS_1_INTR

extern XUartPs UartPs1;	//UART�豸ʵ��

void PS_UART_Init(XUartPs *UartInstPtr,uint16_t DeviceId, uint8_t UART_Mode, uint32_t BaudRate);
void PS_UART_Intr_Init(XUartPs *UartInstPtr,uint16_t UartIntrId, uint8_t RecvTimeout, Xil_InterruptHandler Handler);
void PS_Uart_SendData(XUartPs *UartInstPtr,uint32_t data);
void PS_Uart_SendString(XUartPs *UartInstPtr, char *str);
void PS_Uart_RecvData(XUartPs *UartInstPtr, uint8_t *Buffer,uint32_t Len);


typedef struct{
	u8 rec_buff[1024*1024];
	u32 recv_length;
} rec_buff_t;

void PS_UART_RX(rec_buff_t *pbuf);
void PS_UART_TX(rec_buff_t *pbuf);

#endif /* PS_UART_PS_UART_H_ */

PS_UART.c

/**
  *****************************************************************************
  * 						PS部分UART相关库
  *****************************************************************************
  *
  * @File   : PS_UART.c
  * @By     : Sun
  * @Version: V1.3
  * @Date   : 2021 / 11 / 04
  * @Shop	: https://xiaomeige.taobao.com/
  *
  *****************************************************************************
**/


#include "PS_UART.h"

XUartPs UartPs1;			//UART设备实例


/***********************************************************************************************************
 * @brief:	初始化PS_UART设备
 * @param:	UartInstPtr		UART对象
 * @param:	DeviceId		UART设备ID
 * @param:	UART_Mode		UART模式选择
 * @param:	BaudRate		设置波特率
 * 模式有以下几种:	XUARTPS_OPER_MODE_NORMAL		标准模式
 * 					XUARTPS_OPER_MODE_AUTO_ECHO		自动回显模式
 * 					XUARTPS_OPER_MODE_LOCAL_LOOP	本地环回模式
 * 					XUARTPS_OPER_MODE_REMOTE_LOOP	远程环回模式
 * 			//初始化UART设备UartPs1,设为标准模式,波特率115200
 * Sample:	PS_UART_Init(&UartPs1,XPAR_PS7_UART_1_DEVICE_ID, XUARTPS_OPER_MODE_NORMAL, 115200);
***********************************************************************************************************/
void PS_UART_Init(XUartPs *UartInstPtr,uint16_t DeviceId, uint8_t UART_Mode, uint32_t BaudRate)
{
	XUartPs_Config *Config;
	Config = XUartPs_LookupConfig(DeviceId);
	XUartPs_CfgInitialize(UartInstPtr, Config, Config->BaseAddress);

	//设置波特率
	XUartPs_SetBaudRate(UartInstPtr, BaudRate);

	//设置UART模式
	XUartPs_SetOperMode(UartInstPtr, UART_Mode);
}

/***********************************************************************************************************
 * @brief:	初始化PS UART中断(初始化PS UART中断前,需先初始化PS UART)
 * @param:	UartInstPtr	UART对象
 * @param:	UartIntrId		UART中断ID
 * @param:	RecvTimeout		接收超时设置(设置为n时,如果超过nx4个字符时间仍未接收到数据,则进入超时中断;
 * 							设置为0时禁用该功能)
 * @return:	无
 * Sample:	PS_UART_Intr_Init(&UartPs1, PS_UART1_IRQ_ID, 8, (void *)PS_UART1_IRQ_Handler);
 * 			//初始化PS UART中断,UART对象为UartPs,中断ID为UART1_IRQ_ID,接收超时32字符
***********************************************************************************************************/
void PS_UART_Intr_Init(XUartPs *UartInstPtr,uint16_t UartIntrId, uint8_t RecvTimeout, Xil_InterruptHandler Handler)
{
	uint32_t IntrMask;

	Set_ScuGic_Link(UartIntrId, 0xA8, HIGH_Level_Sensitive,
			(Xil_ExceptionHandler)XUartPs_InterruptHandler, (void *)UartInstPtr);

	//为 UART 设置处理程序,当数据发送和接收时,该处理程序将从中断上下文中调用,
	//指定一个指向 UART 驱动程序实例的指针作为回调引用,以便处理程序能够访问实例数据
	XUartPs_SetHandler(UartInstPtr, (XUartPs_Handler)PS_UART0_IRQ_Handler, UartInstPtr);

	//配置UART的中断模式
	IntrMask = XUARTPS_IXR_TOUT |	XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING |
		XUARTPS_IXR_OVER | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXFULL | XUARTPS_IXR_RXOVR;
	XUartPs_SetInterruptMask(UartInstPtr, IntrMask);

	//Fifo阈值设置为1
	XUartPs_SetFifoThreshold(&UartPs1, 1);

	//接收超时设置
	XUartPs_SetRecvTimeout(UartInstPtr, RecvTimeout);

}

/***********************************************************************************************************
 * @brief:	使用PS UART发送数据,数据需在0~65535之间
 * @param:	UartInstPtr		UART对象
 * @param:	data			数据
 * @return:	无
 * Sample:	PS_Uart_SendData(&UartPs,12345); //发送数据12345
***********************************************************************************************************/
void PS_Uart_SendData(XUartPs *UartInstPtr,uint32_t data)
{
	uint8_t SendData[2];
	int data_H,data_L;
	data_H = data>>8;
	data_L = data&0x00ff;
	if(data_H == 0)//如果高位为0
	{
		SendData[0] = data;
		XUartPs_Send(UartInstPtr, SendData, 1);
	}
	else
	{
		SendData[0] = data_H;
		SendData[1] = data_L;
		XUartPs_Send(UartInstPtr, SendData, 2);
	}
}

/***********************************************************************************************************
 * @brief:	使用PS UART发送字符串
 * @param:	UartInstPtr		UART对象
 * @param:	str				字符串地址
 * @return:	无
 * Sample:	PS_Uart_SendString(&UartPs,"1234567"); //发送了7个字节
***********************************************************************************************************/
void PS_Uart_SendString(XUartPs *UartInstPtr, char *str)
{
	XUartPs_Send(UartInstPtr, (uint8_t *)str, strlen(str));
}

/***********************************************************************************************************
 * @brief:	使用PS UART接收数据
 * @param:	UartInstPtr		UART对象
 * @param:	Buffer			接收数据存储区
 * @param:	Len				接收数据的长度
 * @return:	无
 * Sample:	PS_Uart_RecvData(&UartPs, RecvBuffer,2);接收两个数据,并将数据存入RecvBuffer数组
***********************************************************************************************************/
void PS_Uart_RecvData(XUartPs *UartInstPtr, uint8_t *Buffer,uint32_t Len)
{
	XUartPs_Recv(UartInstPtr, Buffer, Len);
}


/***********************************************************************************************************
* 不定长度接收与发送
***********************************************************************************************************/
void PS_UART_RX(rec_buff_t *pbuf)
{
	PS_UART_Init(&UartPs1,XPAR_PS7_UART_0_DEVICE_ID, XUARTPS_OPER_MODE_NORMAL, 115200);

	u32 max_length=sizeof(pbuf->rec_buff);
	u32 ReceivedCount=0;
	u32 loop_cnt=0;
	while (ReceivedCount<=max_length) {
		u32 OneTimeCount=XUartPs_Recv(&UartPs1, &pbuf->rec_buff[ReceivedCount],
					  (max_length- ReceivedCount));
		ReceivedCount+=OneTimeCount;

		if(ReceivedCount>0){ /*只有当接收到数据后,才开始计数。最初没有接收到数据,不计数。*/
			if(OneTimeCount==0){/*当接收停顿后,开始计时*/
				usleep(10);
				loop_cnt++;
				if(loop_cnt>10000){ /*这个计数长度要大于sscom每发送256bytes后的停顿时间*/
					pbuf->recv_length=ReceivedCount;
					break;
				}
			}
			else{
				loop_cnt=0; /*一旦接收到数量不为零,那么计数值就清零*/
			}
		}
	}
}

void PS_UART_TX(rec_buff_t *pbuf)
{
	u32 TransmitCount = 0;
	u32 remainBytes=pbuf->recv_length;
	while (remainBytes >= 32) {
		TransmitCount+=XUartPs_Send(&UartPs1, &pbuf->rec_buff[TransmitCount],32);
		while (XUartPs_IsSending(&UartPs1)) {}
		remainBytes-=32;
	}
	if(remainBytes){
		TransmitCount+=XUartPs_Send(&UartPs1, &pbuf->rec_buff[TransmitCount],remainBytes);

		while (XUartPs_IsSending(&UartPs1)) {}
	}
}