ZYNQ——PS端之XGpioPs_WritePin()函数详解

本文详细解析了Zynq平台下通过GPIO寄存器控制IO电平的具体流程,包括如何通过XGpioPs_WritePin函数实现对特定pin的高低电平输出,并深入探讨了针对不同pin范围所涉及的LSW与MSW寄存器的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写pin值函数,输出0还是1
void XGpioPs_WritePin(XGpioPs *InstancePtr, u32 Pin, u32 Data)
  参数1:XGpioPs结构体指针
  参数2:待写pin
  参数3:输出高电平为1,输出低电平为0
  返回值:无

void XGpioPs_WritePin(XGpioPs *InstancePtr, u32 Pin, u32 Data)
{
	u32 RegOffset;
	u32 Value;
	u8 Bank;
	u8 PinNumber;
	u32 DataVar = Data;

	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
	Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);

	/* Get the Bank number and Pin number within the bank. */
	XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);

	if (PinNumber > 15U) {
		/* There are only 16 data bits in bit maskable register. */
		PinNumber -= (u8)16;
		RegOffset = XGPIOPS_DATA_MSW_OFFSET;
	} else {
		RegOffset = XGPIOPS_DATA_LSW_OFFSET;
	}

	/*
	 * Get the 32 bit value to be written to the Mask/Data register where
	 * the upper 16 bits is the mask and lower 16 bits is the data.
	 */
	DataVar &= (u32)0x01;
	Value = ~((u32)1 << (PinNumber + 16U)) & ((DataVar << PinNumber) | 0xFFFF0000U);
	XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
			  ((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) +
			  RegOffset, Value);
}

你有没有发现,对于gpio的操控函数的流程大致都是一样的,先校验,然后计算出属于哪个bank模块,然后取出寄存器初始值,在写入我们想写入的值。
  假如我们要操控pin7,输出高电平
那么就调用函数,XGpioPs_WritePin(&psGpioInstancePtr, 7, 1);验证这个函数是否能输出高电平,我们其实可以直接上板子,测量电压。但在此我们还是来分析一下他是怎么实现怎么操控寄存器的,毕竟这种操控寄存器方式是我们最熟悉的最 容易理解的。

XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
			  ((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) +
			  RegOffset, Value);

  1:InstancePtr->GpioConfig.BaseAddr = 0xE000A000
  2:(Bank) * XGPIOPS_DATA_MASK_OFFSET) = 0*0x00000008U
  3:XGPIOPS_DATA_LSW_OFFSET = RegOffset =0
所以最终的addr = 0xE000A000 +0 +0 =0xE000A000
在这里插入图片描述
我们可以从数据手册中找到这个寄存器,就是控制io电平的。这里有一点主要注意的,我们在前面遇到的初始化,设置方向,打开使能等操作,我们可以在datasheet中看到基本上都是一个32的寄存器的每个bit一一对应每个pin脚,比如bank0就是这样的。但是在控制io输出时,我们可以看到这个寄存器只能控制16个pin的输出,所以还需要一个寄存器来控制。对于这一点其实在代码中有体现:

	if (PinNumber > 15U) {
		/* There are only 16 data bits in bit maskable register. */
		PinNumber -= (u8)16;
		RegOffset = XGPIOPS_DATA_MSW_OFFSET;
	} else {
		RegOffset = XGPIOPS_DATA_LSW_OFFSET;
	}

就是这段代码,他会判断输入进来的pin num是0-15还是16-31,因为是不同的寄存器控制,所有在地址偏移的的时候RegOffset 的值就会不一样。假设我们得pin num输入为20,那么最后的addr就会等于:
0xE000A000 +0 +0x00000004 =0xE000A004
在这里插入图片描述
 .  其实从这一点来看,库函数的调用更加方便,官方已经考虑这些因素在里面,写的很兼容。如果是自己在哪里 直接操控寄存器,太麻烦还容易出错,zynq里面的寄存器太多了,多到你都看不完,而且你还需要去理解记住每个寄存器的作用及用法,这工作量就太重了。我们只是去学习,又不是原厂写bsp,会用就行,理解即可。
今记于此,与君共勉!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值