ZYNQ PL串口和PS串口中断使用进行数据收发

一,vivado工程搭建

1,共享中断配置

2,vivado工程效果

二,SDK给PS串口发数据

1,第一种不使用中断

(1)uart_intr.h和uart_intr.c

1,UART_Intr.h
#ifndef SRC_UART_INTR_H_
#define SRC_UART_INTR_H_
#include "xparameters.h"
#include "xuartps.h"
#include "xil_printf.h"
#include "sleep.h"
#define UART_DEVICE_ID                  XPAR_XUARTPS_0_DEVICE_ID
int Uart_Send(XUartPs* Uart_Ps, u8 *sendbuf, int length);
int Uart_Init(XUartPs* Uart_Ps, u16 DeviceId);
#endif

2,UART_Intr.c
#include "UART_Intr.h"
// UART格式
XUartPsFormat uart_format =
{
	9600,
	//XUARTPS_DFT_BAUDRATE,   //默认波特率 115200
	XUARTPS_FORMAT_8_BITS,
	XUARTPS_FORMAT_NO_PARITY,
	XUARTPS_FORMAT_1_STOP_BIT,
};

//--------------------------------------------------------------
//                     UART初始化函数
//--------------------------------------------------------------
int Uart_Init(XUartPs* Uart_Ps, u16 DeviceId)
{
	int Status;
	XUartPs_Config *Config;

	/*  初始化UART设备    */
	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;
	}

	/*  UART设备自检  */
	Status = XUartPs_SelfTest(Uart_Ps);
	if (Status != XST_SUCCESS) 
        {
		return XST_FAILURE;
	}

	/*  设置UART模式与参数   */
	XUartPs_SetOperMode(Uart_Ps, XUARTPS_OPER_MODE_NORMAL); //正常模式
	XUartPs_SetDataFormat(Uart_Ps, &uart_format);    //设置UART格式
	return XST_SUCCESS;
}

int Uart_Send(XUartPs* Uart_Ps, u8 *sendbuf, int length)
{
	int SentCount = 0;
	while (SentCount < length) 
        {
		SentCount += XUartPs_Send(Uart_Ps, &sendbuf[SentCount], 1);
	}

	return SentCount;
}

(2)主函数

#include "UART_Intr.h"
XUartPs Uart_Ps; /* The instance of the UART Driver */
int main(void)
{
	int Status;
	u8 sendbuf[]={0xEB,0x90,0x0A,0x00,0x00,0x0A,0x99,0x01,0x03,0x05,0x01};
	/* 串口初始化 */
	Status = Uart_Init(&Uart_Ps, UART_DEVICE_ID);
	if (Status == XST_FAILURE)
	{
		xil_printf("Uartps Failed\r\n");
		return XST_FAILURE;
	}
	while (1)
	{
		sleep(1);
		Uart_Send(&Uart_Ps, sendbuf, 14);
	}
	return Status;
}

2,第二种,使用中断号检测中断

(1)头文件uart_paramter.h

#ifndef UART_PARAMETER_H_
#define UART_PARAMETER_H_
#include "xuartps.h"
u8 TxString[14] =
{
		"Hello world!\r\n"
};
XUartPsFormat UartFormat =
{
		115200,
		XUARTPS_FORMAT_8_BITS,
		XUARTPS_FORMAT_NO_PARITY,
		XUARTPS_FORMAT_1_STOP_BIT
};
#endif 

(2)主函数

#include "xparameters.h"
#include <stdio.h>
#include "xil_printf.h"
#include "sleep.h"
#include "xscugic.h"
#include "uart_parameter.h"

#define UART_DEVICE_ID      XPAR_XUARTPS_0_DEVICE_ID
#define INTC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID
#define UART_INT_IRQ_ID		XPAR_XUARTPS_1_INTR
/* Statement */
#define UART_TX      0
#define UART_RXCHECK 1
#define UART_WAIT    2

/* maximum receiver length */
#define MAX_LEN    2000
/************************** Variable Definitions *****************************/
XUartPs Uart_PS;		//Instance of the UART Device 
XScuGic IntcInstPtr ;
/* UART receiver buffer */
u8 ReceivedBuffer[MAX_LEN] ;
/* UART receiver buffer pointer*/
u8 *ReceivedBufferPtr ;
/* UART receiver byte number */
volatile u32 ReceivedByteNum ;
volatile u32 ReceivedFlag  ;
int UartPsSend(XUartPs *InstancePtr, u8 *BufferPtr, u32 NumBytes) ;
int UartPsRev (XUartPs *InstancePtr, u8 *BufferPtr, u32 NumBytes) ;
int SetupInterruptSystem(XScuGic *IntcInstancePtr,	XUartPs *UartInstancePtr, u16 UartIntrId);
void Handler(void *CallBackRef);

