写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,会用就行,理解即可。
今记于此,与君共勉!