ZYNQ+Vivado2015.2系列(十五)AXI Timer 用户定时器中断控制LED

前面的中断学习中我们学了按键,GPIO,Timer,是时候把它们整合到一起了。今天我们混合使用PS/PL部分的资源,建立一个比较大的系统。

板子:zc702。

实现功能如下:

1.通过串口打印信息询问你要按SW5还是SW7;

2.当正确的按键被按下,定时器启动,关闭led DS23;

3.当定时器溢出后触发中断,开启DS23,系统回到1。

我们用一个AXI GPIO连接到SW5,EMIO连接SW7,MIO连接DS23(固定连接),定时器也使用PL的AXI Timer。

AXI Timer的主要特性:

ZYNQ+Vivado2015.2系列(十五)AXI Timer 用户定时器中断控制LED_第1张图片

硬件系统

1.添加zynq核,AXI GPIO,AXI Timer

2.打开zynq核的配置,使能UART 1,使能GPIO MIO,添加1 bit的EMIO GPIO,使能PL-PS中断IRQ_F2P

3.AXI GPIO宽度设为1

ZYNQ+Vivado2015.2系列(十五)AXI Timer 用户定时器中断控制LED_第2张图片

ZYNQ+Vivado2015.2系列(十五)AXI Timer 用户定时器中断控制LED_第3张图片

4.点击自动连接,所有都可以自动连接

5.将zynq的IRQ_F2P[0:0] 连接到AXI Timer的interrupt,点击zynq的GPIO_0  右键Make External ,点击输出的引脚可以修改信号名称

生成顶层文件:
ZYNQ+Vivado2015.2系列(十五)AXI Timer 用户定时器中断控制LED_第4张图片


添加约束

连接到两个按键,AXI GPIO连接到SW5,EMIO 连接到SW7

ZYNQ+Vivado2015.2系列(十五)AXI Timer 用户定时器中断控制LED_第5张图片

set_property PACKAGE_PIN G19 [get_ports {gpio_sw_tri_i[0]}]
set_property IOSTANDARD LVCMOS25 [get_ports {gpio_sw_tri_i[0]}]
set_property PACKAGE_PIN F19 [get_ports {gpio_0_tri_io[0]}]
set_property IOSTANDARD LVCMOS25 [get_ports {gpio_0_tri_io[0]}]

另外,LED DS 23连接在MIO 10:
ZYNQ+Vivado2015.2系列(十五)AXI Timer 用户定时器中断控制LED_第6张图片ZYNQ+Vivado2015.2系列(十五)AXI Timer 用户定时器中断控制LED_第7张图片

生成比特文件,打开SDK。


软件部分

代码来自于Xilinx官方。