int main(void)
{
	int Status;
	XUartPs_Config *Config;

	u32 SendByteNum ;
	u8 *SendBufferPtr ;
	u8 state = UART_TX ;

	ReceivedBufferPtr = ReceivedBuffer ;

	ReceivedFlag = 0 ;
	ReceivedByteNum = 0 ;

	Config = XUartPs_LookupConfig(UART_DEVICE_ID);
	if (NULL == Config)
   {
		return XST_FAILURE;
	}
	Status = XUartPs_CfgInitialize(&Uart_PS, Config, Config->BaseAddress);
	if (Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}
	/* Use Normal mode. */
	XUartPs_SetOperMode(&Uart_PS, XUARTPS_OPER_MODE_NORMAL);
	/* Set uart mode Baud Rate 115200, 8bits, no parity, 1 stop bit */
	XUartPs_SetDataFormat(&Uart_PS, &UartFormat) ;
	/*Set receiver FIFO interrupt trigger level, here set to 1*/
	XUartPs_SetFifoThreshold(&Uart_PS,1) ;
	/* Enable the receive FIFO trigger level interrupt and empty interrupt for the device */
	XUartPs_SetInterruptMask(&Uart_PS,XUARTPS_IXR_RXOVR|XUARTPS_IXR_RXEMPTY);
	SetupInterruptSystem(&IntcInstPtr, &Uart_PS, UART_INT_IRQ_ID) ;

	while(1)
	{
		switch(state)
		{
		case UART_TX :          /* Send string to pc */
		{
			SendBufferPtr = TxString ;
			SendByteNum = sizeof(TxString) ;
			//UartPsSend(&Uart_PS, SendBufferPtr, SendByteNum);
			state = UART_RXCHECK ;
			break ;
		}
		case UART_RXCHECK :    /* Check receiver flag, send received data */
		{
			if (ReceivedFlag)
			{
				/* Reset receiver pointer, flag, byte number */
				ReceivedBufferPtr = ReceivedBuffer ;
				SendBufferPtr = ReceivedBuffer ;
				SendByteNum = ReceivedByteNum ;
				ReceivedFlag = 0 ;
				ReceivedByteNum = 0 ;
				//-----------------------------
				uint8_t abc[8]={0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};
				UartPsSend(&Uart_PS, abc, 8);
				//UartPsSend(&Uart_PS, SendBufferPtr, SendByteNum);

			}
			else
			{
				state = UART_WAIT ;
			}
			break ;
		}
		case UART_WAIT :		/* Wait for 1s */
		{
			sleep(1) ;
			state = UART_TX ;
			break ;
		}
		default : break ;
		}
	}
}

int SetupInterruptSystem(XScuGic *IntcInstancePtr,	XUartPs *UartInstancePtr, u16 UartIntrId)
{
	int Status;
	/* Configuration for interrupt controller */
	XScuGic_Config *IntcConfig;

	/* Initialize the interrupt controller driver */
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	if (NULL == IntcConfig)
	{
		return XST_FAILURE;
	}

	Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);
	if (Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}

	/*
	 * Connect the interrupt controller interrupt handler to the
	 * hardware interrupt handling logic in the processor.
	 */
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler) XScuGic_InterruptHandler,IntcInstancePtr);
	Status = XScuGic_Connect(IntcInstancePtr, UartIntrId,(Xil_ExceptionHandler) Handler,(void *) UartInstancePtr);
	if (Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}
	XScuGic_Enable(IntcInstancePtr, UartIntrId);
	Xil_ExceptionEnable();
	return Status ;
}


void Handler(void *CallBackRef)
{
	XUartPs *UartInstancePtr = (XUartPs *) CallBackRef ;
	u32 ReceivedCount = 0 ;
	u32 UartSrValue ;
	UartSrValue = XUartPs_ReadReg(UartInstancePtr->Config.BaseAddress, XUARTPS_SR_OFFSET) & (XUARTPS_IXR_RXOVR|XUARTPS_IXR_RXEMPTY);
	ReceivedFlag = 0 ;

	if (UartSrValue & XUARTPS_IXR_RXOVR)   /* check if receiver FIFO trigger */
	{
		ReceivedCount = UartPsRev(&Uart_PS, ReceivedBufferPtr, MAX_LEN) ;
		ReceivedByteNum += ReceivedCount ;
		ReceivedBufferPtr += ReceivedCount ;
		/* clear trigger interrupt */
		XUartPs_WriteReg(UartInstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_RXOVR) ;
	}
	else if (UartSrValue & XUARTPS_IXR_RXEMPTY) //check if receiver FIFO empty 
	{
		/* clear empty interrupt */
		XUartPs_WriteReg(UartInstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_RXEMPTY) ;
		ReceivedFlag = 1 ;
	}
}




