一、另存一个zynq的hello word工程,命名为uart_inter_loop

二、删掉SDK包,重新生成SDK 硬件设计编写代码。

三、导出硬件设计

四、打开SDK,新建一个项目,建立一个main.c的源文件后编写SDK代码。

#include "stdio.h"
#include "xparameters.h"
#include "xuartps.h"
#include "XScuGic.h"

#define UART_DEVICE_ID			XPAR_XUARTPS_0_DEVICE_ID
#define INTC_DEVICE_ID			XPAR_SCUGIC_SINGLE_DEVICE_ID
#define UART_INT_IRQ_ID			XPS_UART1_INT_ID

#define XIL_EXCEPTION_ID_INT	XIL_EXCEPTION_ID_IRQ_INT

XUartPs_Config *Config;
XUartPs 		UartPs;
XScuGic_Config *IntcConfig;
XScuGic 		Interr_contrl;

//串口初始化函数
int uart_init(XUartPs *UartPs)
{
	int Status;
	//GPIO 初始化
	Config = XUartPs_LookupConfig(UART_DEVICE_ID);
	if (NULL == Config) {
		return XST_FAILURE;
	}

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

			/* Check hardware build */
	Status = XUartPs_SelfTest(UartPs);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	//设置串口的工作模式
	XUartPs_SetOperMode(UartPs, XUARTPS_OPER_MODE_NORMAL);//设置为正常模式
	//设置接收fifo触发的阈值,达到设置的阈值后的数据会产生中断,以下是每接收到一个就产生一次中断。
	XUartPs_SetFifoThreshold(UartPs,1);
	//设置波特率,这里软件已经设置了默认的1152200,如果要自己修改可以设置。
	XUartPs_SetBaudRate(UartPs,115200);
	//设置停止位
	XUartPs_SetRecvTimeout(UartPs, 8);

	return XST_SUCCESS;
}

//中断处理函数
void uart_interr_handle(void *CallBackRef)
{
	u32 recive_data;
	u32 IsrStatus;
	XUartPs *Uart_gpio=(XUartPs *)CallBackRef;

	//读中断寄存器里面的值。XUartPs_SetInterruptMask(UartPs, XUARTPS_IXR_RXOVR);其实就是这个函数XUARTPS_IXR_RXOV的值,这个值
	//只将最低为设置为1,也就是我们在中断系统初始化时使能了最低位。因此22读出来的也就是1:XUARTPS_IXR_RXOV
	IsrStatus = XUartPs_ReadReg(Uart_gpio->Config.BaseAddress,XUARTPS_IMR_OFFSET);
	IsrStatus &= XUartPs_ReadReg(Uart_gpio->Config.BaseAddress, XUARTPS_ISR_OFFSET);

	//接收数据
	if(IsrStatus & XUARTPS_IXR_RXOVR)
	{
		recive_data=XUartPs_RecvByte(Uart_gpio->Config.BaseAddress);
		//清除状态位
		XUartPs_WriteReg(Uart_gpio->Config.BaseAddress, XUARTPS_IMR_OFFSET,XUARTPS_IXR_RXOVR);
		//发送数据
		XUartPs_SendByte(Uart_gpio->Config.BaseAddress,recive_data);
	}
}

//串口初始化函数中断函数
int uart_interr_init(XScuGic *Interr_contrl,XUartPs *UartPs)
{
	int Status;
	//中断初始化
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	if (NULL == IntcConfig) {
		return XST_FAILURE;
	}
	Status = XScuGic_CfgInitialize(Interr_contrl, IntcConfig,IntcConfig->CpuBaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	Status = XScuGic_Connect(Interr_contrl, UART_INT_IRQ_ID,(Xil_ExceptionHandler)uart_interr_handle,(void *) UartPs);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	//设置触发方式,阈值触发
	XUartPs_SetInterruptMask(UartPs, XUARTPS_IXR_RXOVR);

	//处理ARM异常,中断程序必须有的三个函数
	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,Interr_contrl);
	Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

	//使能中断号。
	XScuGic_Enable(Interr_contrl, UART_INT_IRQ_ID);
	return XST_SUCCESS;
}

int main()
{
	int Status;
	printf("uart_interr_loop test!\n");

	Status=uart_init(&UartPs);
	if (Status != XST_SUCCESS) {
		printf("uart_init error!\n");
		return XST_FAILURE;
	}

	Status=uart_interr_init(&Interr_contrl,&UartPs);
	if (Status != XST_SUCCESS) {
		printf("uart_interr_init error!\n");
		return XST_FAILURE;
	}

	while(1);
	return Status;
}






五、这里就一个注意的点:#define UART_INT_IRQ_ID            XPS_UART1_INT_ID。这里我用的小梅哥的板子,他的UART外设在vivade进行硬件设计的时候只能选择UART1,根据原理图所得。而正点原子的启明星zynq开发板的外设为UART0。也是根据原理图看出来的。这里我前面也有提到过。

六、烧录、实验结果。记得连接串口。下图,右上角的绿色加号。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