#include 
#include "platform.h"
#include "xil_types.h"
#include "xgpio.h"
#include "xtmrctr.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "xil_io.h"
#include "xil_exception.h"
#include "xscugic.h"
static XGpioPs psGpioInstancePtr;
extern XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES];
static int iPinNumber = 10;
XScuGic InterruptController; /* Instance of the Interrupt Controller */
static XScuGic_Config *GicConfig;/* The configuration parameters of the
controller */
static int InterruptFlag;
//void print(char *str);
extern char inbyte(void);
void Timer_InterruptHandler(void *data, u8 TmrCtrNumber)
{
	print(" Inside Timer ISR \n \r ");
	XTmrCtr_Stop(data,TmrCtrNumber);
	// PS GPIO Writting
	print("LED 'DS23' Turned ON \r\n");
	XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,1);
	XTmrCtr_Reset(data,TmrCtrNumber);
	print(" Timer ISR Exit\n \n \r");
	InterruptFlag = 1;
}
int SetUpInterruptSystem(XScuGic *XScuGicInstancePtr)
{
	/*
	* Connect the interrupt controller interrupt handler to the hardware
	* interrupt handling logic in the ARM processor.
	*/
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
	(Xil_ExceptionHandler) XScuGic_InterruptHandler,
	XScuGicInstancePtr);
	/*
	* Enable interrupts in the ARM
	*/
	Xil_ExceptionEnable();
	return XST_SUCCESS;
}
int ScuGicInterrupt_Init(u16 DeviceId,XTmrCtr *TimerInstancePtr)
{
	int Status;
	/*
	* Initialize the interrupt controller driver so that it is ready to
	* use.
	* */
	GicConfig = XScuGic_LookupConfig(DeviceId);
	if (NULL == GicConfig) {
	return XST_FAILURE;
	}
	Status = XScuGic_CfgInitialize(&InterruptController, GicConfig,
	GicConfig->CpuBaseAddress);
	if (Status != XST_SUCCESS) {
	return XST_FAILURE;
}
/*
* Setup the Interrupt System
* */
Status = SetUpInterruptSystem(&InterruptController);
if (Status != XST_SUCCESS) {
	return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an
* interrupt for the device occurs, the device driver handler performs
* the specific interrupt processing for the device
*/
Status = XScuGic_Connect(&InterruptController,
XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR,
(Xil_ExceptionHandler)XTmrCtr_InterruptHandler,
(void *)TimerInstancePtr);
if (Status != XST_SUCCESS) {
	return XST_FAILURE;
}
/*
* Enable the interrupt for the device and then cause (simulate) an
* interrupt so the handlers will be called
*/
XScuGic_Enable(&InterruptController, XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR);
	return XST_SUCCESS;
}
int main()
{
	static XGpio GPIOInstance_Ptr;
	XGpioPs_Config*GpioConfigPtr;
	XTmrCtr TimerInstancePtr;
	int xStatus;
	u32 Readstatus=0,OldReadStatus=0;

	int iPinNumberEMIO = 54;
	u32 uPinDirectionEMIO = 0x0;

	u32 uPinDirection = 0x1;
	int exit_flag,choice,internal_choice;
	init_platform();

	xStatus = XGpio_Initialize(&GPIOInstance_Ptr,XPAR_AXI_GPIO_0_DEVICE_ID);
	if(XST_SUCCESS != xStatus)
		print("GPIO INIT FAILED\n\r");

	XGpio_SetDataDirection(&GPIOInstance_Ptr, 1,1);//AXI GPIO  1表示输入

	xStatus = XTmrCtr_Initialize(&TimerInstancePtr,XPAR_AXI_TIMER_0_DEVICE_ID);
	if(XST_SUCCESS != xStatus)
		print("TIMER INIT FAILED \n\r");

	XTmrCtr_SetHandler(&TimerInstancePtr,
	Timer_InterruptHandler,
	&TimerInstancePtr);

	XTmrCtr_SetResetValue(&TimerInstancePtr,
	0, //Change with generic value
	0xff000000);

	XTmrCtr_SetOptions(&TimerInstancePtr,
	XPAR_AXI_TIMER_0_DEVICE_ID,
	(XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION ));//Setting timer Option (Interrupt Mode And Auto Reload )

	GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
	if(GpioConfigPtr == NULL)
	return XST_FAILURE;
	xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,
	GpioConfigPtr,
	GpioConfigPtr->BaseAddr);
	if(XST_SUCCESS != xStatus)
		print(" PS GPIO INIT FAILED \n\r");

	XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumber,uPinDirection);//MIO上的DS23  1代表输出
	XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumber,1);//1 for Enabling Output Enable

	XGpioPs_SetDirectionPin(&psGpioInstancePtr,
	iPinNumberEMIO,uPinDirectionEMIO);  //EMIO上的SW7   0代表输入
	XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumberEMIO,0); //0 for Disabling Output Enable

	xStatus=ScuGicInterrupt_Init(XPAR_PS7_SCUGIC_0_DEVICE_ID,&TimerInstancePtr);
	if(XST_SUCCESS != xStatus)

	//User selection procedure to select and execute tests
	exit_flag = 0;
	while(exit_flag != 1)
	{
		print("------- Menu Starts -------\r\n");
		print("Press '1' to use NORMAL GPIO as an input (SW5 switch)\r\n");
		print("Press '2' to use EMIO as an input (SW7 switch)\r\n");
		print("Press any other key to Exit\r\n");

		choice = inbyte();//等待串口输入
		printf("Selection : %c \r\n",choice);
		internal_choice = '1';
		switch(choice)
		{
		// Use case for AXI GPIO
		case '1':
		exit_flag = 0;
		print("Press Switch 'SW5' push button on board \r\n");
		print(" \r\n");
		while(internal_choice != '0')
		{
			Readstatus = XGpio_DiscreteRead(&GPIOInstance_Ptr, 1);
			if(1== Readstatus && 0 == OldReadStatus )
			{
				print("SW5 PUSH Button pressed \n\r");
				print("LED 'DS23' Turned OFF \r\n");
				XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,0);
				//Start Timer
				XTmrCtr_Start(&TimerInstancePtr,0);
				print("timer start \n\r");
				//Wait For interrupt;
				print("Wait for the Timer interrupt to tigger \r\n");
				print(" \r\n");
				while(InterruptFlag != 1);
				InterruptFlag = 0;
				print("Press '0' to go to Main Menu \n\r ");
				print("Press any other key to remain in AXI GPIO Test \n\r ");
				internal_choice = inbyte();
				printf("Select = %c \r\n",internal_choice);
				if(internal_choice != '0')
				{
					print("Press Switch 'SW5' push button on board \r\n");
				}
			}
			OldReadStatus = Readstatus;
		}
		print(" \r\n");
		print(" \r\n");
		break;
		case '2' :
			//Use  case for PS GPIO
			exit_flag = 0;
			print("Press Switch 'SW7' push button on board \r\n");
			print(" \r\n");
			while(internal_choice != '0')
			{
				Readstatus = XGpioPs_ReadPin(&psGpioInstancePtr,
				iPinNumberEMIO);
				if(1== Readstatus && 0 == OldReadStatus )
				{
					print("SW7 PUSH Button pressed \n\r");
					print("LED 'DS23' Turned OFF \r\n");
					XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,0);
					//Start Timer
					XTmrCtr_Start(&TimerInstancePtr,0);
					print("timer start \n\r");
					//Wait For interrupt;
					print("Wait for the Timer interrupt to tigger \r\n");
					print(" \r\n");
					while(InterruptFlag != 1);
					InterruptFlag = 0;
					print("Press '0' to go to Main Menu \n\r ");
					print("Press any other key to remain in EMIO Test \n\r ");
					internal_choice = inbyte();
					printf("Select = %c \r\n",internal_choice);
					if(internal_choice != '0')
					{
						print("Press Switch 'SW7' push button on board \r\n");
					}
				}
				OldReadStatus = Readstatus;
			}
			print(" \r\n");
			print(" \r\n");
			break;
			default :
			exit_flag = 1;
			break;
			}
		}
		print("BYE \r\n");
		cleanup_platform();
		return 0;
	}