int UartPsSend(XUartPs *InstancePtr, u8 *BufferPtr, u32 NumBytes)
{
	u32 SentCount = 0U;
	/* Setup the buffer parameters */
	InstancePtr->SendBuffer.RequestedBytes = NumBytes;
	InstancePtr->SendBuffer.RemainingBytes = NumBytes;
	InstancePtr->SendBuffer.NextBytePtr = BufferPtr;


	while (InstancePtr->SendBuffer.RemainingBytes > SentCount)
	{
		/* Fill the FIFO from the buffer */
		if (!XUartPs_IsTransmitFull(InstancePtr->Config.BaseAddress))
		{
			XUartPs_WriteReg(InstancePtr->Config.BaseAddress,XUARTPS_FIFO_OFFSET,((u32)InstancePtr->SendBuffer.NextBytePtr[SentCount]));

			/* Increment the send count. */
			SentCount++;
		}
	}

	/* Update the buffer to reflect the bytes that were sent from it */
	InstancePtr->SendBuffer.NextBytePtr += SentCount;
	InstancePtr->SendBuffer.RemainingBytes -= SentCount;


	return SentCount;
}

int UartPsRev(XUartPs *InstancePtr, u8 *BufferPtr, u32 NumBytes)
{
	u32 ReceivedCount = 0;
	u32 CsrRegister;

	/* Setup the buffer parameters */
	InstancePtr->ReceiveBuffer.RequestedBytes = NumBytes;
	InstancePtr->ReceiveBuffer.RemainingBytes = NumBytes;
	InstancePtr->ReceiveBuffer.NextBytePtr = BufferPtr;

	/*
	 * Read the Channel Status Register to determine if there is any data in
	 * the RX FIFO
	 */
	CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
			XUARTPS_SR_OFFSET);

	/*
	 * Loop until there is no more data in RX FIFO or the specified
	 * number of bytes has been received
	 */
	while((ReceivedCount < InstancePtr->ReceiveBuffer.RemainingBytes)&&
			(((CsrRegister & XUARTPS_SR_RXEMPTY) == (u32)0)))
	{
		InstancePtr->ReceiveBuffer.NextBytePtr[ReceivedCount] =
				XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_FIFO_OFFSET);

		ReceivedCount++;
		CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_SR_OFFSET);
	}
	InstancePtr->is_rxbs_error = 0;
	/*
	 * Update the receive buffer to reflect the number of bytes just
	 * received
	 */
	if(InstancePtr->ReceiveBuffer.NextBytePtr != NULL)
        {
		InstancePtr->ReceiveBuffer.NextBytePtr += ReceivedCount;
	}
	InstancePtr->ReceiveBuffer.RemainingBytes -= ReceivedCount;

	return ReceivedCount;
}


3,比较复杂的一种带中断的写法

(1)uartps_intr.h和uart_intr.c

1,uartps_intr.h
#ifndef UARTPS_INTR_H_
#define UARTPS_INTR_H_
#include "xparameters.h"
#include "xplatform_info.h"
#include "xuartps.h"
#include "xil_exception.h"
#include "xil_printf.h"
#include "xscugic.h"
int Init_UartPsIntr(XUartPs *UartInstPtr,u16 DeviceId);
int UartPs_Setup_IntrSystem(XScuGic *IntcInstancePtr,XUartPs *UartInstancePtr,u16 UartIntrId);
void UartPs_Intr_Handler(void *CallBackRef, u32 Event, unsigned int EventData);
#define UART_DEVICE_ID		XPAR_XUARTPS_0_DEVICE_ID
#define INTC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID
#define UART_INT_IRQ_ID		XPAR_XUARTPS_1_INTR
#define TEST_BUFFER_SIZE	10
XUartPs UartPs;//uart
static u8 SendBuffer[TEST_BUFFER_SIZE];	/* Buffer for Transmitting Data */
static u8 RecvBuffer[TEST_BUFFER_SIZE];	/* Buffer for Receiving Data */
volatile int TotalReceivedCount;
volatile int TotalSentCount;
int TotalErrorCount;
#endif /* SRC_UARTPS_INTR_H_ */




