ZYNQ之GPIO

1.GPIO(generate )

在这里插入图片描述
PS端
500和501:共54根引脚,连接PS MIO,外设通过MIO用软件进行多路复用。
502:用来和DDR连接的。

PL端:13、34、35。

1.GPIO是一个外设,用来对器件引脚做观测(input)以及控制(output)。
2.每个IO都可以独立的、动态的编程。作为输入/输出/中断模式每个IO对应一个寄存器地址。控制IO的本质是读写寄存器地址。
3.GPIO被分成了四个bank,bank0和bank1通过MIO连接到PS引脚,bank2和bank3通过EMIO连接到PL引脚。
4.软件通过一组存储映射(memery-mapped)的寄存器来控制GPIO.
#存储映射:是指一次读写操作过程中的地址

控制GPIO的寄存器组
1.DATA_RO:用来反映器件引脚的状态。
2.DATA:32位,当GPIO被配置成输出的时候,该寄存器可以控制输出的值。
3.MASK_DATA_LSW/MASK_DATA_MSW:16位掩膜。
4.DIRM:控制IO引脚是作为输入还是输出。本质是控制输出使能。
5.OEN:当配置成输出(DIRM=1)的时候,OEN才有用。该寄存器用来打开/关闭输出使能。决定输出时data还是高阻态。

1.1 GPIO功能配置

上电和复位在编程时不需要考虑。

1.1.1 GPIO Configuration

2.MIO和EMIO

在这里插入图片描述
ZYNQ GPIO 接口信号被分成四组,分别是从 BANK0 到 BANK3。
其中 BANK0 和 BANK1 中共计 54个信号通过 MIO 连接到 ZYNQ 器件的引脚上,这些引脚属于 PS 端;
而 BANK2 和 BANK3 中共计 64 个信号则通过 EMIO 连接到了 ZYNQ 器件的 PL 端。
在这里插入图片描述
上半部分为中断有关的寄存器,下半部分为数据有关的寄存器。
在这里插入图片描述

控制GPIO的寄存器组
1.DATA_RO:当GPIO被配置成输入时,使软件观察到GPIO上的值。
2.DATA:32位,当GPIO被配置成输出的时候,该寄存器可以控制输出的值。
3.MASK_DATA_LSW/MASK_DATA_MSW:16位掩膜。
4.DIRM:控制IO引脚是作为输入还是输出。本质是控制输出使能。
5.OEN:当配置成输出(DIRM=1)的时候,OEN才有用。该寄存器用来打开/关闭输出使能。决定输出时data还是高阻态。

2.1 MIO

MIO:将来自PS外设和静态存储器接口的访问多路复用到PS的引脚上。把PS的外设和PS的引脚连接起来。并不是一一对应,可通过编程改变(多路复用)。

2.2 EMIO

EMIO(extendable multiuse I/O):是PS和PL之间的接口,扩展PS的引脚,使用FPGA端的引脚。PL端的引脚给PS端使用。
PS可以通过EMIO访问PL端。

4.GPIO中断

在这里插入图片描述

控制中断的寄存器组
1.INT_TYPR:中断类型选择——边沿或者电平(1边沿0电平)。
2.INT_POLARITY:极性选择(1正极性或者0负极性)。根据中断类型是边沿还是电平来确定是升降边沿还是高低电平触发。
3.INT_ANY:只针对边沿触发,是否同时支持升降沿触发(0不支持1支持)。
以上三个值进入中断逻辑寄存器来确定最后的中断触发条件
4.INT_STAT:写1清除中断。读来获取当前中断状态。
5.INT_MASK:中断屏蔽,选择性的屏蔽某些端口的GPIO
6.INT_DIS/INT_EN:使能或者关闭中断使能。
7.IRQ #52 to GIC:可以接收到PS和PL的中断请求信号。每个中断源都有一个自己的ID,GPIO的中断号为52.
在这里插入图片描述
在这里插入图片描述

5.代码

5.1 MIO和EMIO控制GPIO

/*
 	 用PL端口的GPIO操控PS端口的LED
 	 按键按下为1,没按下为0;
 	 灯1亮,0灭
*/
#include "stdio.h"
#include "xparameters.h"
#include "xgpiops.h"


#define GPIO_DEVICE_ID  	XPAR_XGPIOPS_0_DEVICE_ID

//核心板上PS端LED
#define	MIO_0_LED			0
//底板上PS端的LED
#define	MIO_7_LED 			7
#define MIO_8_LED			8
//底板上PS端的按键
#define	MIO_11_KEY 			11		//KEY1
#define	MIO_12_KEY 			12		//KEY0
//底板上PL端的按键
#define	EMIO_KEY0 			54		//bank35 L20 PL KEY0


XGpioPs_Config * 	ConfigPtr	;

XGpioPs 			Gpio		;	/* The driver instance for GPIO Device. */

