pynq
pynq-z2是一款PFGA的开发板,就是那个粉粉的板子,还挺贵。现在说如何使用它上面的uart0串口。
所需设备:
pynq-z2,可以传数据的USB线,电脑装有vivado软件
1.新建vivado工程,新建Block Design然后添加ZYNQ、GPIO等IP核,自动连线后可以得到如图的原理图:
- 完成顶层封装,然后综合实现生成比特流文件,导出xsa文件,硬件部分准备完毕
xsa文件:
set_property PACKAGE_PIN R14 [get_ports {led_0[0]}]
set_property PACKAGE_PIN P14 [get_ports {led_0[1]}]
set_property PACKAGE_PIN N16 [get_ports {led_0[2]}]
set_property PACKAGE_PIN M14 [get_ports {led_0[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_0[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_0[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_0[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_0[3]}]
- 在vitis里面新建工程和cpp文件,同时建立BSP文件,编写串口通信代码,包括串口初始化,串口中断初始化以及中断处理函数。设置串口波特率为115200,接收一个bit则触发,中断模式为正常模式。
#include "xgpiops_hw.h"
#include <stdio.h>
#include "xil_printf.h"
#include "xuartps.h"
#include "xparameters.h"
#include "xscugic.h"
#include "xuartps_hw.h"#define LED_BASE XPAR_GPIO_0_S00_AXI_BASEADDR
#define UART_Device_Id XPAR_PS7_UART_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define UART_INT_IRQ_ID XPAR_XUARTPS_0_INTR
#define INTC XScuGicXUartPs UartPs;
INTC InterruptController;
void uart_init(XUartPs *UartInstPtr,u16 DeviceId)
{XUartPs_Config *Config;//根据ID查找配置信息Config = XUartPs_LookupConfig(DeviceId);//根据配置信息,初始化UARTXUartPs_CfgInitialize(UartInstPtr, Config, Config->BaseAddress);//设置波特率XUartPs_SetBaudRate(UartInstPtr, 115200);//设置触发阈值XUartPs_SetFifoThreshold(UartInstPtr, 1);//改变模式为正常模式XUartPs_SetOperMode(UartInstPtr, XUARTPS_OPER_MODE_NORMAL);
}
//中断处理函数
void UART_intr_handle(void *call_back_ref)
{XUartPs *uart_instance_ptr = (XUartPs *)call_back_ref;u32 rec_data = 0;u32 isr_status;//读取中断寄存器isr_status = XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,XUARTPS_IMR_OFFSET);isr_status &= XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,XUARTPS_ISR_OFFSET);//中断标志状态位,是否为RxFIFO触发if(isr_status & XUARTPS_IXR_RXOVR){rec_data = XUartPs_RecvByte(XPAR_PS7_UART_0_BASEADDR);XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress,XUARTPS_ISR_OFFSET,XUARTPS_IXR_RXOVR);//清除中断}XUartPs_SendByte(XPAR_PS7_UART_0_BASEADDR,rec_data);//将接受到的数据返回XGpioPs_WriteReg(LED_BASE,0,rec_data&0x0f);//将接收到的数据后4位写入LED的状态
}void uart_intr_int(INTC *IntcInstancePtr,XUartPs *UartInstancePtr,u16 UartIntrId)
{//UART控制器中断初始化XScuGic_Config *IntcConfig;IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);Xil_ExceptionInit();Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler) XScuGic_InterruptHandler,IntcInstancePtr);XScuGic_Connect(IntcInstancePtr, UartIntrId,(Xil_ExceptionHandler) UART_intr_handle,(void *) UartInstancePtr);XUartPs_SetInterruptMask(UartInstancePtr, XUARTPS_IXR_RXOVR);//设置触发leixXScuGic_Enable(IntcInstancePtr, UartIntrId);//使能中断设备Xil_ExceptionEnable();
}
int main()
{//初始化uart_init(&UartPs,UART_Device_Id);//UART控制器初始化uart_intr_int(&InterruptController, &UartPs,UART_INT_IRQ_ID);//收发数据print("Hello World\n\r");//打印hello World检测程序是否正常运行while(1){}return 0;
}
这样就实现了串口的双向传递,并利用了串口接收的数据去控制LED状态,比如,串口发送0x0a,LED灯就会按1010点亮.