2,uartps_intr.c
#include "uartps_intr.h"
int Init_UartPsIntr(XUartPs *UartInstPtr,u16 DeviceId )
{
	int Status;
	XUartPs_Config *Config;
	u32 IntrMask;

	if (XGetPlatform_Info() == XPLAT_ZYNQ_ULTRA_MP)
	{
#ifdef XPAR_XUARTPS_1_DEVICE_ID
		DeviceId = XPAR_XUARTPS_1_DEVICE_ID;
#endif
	}

	Config = XUartPs_LookupConfig(DeviceId);
	if (NULL == Config)
	{
		return XST_FAILURE;
	}

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

	
	 /* Setup the handlers for the UART that will be called from the
	 * interrupt context when data has been sent and received, specify
	 * a pointer to the UART driver instance as the callback reference
	 * so the handlers are able to access the instance data*/
	XUartPs_SetHandler(UartInstPtr, (XUartPs_Handler)UartPs_Intr_Handler, UartInstPtr);

	/*
	 * Enable the interrupt of the UART so interrupts will occur, setup
	 * a local loopback so data that is sent will be received.
	 */
	IntrMask =
		XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING |
		XUARTPS_IXR_OVER | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXFULL |
		XUARTPS_IXR_RXOVR;

	if (UartInstPtr->Platform == XPLAT_ZYNQ_ULTRA_MP)
	{
		IntrMask |= XUARTPS_IXR_RBRK;
	}
	XUartPs_SetInterruptMask(UartInstPtr, IntrMask);
	XUartPs_SetRecvTimeout(UartInstPtr, 8);
	return XST_SUCCESS;
}


void UartPs_Intr_Handler(void *CallBackRef, u32 Event, unsigned int EventData)
{
	int i = 0;
	/* All of the data has been sent */
	if (Event == XUARTPS_EVENT_SENT_DATA)
	{
		TotalSentCount = EventData;
	}
	/* All of the data has been received */
	if (Event == XUARTPS_EVENT_RECV_DATA)
	{
		TotalReceivedCount = EventData;
		if(TotalReceivedCount == TEST_BUFFER_SIZE)
		{
			for(i=0;i<TotalReceivedCount;i++)
			{
				SendBuffer[i] = RecvBuffer[i];
			}
			XUartPs_Send(&UartPs, SendBuffer, TotalReceivedCount);
			XUartPs_Recv(&UartPs, RecvBuffer, TEST_BUFFER_SIZE);
			TotalReceivedCount=0;
		}
	}
	/*
	 * Data was received, but not the expected number of bytes, a
	 * timeout just indicates the data stopped for 8 character times
	 */
	if (Event == XUARTPS_EVENT_RECV_TOUT)
	{
		TotalReceivedCount = EventData;
			for(i=0;i<TotalReceivedCount;i++)
			{
				SendBuffer[i] = RecvBuffer[i];
			}
		XUartPs_Send(&UartPs, SendBuffer, TotalReceivedCount);
		XUartPs_Recv(&UartPs, RecvBuffer, TEST_BUFFER_SIZE);
		TotalReceivedCount=0;
	}

	/*
	 * Data was received with an error, keep the data but determine
	 * what kind of errors occurred
	 */
	if (Event == XUARTPS_EVENT_RECV_ERROR) 
        {
		TotalReceivedCount = EventData;
		TotalErrorCount++;
	}
	 /* Data was received with an parity or frame or break error, keep the data
	 * but determine what kind of errors occurred. Specific to Zynq Ultrascale+
	 * MP.*/
	if (Event == XUARTPS_EVENT_PARE_FRAME_BRKE) 
        {
		TotalReceivedCount = EventData;
		TotalErrorCount++;
	}
	/*
	 * Data was received with an overrun error, keep the data but determine
	 * what kind of errors occurred. Specific to Zynq Ultrascale+ MP.
	 */
	if (Event == XUARTPS_EVENT_RECV_ORERR) 
       {
		TotalReceivedCount = EventData;
		TotalErrorCount++;
	}
}

int UartPs_Setup_IntrSystem(XScuGic *IntcInstancePtr,XUartPs *UartInstancePtr,u16 UartIntrId)
{
	int Status;
	XScuGic_Config *IntcConfig; /* Config for interrupt controller */
	/* Initialize the interrupt controller driver */
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	if (NULL == IntcConfig)
	{
		return XST_FAILURE;
	}
	Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);
	if (Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}
	/*
	 * interrupt for the device occurs, the device driver handler
	 * performs the specific interrupt processing for the device
	 */
	Status = XScuGic_Connect(IntcInstancePtr, UartIntrId,
	(Xil_ExceptionHandler) XUartPs_InterruptHandler,(void *) UartInstancePtr);
	if (Status != XST_SUCCESS) 
        {
		return XST_FAILURE;
	}

(2)sys_intr.h和sys_intr.c