从main函数开始:
定义三个实例:

AXI GPIO实例:XGpio

AXI Timer实例:XTmrCtr

前面还定义了EMIO GPIO实例:XGpioPs

(EMIO Pin脚是54,DS 23  Pin脚是10)


AXI GPIO初始化:XGpio_Initialize

AXI GPIO设置数据方向:XGpio_SetDataDirection  1表示输入,这个IO是接SW5的


AXI Timer初始化:XTmrCtr_Initialize

设置AXI Timer中断处理器:XTmrCtr_SetHandler   这个处理器就是我们自定义的功能Timer_InterruptHandler(),中断发生之后去干嘛,这里我们实现的是点亮DS 23

设置AXI Timer初始值:XTmrCtr_SetResetValue

定时器功能设置:XTmrCtr_SetOptions  

 XTC_INT_MODE_OPTIONEnables the timer counter interrupt output.

XTC_AUTO_RELOAD_OPTIONconfigures the timer counter to reload from the compare value           


PS的GPIO初始化:XGpioPs_LookupConfig  XGpioPs_CfgInitialize

设置IO的数据方向:XGpioPs_SetDirectionPin   //MIO上的DS23  1代表输出  | EMIO上的SW7   0代表输入

XGpioPs_SetOutputEnablePin  ////1 for Enabling Output Enable   0 for Disabling Output Enable


GIC初始化:封装在ScuGicInterrupt_Init()函数

XScuGic_LookupConfig-->XScuGic_CfgInitialize


while循环:向控制台输入一个值,利用inbyte()接收,利用case选择是使用SW5还SW7触发定时器,触发后开启定时器,中断发生点亮DS 23。当标志位exit_flag不等于1持续这个操作,没有进入任何case分支,进入default,默认里面设置exit_flag=1,退出while,程序就结束了。

注:我在测试的时候,inbyte()会时不时抽风,需要重启应用程序,有待考究。


你可能感兴趣的:(ZYNQ)