0%

ZYNQ嵌入式之UART控制器(基于PYNQ-Z2开发板)

本节主要以串口UART中断实验为例,简单演示了串口的使用

UART串口中断实验

  • 实验任务:使用UART控制器,完成串口中断数据环回的功能

    image-20230925143504262

1.Vivado中的相关配置

  • 与hello world中的配置一样

2.Vitis中的代码编写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include<iostream>
#include<xparameters.h>
#include<xuartps.h>
#include<xscugic.h>
#include<xuartps_hw.h>

using namespace std;

/***********************参数声明**********************/
/*串口UART相关参数*/
#define DeviceId XPAR_PS7_UART_0_DEVICE_ID //串口设备ID
XUartPs Uart_Inst; //串口驱动程序实例
/*串口UART中断相关参数*/
#define INTR_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID //中断控制器的器件ID
#define UART_INT_IRQ_ID XPAR_XUARTPS_0_INTR //串口中断ID
XScuGic ScuGic_Inst; //中断控制器驱动程序实例

/***********************函数声明**********************/
void uart_init(XUartPs* Uart_Inst); //串口UART初始化函数
void uart_intr_init(XScuGic* intr, XUartPs* Uart_Inst); //中断初始化程序
void UartIntr_Handler(XUartPs * CallbackRef); //中断服务函数

int main(void)
{
//串口初始化函数
uart_init(&Uart_Inst);
//中断初始化程序
uart_intr_init(&ScuGic_Inst, &Uart_Inst);

while(1);
return 0;
}

//串口UART初始化程序
void uart_init(XUartPs* Uart_Inst)
{
XUartPs_Config *Config;
//查找配置信息
Config = XUartPs_LookupConfig(DeviceId);
//对UART控制器进行初始化
XUartPs_CfgInitialize(Uart_Inst, Config, Config->BaseAddress);

//设置UART的工作模式
XUartPs_SetOperMode(Uart_Inst, XUARTPS_OPER_MODE_NORMAL);
//设置接收FIFO的触发阈值,每接收1个字节的数据即产生中断,故第二个参数填1
XUartPs_SetFifoThreshold(Uart_Inst, 1);
//设置波特率:115200
XUartPs_SetBaudRate(Uart_Inst, 115200);
}

//中断初始化程序
void uart_intr_init(XScuGic* intr, XUartPs* Uart_Inst)
{
XScuGic_Config *IntcConfig; //中断控制器的配置信息
//初始化中断控制器的驱动
IntcConfig = XScuGic_LookupConfig(INTR_DEVICE_ID);
XScuGic_CfgInitialize(intr, IntcConfig, IntcConfig->CpuBaseAddress);

//设置并打开中断异常处理功能
//初始化ARM处理器异常句柄
Xil_ExceptionInit();
//来给IRQ异常注册处理程序
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler,
(void *)intr);
Xil_ExceptionEnable();

//关联中断ID和中断处理函数
XScuGic_Connect(intr, UART_INT_IRQ_ID,
(Xil_ExceptionHandler)UartIntr_Handler,
(void *)Uart_Inst);
//设置触发类型,RX FIFO trigger interrupt
XUartPs_SetInterruptMask(Uart_Inst, XUARTPS_IXR_RXOVR);//触发类型
//使能串口UART中断
XScuGic_Enable(intr, UART_INT_IRQ_ID);
}

//中断处理函数
void UartIntr_Handler(XUartPs * CallbackRef)
{
u32 IsrStatus;
u32 read_data = 0;
//获取中断状态寄存器的值
IsrStatus = XUartPs_ReadReg(CallbackRef->Config.BaseAddress, XUARTPS_IMR_OFFSET);//读取掩码

IsrStatus &= XUartPs_ReadReg(CallbackRef->Config.BaseAddress, XUARTPS_ISR_OFFSET);//读取状态

//XUARTPS_IXR_RXOVR是接收中断触发阈值的位
if(IsrStatus & XUARTPS_IXR_RXOVR)
{
read_data = XUartPs_RecvByte(CallbackRef->Config.BaseAddress); //读取接收到的一个字节的数据

XUartPs_WriteReg(CallbackRef->Config.BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_RXOVR); //清除中断状态位
}

//收到什么,发送什么
XUartPs_SendByte(CallbackRef->Config.BaseAddress,read_data);

}

3.实验结果

image-20230925160225125

欢迎来到ssy的世界