#ifndef SYS_INTR_H_
#define SYS_INTR_H_
#include "xparameters.h"
#include "xil_exception.h"
#include "xdebug.h"
#include "xscugic.h"
#define INTC_DEVICE_ID          XPAR_SCUGIC_SINGLE_DEVICE_ID
XScuGic Intc; //GIC
int Init_Intr_System(XScuGic * IntcInstancePtr);
void Setup_Intr_Exception(XScuGic * IntcInstancePtr);
#endif 




#include "sys_intr.h"
void Setup_Intr_Exception(XScuGic * IntcInstancePtr)
{
	//从硬件使能中断
	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
			(Xil_ExceptionHandler)XScuGic_InterruptHandler,
			(void *)IntcInstancePtr);
	Xil_ExceptionEnable();
}

int Init_Intr_System(XScuGic * IntcInstancePtr)
{
	int Status;
	XScuGic_Config *IntcConfig;
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	if (NULL == IntcConfig)
	{
		return XST_FAILURE;
	}
	Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);
	if (Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}
	return XST_SUCCESS;
}

(3)主函数

#include "sys_intr.h"
#include "uartps_intr.h"
void init_intr_sys(void)
{
	Init_UartPsIntr(&UartPs,UART_DEVICE_ID);
	Init_Intr_System(&Intc);
	Setup_Intr_Exception(&Intc);
	UartPs_Setup_IntrSystem(&Intc, &UartPs, UART_INT_IRQ_ID);
}
int main(void)
{
	init_intr_sys();
	XUartPs_Recv(&UartPs, RecvBuffer, TEST_BUFFER_SIZE);
    while(1);
	return 0;
}

三,SDK给PL axi_uartlitle串口发数据执行流程

1,PL串口把收到的数据回发,不加中断

#include "xuartlite.h"
#include "xparameters.h"
#include "sleep.h"
#include "xil_printf.h"
#include "string.h"
int main()
{
	//实例化xuart2
	XUartLite  xuart2;//uart对象
	//查找uart配置
	XUartLite_Config *XUARTConfigPtr;
	XUARTConfigPtr = XUartLite_LookupConfig(XPAR_UARTLITE_0_DEVICE_ID);//ID来源于xparameters.h
	if (XUARTConfigPtr == NULL)
	{
		//在bsp中设置为uartlite0负责stdout
		//print("failed XUartlite_LookupConfig\n\r");
		return XST_FAILURE;
	}
	else
	{
		//print("succeed XUartlite_LookupConfig\n\r");
	}
	//uart初始化
	int Status;
	Status = XUartLite_Initialize(&xuart2, XPAR_UARTLITE_0_DEVICE_ID);
	if (Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}
	//接收缓冲
	u8 buf[64]={0x55,0x55,0x55,0x55,0x55};
	u8 buf2[64]={0};
	//接收字节数
	u32 recv_cnt = 0;
	while (TRUE)
	{
		usleep(500000);//等待500ms
		recv_cnt = XUartLite_Recv(&xuart2, buf2, 64);//接收数据
		if(recv_cnt>0)
		{
			XUartLite_Send(&xuart2, buf2,recv_cnt);
			memset(buf2, 0, 64);
			recv_cnt = 0;
		}
	}
	return 0;
}

2,使用中断号触发,从SDK空工程把串口号切换到PL串口