int main(){
	u32 ps_key0_value;
	u32 ps_key1_value;
	u32 pl_key0_value;
	printf("GPIO EMIO TEST!\n\r");

	//根据器件ID,查找器件的配置信息,返回值是一个结构体指针(XGpioPs_Config *)
	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);

	//初始化GPIO驱动
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);

	//把GPIO的方向设置为输出(0输入 1输出)
	XGpioPs_SetDirectionPin(&Gpio, MIO_0_LED, 1);
	XGpioPs_SetDirectionPin(&Gpio, MIO_7_LED, 1);
	XGpioPs_SetDirectionPin(&Gpio, MIO_8_LED, 1);

	//把GPIO的方向设置为输入(0输入 1输出)
	XGpioPs_SetDirectionPin(&Gpio, EMIO_KEY0, 0);
	XGpioPs_SetDirectionPin(&Gpio, MIO_12_KEY, 0);
	XGpioPs_SetDirectionPin(&Gpio, MIO_11_KEY, 0);

	//设置输出使能(0关闭 1打开)
	XGpioPs_SetOutputEnablePin(&Gpio, MIO_0_LED, 1);
	XGpioPs_SetOutputEnablePin(&Gpio, MIO_7_LED, 1);
	XGpioPs_SetOutputEnablePin(&Gpio, MIO_8_LED, 1);
	//写数据到GPIO
	while(1){
		//读取按键状态
		ps_key0_value = XGpioPs_ReadPin(&Gpio, MIO_12_KEY);
		ps_key1_value = XGpioPs_ReadPin(&Gpio, MIO_11_KEY);
		pl_key0_value = XGpioPs_ReadPin(&Gpio, EMIO_KEY0);
		//将按键状态写入LED(按键按下灯亮,松开灯灭)
		XGpioPs_WritePin(&Gpio,MIO_0_LED,~ps_key0_value);
		XGpioPs_WritePin(&Gpio,MIO_7_LED,~ps_key1_value);
		XGpioPs_WritePin(&Gpio,MIO_8_LED,~pl_key0_value);
	}
	return 0;
}

5.2 中断控制GPIO

/*
 	 用PS端口的GPIO操控PS端口的LED
*/
#include "stdio.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "sleep.h"
#include "xscugic.h"


#define GPIO_DEVICE_ID  	XPAR_XGPIOPS_0_DEVICE_ID
//GPIO的中断号
#define GPIO_INTERRUPT_ID	XPAR_XGPIOPS_0_INTR
//GIC器件ID
#define INTC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID

//核心板上PS端LED
#define	MIO_0_LED			0
//PS端按键KEY
#define MIO_12_KEY 			12

XGpioPs_Config * 	ConfigPtr	;
XScuGic_Config * 	IntcConfig	; /* Instance of the interrupt controller */

//驱动实例
XGpioPs 			Gpio		;	/* The driver instance for GPIO Device. */
XScuGic 			Intc		;	/* The Instance of the Interrupt Controller Driver */

void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio,u16 GpioIntrId);
void IntrHandler();//中断服务函数

u32	key_press = 0;

int main(){
	u32	led_value = 0;
	printf("GPIO INTERUPT TEST!\n\r");

	//根据器件ID,查找器件的配置信息,返回值是一个结构体指针(XGpioPs_Config *)
	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);

	//初始化GPIO驱动
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);

	//把GPIO的方向设置为输出(0输入 1输出)
	XGpioPs_SetDirectionPin(&Gpio, MIO_0_LED, 1);

	//把GPIO的方向设置为输入(0输入 1输出)
	XGpioPs_SetDirectionPin(&Gpio, MIO_12_KEY, 0);

	//设置输出使能(0关闭 1打开)
	XGpioPs_SetOutputEnablePin(&Gpio, MIO_0_LED, 1);

	//
	SetupInterruptSystem(&Intc, &Gpio, GPIO_INTERRUPT_ID);
	//写数据到GPIO
	while(1){
	//改变LED的显示状态
		if(key_press == 1){
			led_value = ~led_value;
			key_press = 0;
			//清除之前的中断状态
			XGpioPs_IntrClearPin(&Gpio,MIO_12_KEY);
			//延时消抖
			XGpioPs_WritePin(&Gpio,MIO_0_LED,led_value);
			//再次使能中断
			usleep(200000);
			XGpioPs_IntrEnablePin(&Gpio,MIO_12_KEY);
		}
	}
	return 0;
}

//设置中断
void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio,
				u16 GpioIntrId)
{

	//查找GIC器件配置信息,并进行初始化
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);

	//初始化RAM处理器异常句柄
	Xil_ExceptionInit();
	//给IRQ注册异常处理程序
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
				(Xil_ExceptionHandler)XScuGic_InterruptHandler,
				GicInstancePtr);
	//使能处理器的中断
	Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

	//关联中断处理函数,当外部中断来临时
	XScuGic_Connect(GicInstancePtr, GpioIntrId,(Xil_ExceptionHandler)IntrHandler,(void *)Gpio);
	//为GPIO器件使能中断,对中断控制器进行配置
	XScuGic_Enable(GicInstancePtr, GpioIntrId);

	//设置MIO引脚中断类型为下降沿触发
	XGpioPs_SetIntrTypePin(Gpio, MIO_12_KEY, XGPIOPS_IRQ_TYPE_EDGE_FALLING);
	//打开中断使能,对IO管脚配置
	XGpioPs_IntrEnablePin(Gpio, MIO_12_KEY);
}
void IntrHandler(){
	printf("interupt detected!\n\r ");
	key_press = 1;
	//屏蔽中断
	XGpioPs_IntrDisablePin(&Gpio,MIO_12_KEY);
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值