MIO和GPIO概述
GPIO-Bank0/Bank1基础寄存器配置
GPIO作为外设被分为4组(4个Bank):Bank0~Bank3。
Bank0和Bank1通过MIO连接到PS的引脚。
Bank2和Bank3通过EMIO连接到PL。
现在我们来看Bank0和Bank1的GPIO:
(1)Input配置:
DATA_RO(read only) 寄存器: 存储GIPO读入的电平数据。
【注意: 他是一个只读寄存器,我们无法对他进行写入。】 【注意:无论GPIO配置为input还是output模式,DATA_RO内都会观测、写入IO口的电平。(通过图中的“三态门”也能看出)】
(2)Output配置:
DATA寄存器:在GPIO被配置为output模式时,DATA寄存器存储我们将要输出的电平数据。
【注意:对DATA进行写入操作时,必须一次性写入32bits,不能单独操作某一位。】 【注意:如果我们对DATA进行读取操作,将会得到DATA上一次存储的数据。】
MASK_DATA_LSW(低16位)和MASK_DATA_MSW(高16位)寄存器:通过写入这个寄存器,屏蔽DATA对应几位。这样我们再次写入DATA时,就可以仅仅改变DATA寄存器的某几位。
【注意:DATA有32bits而一个MASK仅有16bits,固有高16位和低16位的两个MASK寄存器。】 【注意:更改DATA寄存器内的数值,需要经过Read-Modify-Write过程】 【使用例】 DATA(32bits):1010_1100_0011_0101_1100_0011_0101_1100,我想修改DATA的最高四位。 MASK(16bits+16bits):0000_1111_1111_1111 + 1111_1111_1111_1111,最高四位是0000因而没有被屏蔽。 此时再次写入DATA:0101_0000_0000_0000_0000_0000_0000_0000。 写入结束以后,DATA内最终存储:0101_1100_0011_0101_1100_0011_0101_1100。
(3)输入输出模式配置:
DIRM(Direction Mode)寄存器:控制GPIO的方向。即配置GPIO为“Input模式”或“Output模式”。
【注意:实际上,DIRM仅用于控制“输出使能”。(通过图中的“三态门”也能看出)】 【注意:DIRM=1时,使能输出Output驱动。 DIRM=0时,关闭输出Output驱动。】
OEN(Output Enable)寄存器:当GPIO配置为输出Output模式时,该寄存器控制输出使能与否。(即相当于对输出的二次控制)
【注意:OEN=0,关闭使能;OEN=1,开启使能。】
我们清楚地看到,OEN与DIRM后接入“与门”。即:当DIRM=1和OEN=1同时配置时,输出通道才被打开了。
(4)MIO[8:7]配置:
MIO[8:7] 在系统复位过程中作为VMODE引脚(作为输入),用于配置MIO-Bank的电压。(复位结束后,只能作为输出信号)
硬件配置
①添加ZYNQ核,配置DDR3、UART和GPIO: 发现错误,关闭不需要的引脚。 注意,我们直接将PS的引脚引出,不经过FPGA的部分。如果不这样做,还需要另外添加AXI_GPIO的IP核。
②生成硬件设计文件,创建顶层封装:
软件书写
①将硬件设计顶层文件导入到SDK: ②启动SDK,新建工程: SDK中: 在刚才创建的工程文件夹的src文件夹下,创建新的main.c文件(source file):
③参考官方demo书写自己的代码: (1)官方的demo在system.mss中寻找:Documentation可以查看帮助文档 (2)点击上图的Import Examples导入demo: (第一个xgpiops_intr_example设计中断,暂不导入)
这些代码,将是我们自己配置GPIO时,需要参考的。
④代码书写:
GPIO接口使用流程: (1)初始化GIPO驱动(GPIO driver)。 (2)配置GPIO的方向(Input or Output)。 (3)设置输入/输出使能。 (4)如果要输出,写数据到GPIO的输出引脚。
(1) 初始化GPIO驱动: 先从demo(xgpiops_polled_example.c)中拷贝下图程序中的25,27行的代码。此时程序必然会报错。查看报错信息,按住ctrl点击对应变量或者函数,溯源,然后在main中添加宏定义,全局变量声明或者头文件。 (2)设置为输出模式,并且使能: (3)给GPIO写数据: (4)后续处理:配置函数最好都封装在函数里。
本工程实例完整代码main.c:
#include<stdio.h>
#include"xgpiops.h"
#include"xparameters.h"
#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
XGpioPs Gpio;
static u32 Output_Pin = 0;
void GPIO_OUTPUT_INIT(u32 Output_Pin)
{
XGpioPs_Config * ConfigPtr;
s32 Status;
ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
XGpioPs_SetDirectionPin(&Gpio, Output_Pin, 1);
XGpioPs_SetOutputEnablePin(&Gpio, Output_Pin, 1);
}
void GPIO_Write(u32 Output_Pin,u32 Data_Send)
{
XGpioPs_WritePin(&Gpio, Output_Pin, Data_Send);
}
int main(void)
{
printf("GPIO-MIO-TEST\n\r");
GPIO_OUTPUT_INIT(Output_Pin);
GPIO_Write(Output_Pin,0x0);
return 0;
}
附录:GPIO常规配置函数集【重要】
#include<stdio.h>
#include"xgpiops.h"
#include"xscugic.h"
#include"xparameters.h"
#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
XGpioPs Gpio;
static u32 Output_Pin_m = 0;
static u32 Input_Pin_m = 0;
void GPIO_OUTPUT_INIT(u32 Output_Pin);
void GPIO_INPUT_INIT(u32 Input_Pin);
void GPIO_Write(u32 Output_Pin,u32 Data_Send);
u32 GPIO_Read(u32 Iutput_Pin);
void GPIO_OUTPUT_INIT(u32 Output_Pin)
{
XGpioPs_Config * ConfigPtr;
ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
XGpioPs_SetDirectionPin(&Gpio, Output_Pin, 1);
XGpioPs_SetOutputEnablePin(&Gpio, Output_Pin, 1);
}
void GPIO_INPUT_INIT(u32 Output_Pin)
{
XGpioPs_Config * ConfigPtr;
ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
XGpioPs_SetDirectionPin(&Gpio, Output_Pin, 0);
XGpioPs_SetOutputEnablePin(&Gpio, Output_Pin, 1);
}
void GPIO_Write(u32 Output_Pin,u32 Data_Send)
{
XGpioPs_WritePin(&Gpio, Output_Pin, Data_Send);
}
u32 GPIO_Read(u32 Iutput_Pin)
{
u32 read_data;
read_data = XGpioPs_ReadPin(&Gpio, Iutput_Pin);
return read_data;
}
|