#include "stdio.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "sleep.h"
#include "xuartlite.h"
#include "xuartlite_i.h"
#include "xscugic.h"
///xxx#include "xuartps.h"
#define SEND_BUFF_SIZE 128
#define RECV_BUFF_SIZE 1
//函数声明
void ScuGic_UartLite_handle(void *CallbackRef);
void SendENDHandle(void *CallbackRef,unsigned int ByteCount);
void RecvENDHandle(void *CallbackRef,unsigned int ByteCount);
//全局变量
XScuGic scugic_inst;
XScuGic_Config *scugic_cfg_ptr;
XUartLite PL_Extend_Uart_inst;
unsigned char SendBuff[SEND_BUFF_SIZE]={"FUCK THE WORLD ONCE,FUCK THE WORLD TWICE\r\n"};
unsigned char RecvBuff[RECV_BUFF_SIZE]={0};
unsigned int recvcount=0;
int main()
{
	unsigned int state = 0;
	//初始化实例
	//state = XUartLite_Initialize( &PL_Extend_Uart_inst , XPAR_UARTLITE_0_DEVICE_ID );
	state = XUartLite_Initialize( &PL_Extend_Uart_inst , XPAR_XUARTPS_0_DEVICE_ID  );
	xil_printf("initialize state=%d\r\n",state);
	//设置发送buffer结束或接收buffer结束时的处理函数
	XUartLite_SetSendHandler( &PL_Extend_Uart_inst, SendENDHandle, &PL_Extend_Uart_inst );
	XUartLite_SetRecvHandler( &PL_Extend_Uart_inst, RecvENDHandle, &PL_Extend_Uart_inst );
	PL_Extend_Uart_inst.ReceiveBuffer.NextBytePtr = RecvBuff;
	PL_Extend_Uart_inst.ReceiveBuffer.RemainingBytes = RECV_BUFF_SIZE;
	//自检
	state = XUartLite_SelfTest( &PL_Extend_Uart_inst );
	xil_printf("selftest state=%d\r\n",state);
	//串口使能中断
	XUartLite_EnableInterrupt( &PL_Extend_Uart_inst );
	//scugic中断控制器初始化
	scugic_cfg_ptr = XScuGic_LookupConfig( XPAR_PS7_SCUGIC_0_DEVICE_ID );
	XScuGic_CfgInitialize( &scugic_inst,scugic_cfg_ptr,scugic_cfg_ptr->CpuBaseAddress );
	//设置优先级,中断触发类型
	XScuGic_SetPriorityTriggerType( &scugic_inst , XPAR_FABRIC_UARTLITE_0_VEC_ID , 0x0a , 0x03 );
	//将中断ID与中断处理函数相关联
	XScuGic_Connect( &scugic_inst,XPAR_FABRIC_UARTLITE_0_VEC_ID,ScuGic_UartLite_handle,&PL_Extend_Uart_inst );
	//使能AXI_GPIO中断
	XScuGic_Enable( &scugic_inst,XPAR_FABRIC_UARTLITE_0_VEC_ID );
	//设置并打开中断异常处理功能
	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler, &scugic_inst);
	Xil_ExceptionEnable();
	//xil_printf("len=%d\r\n",strlen((char *)SendBuff));
	while(1)
	{
		//将buffer中的数据全发送出去
	//XUartLite_Send( &PL_Extend_Uart_inst,SendBuff,strlen((char *)SendBuff));
		sleep(1);

		//xil_printf("RemainingBytes=%d\r\n",PL_Extend_Uart_inst.SendBuffer.RemainingBytes);
		state = XUartLite_ReadReg(PL_Extend_Uart_inst.RegBaseAddress,XUL_STATUS_REG_OFFSET);
		xil_printf("state=%d recvcount=%d\r",state,recvcount);
		XUartLite_Send( &PL_Extend_Uart_inst,RecvBuff,strlen((char *)RecvBuff));
		sleep(1);
	}

	return 0;
}

//该函数内部最好不要放打印函数,因为打印函数速度慢,会导致接收异常
void ScuGic_UartLite_handle(void *CallbackRef)
{
	//xil_printf("enter intr\r\n");
	XUartLite_InterruptHandler( &PL_Extend_Uart_inst );
}
//该函数内部最好不要放打印函数,尤其是需要使用扩展串口向外传输大量连续数据的时候,因为打印函数速度慢,会导致发送异常
void SendENDHandle(void *CallbackRef,unsigned int ByteCount)
{
	xil_printf("send end\r\n");
}
//该函数内部最好不要放打印函数,因为打印函数速度慢,会导致接收异常
void RecvENDHandle(void *CallbackRef,unsigned int ByteCount)
{
	recvcount++;
	xil_printf( "%s\n",RecvBuff );
	memset(RecvBuff,0,RECV_BUFF_SIZE);
	PL_Extend_Uart_inst.ReceiveBuffer.RemainingBytes = RECV_BUFF_SIZE;
	PL_Extend_Uart_inst.ReceiveBuffer.NextBytePtr = RecvBuff;
	XUartLite_EnableInterrupt( &PL_Extend_Uart_inst );
}

3,INTC带中断控制的方法,从SDK空工程把串口号切换到PL串口,使用microblaze软盒加中断控制器INTC模块

(1)sys_intr.h和sys_intr.c

#ifndef SYS_INTR_H_
#define SYS_INTR_H_
#include "xparameters.h"
#include "xil_exception.h"
#include "xdebug.h"
#include "XIntc.h"
int Init_Intr_System(XIntc * IntcInstancePtr);
void Intc_Enable(XIntc *IntcInstancePtr,u16 Intr_Id);
int Intc_Start(XIntc *IntcInstancePtr);
void setup_Intr_Exception(XIntc * IntcInstancePtr);
#endif 



#include "sys_intr.h"
#define INTC_DEVICE_ID          XPAR_INTC_0_DEVICE_ID
void Setup_Intr_Exception(XIntc * IntcInstancePtr)
{
	/* Enable interrupts from the hardware */
	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
			(Xil_ExceptionHandler)XIntc_InterruptHandler,
			(void *)IntcInstancePtr);
	Xil_ExceptionEnable();
}
int Init_Intr_System(XIntc * IntcInstancePtr)
{
	int Status;
	Status = XIntc_Initialize(IntcInstancePtr, INTC_DEVICE_ID);
		if (Status != XST_SUCCESS) 
		{
			return XST_FAILURE;
		}
	return XST_SUCCESS;
}
void Intc_Enable(XIntc *IntcInstancePtr,u16 Intr_Id)
{
	XIntc_Enable(IntcInstancePtr, Intr_Id);
}
int Intc_Start(XIntc *IntcInstancePtr)
{
	int Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE);
	if(Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}
	return XST_SUCCESS;
}

(2)UART_Intr.h和UART_Intr.c

#ifndef SRC_UART_INTR_H_
#define SRC_UART_INTR_H_
#include "xintc.h"
#include "xuartlite.h"
#include "xuartlite_l.h"
void uart_intr_handler(void *CallbackRef);
int Uart_SetupIntrSystem(XIntc* IntcInstancePtr,XUartLite* UartInstancePtr,u16 IntrId);
#endif



#include "UART_Intr.h"
void uart_intr_handler(void *CallbackRef)//中断函数
{
	u8 ReadByte;
	u32 IsrStatus;
	XUartLite *InstancePtr= (XUartLite *)CallbackRef;
	//读取状态寄存器
	IsrStatus = XUartLite_ReadReg(InstancePtr->RegBaseAddress,XUL_STATUS_REG_OFFSET);//读取状态寄存器
	while(IsrStatus & XUL_SR_RX_FIFO_VALID_DATA)
	{
		//读取数据
		ReadByte=XUartLite_ReadReg(InstancePtr->RegBaseAddress,XUL_RX_FIFO_OFFSET);
		//发送数据
		XUartLite_WriteReg(InstancePtr->RegBaseAddress,XUL_TX_FIFO_OFFSET,ReadByte);
		//读取状态寄存器
		IsrStatus = XUartLite_ReadReg(InstancePtr->RegBaseAddress,XUL_STATUS_REG_OFFSET);
	}
}
int Uart_SetupIntrSystem(XIntc* IntcInstancePtr,XUartLite* UartInstancePtr,u16 IntrId)
{
	int Status;

	Status = XIntc_Connect(IntcInstancePtr, IntrId,(XInterruptHandler)uart_intr_handler,(void *)UartInstancePtr);
	if (Status != XST_SUCCESS) 
	{
		return XST_FAILURE;
	}
	XUartLite_EnableInterrupt(UartInstancePtr);
	return XST_SUCCESS;
}

(3)主函数

#include "UART_Intr.h"
#include "xparameters.h"
#include "sys_intr.h"
#define UART_DEV_ID		XPAR_UARTLITE_0_DEVICE_ID
#define UART_INTR_ID	XPAR_INTC_0_UARTLITE_0_VEC_ID
static XIntc Intc; //GIC
static XUartLite Uart;//timer
int main(void)
{
	XUartLite_Initialize(&Uart, UART_DEV_ID);
	Init_Intr_System(&Intc); // initial DMA interrupt system
	Uart_SetupIntrSystem(&Intc,&Uart,UART_INTR_ID);
	Intc_Start(&Intc);
	Intc_Enable(&Intc,UART_INTR_ID);
	Setup_Intr_Exception(&Intc);
	while(1);
}

4, 使用寄存器方法

(1)功能:AXI-UART模块配置

void AxiUartConfig(void)
{
    PsWriteWord(ADDR_INTR_CLEAR, 0);
    PsWriteWord(ADDR_INTR_CLEAR, 1);
    PsWriteWord(ADDR_INTR_CLEAR, 2);
    PsWriteWord(ADDR_INTR_CLEAR, 3);
    PsWriteWord(ADDR_INTR_EN, 0xFFFF); // interrupt enable

    // TEST_UART   TTL   
    PsWriteWord(ADDR_UART0_RST, 1);
    DelayUs(1);
    PsWriteWord(ADDR_UART0_RST, 0);
    PsWriteWord(ADDR_UART0_BAUD, 52); // 12 = 460800   =  100M  / 460800 / 16 - 1
    PsWriteWord(ADDR_UART0_PARITY, 0);
    PsWriteWord(ADDR_UART0_STOP, 0);
    PsWriteWord(ADDR_UART0_EN, 1);

    // PL_UART1    RS422  
    PsWriteWord(ADDR_UART1_RST, 1);
    DelayUs(1);
    PsWriteWord(ADDR_UART1_RST, 0);
    PsWriteWord(ADDR_UART1_BAUD, 52); // 52 = 115200
    PsWriteWord(ADDR_UART1_PARITY, 0);
    PsWriteWord(ADDR_UART1_STOP, 0);
    PsWriteWord(ADDR_UART1_EN, 1);

    // PL_UART2    RS422  
    PsWriteWord(ADDR_UART2_RST, 1);
    DelayUs(1);
    PsWriteWord(ADDR_UART2_RST, 0);
    PsWriteWord(ADDR_UART2_BAUD, 52); // 52 = 115200
    PsWriteWord(ADDR_UART2_PARITY, 0);
    PsWriteWord(ADDR_UART2_STOP, 0);
    PsWriteWord(ADDR_UART2_EN, 1);
}

(2)获取串口控制台数据

Uint8 ConsoleAcquireData(int port)
{
    Uart_stu *mUart;
    Uint8   rXor = 0;  // 异或校验码
    Uint16  ckSum = 0;  // 校验和
    uint16_t i;
    uint8_t *buf;
    comm2upper_stu *comm_pt;
    if(port == IF_UART)
   { 
 if(!(Ctl_param.comm2upper.if_sw & uart_enable))
	return 0;
mUart = &Ctl_param.uart_console;
Ctl_param.comm2upper.err = 0;

while (mUart->rb.rx_head != mUart->rb.rx_tail )
{
	mUart->frm_rx_buf[mUart->frm_rx_idx] = mUart->rb.rx[mUart->rb.rx_tail];
	__BUF_INCR(mUart->rb.rx_tail);
	mUart->frm_rx_idx++;

	switch(mUart->frm_rx_idx)
	{
		// 长度码
		case 1: if(mUart->frm_rx_buf[0]  != 0x55)
					mUart->frm_rx_idx = 0;
			break;
		case 2: if(mUart->frm_rx_buf[1]  != 0xAA)
					mUart->frm_rx_idx = 0;
			break;
		case 3: if(mUart->frm_rx_buf[2]  != 0x01)
					mUart->frm_rx_idx = 0;
			break;
		case 4: if(mUart->frm_rx_buf[3]  != 0x36)
					mUart->frm_rx_idx = 0;
				else
					mUart->frm_length = 0x36;
			break;
		default:
				if(mUart->frm_rx_idx == mUart->frm_length)   // 数据段读完
				{
					for(i=2; i<53; i++)//3~52字节求和
					{
						ckSum += mUart->frm_rx_buf[i];
					}
					ckSum &= 0xFF; // 取低八位

					if(ckSum == mUart->frm_rx_buf[mUart->frm_length - 2] &&
					   0x0D == mUart->frm_rx_buf[mUart->frm_length - 1]) // success
					{
						comm_pt = &Ctl_param.comm2upper;
						buf = &mUart->frm_rx_buf[0];
						comm_pt->load_info.missile_longitude = *(int32_t *)(buf+5);
						comm_pt->load_info.latitude = *(int32_t *)(buf+9);
						comm_pt->load_info.height = *(int32_t *)(buf+13);
						comm_pt->load_info.nVelocity = *(int32_t *)(buf+15);
						comm_pt->load_info.sVelocity = *(int32_t *)(buf+17);
						comm_pt->load_info.eVelocity = *(int32_t *)(buf+19);
						comm_pt->load_info.target_longitude = *(int32_t *)(buf+21);
						comm_pt->load_info.target_latitude = *(int32_t *)(buf+25);
						comm_pt->load_info.target_height = *(int32_t *)(buf+29);
						comm_pt->load_info.pitch = *(int32_t *)(buf+31);
						comm_pt->load_info.yaw = *(int32_t *)(buf+33);
						comm_pt->load_info.roll = *(int32_t *)(buf+35);
						comm_pt->load_info._wx = *(int32_t *)(buf+37) & 0x00FFFFFF;
						comm_pt->load_info._wy = *(int32_t *)(buf+40) & 0x00FFFFFF;
						comm_pt->load_info._wz = *(int32_t *)(buf+43) & 0x00FFFFFF;
						comm_pt->load_info.target_distance = *(int32_t *)(buf+46);
						comm_pt->load_info.frm_cnt = *(int32_t *)(buf+50);
						mUart->frm_rx_idx = 0;
					}
				}
			break;
	}
}
mUart->frm_rx_idx = 0;
mUart->rb.rx_head = 0;
mUart->rb.rx_tail = 0;

 

 


版权声明:本文为wangjie36原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。