最新电影在线观看,jrs低调看直播,avav天堂,囯产精品宾馆在线精品酒店,亚洲精品成人区在线观看

ZYNQ-利用PS引腳實現EMIO GPIO的驅動

學習內容

使用SDK和提供的API進行初始化GPIO,并驅動led和btn進行操作,實現led呼吸燈效果,串口讀取btn的值。

開發環境

vivado 18.3 && SDK 開發板 pynq-z2

原理講解

  • gpio可以看做一個外設,用于對器件的引腳作觀測(input)以及控制(output)
  • MIO 是將PS的外設和靜態存儲器接口的訪問多路復用到PS的引腳上。
  • 當我們的PS端的MIO不夠用時候,我們可以在搭建硬件平臺時候進行設計,將我們的PL端口的引腳定義拓展為EMIO然后被PS正常驅動。
  • gpio 被分為了4個bank bank0和bank1通過MIO連接到PS的引腳,bank2和bank3通過EMIO連接到PL

    這里給出GPIO的一個寄存器的結構圖,方便我們從底層更加深入了解gpio的具體配置的一個狀態

    圖片的上半部分表示的是和IO的中斷功能有關的寄存器,本節主要關注下面的部分。 通過閱讀UG585,我們可以知道寄存器組的不同功能:
  • DATA_RO:用來反映引腳的功能狀態
  • DATA:當GPIO信號被配置為輸出時,這個寄存器控制要輸出的值。該寄存器的所有32位同時寫入。
  • MASK_DATA_LSW: 用于屏蔽DATA的低16位
  • MASK_DATA_MSW: 用于屏蔽DATA的高16位
  • DIRM:用于控制IO引腳作為輸入還是輸出。0關閉輸出驅動,1打開輸出驅動
  • OEN:當IO配置為輸出時,用于控制打開或者關閉輸出使能。0關閉使能,1進行使能

硬件平臺搭建

同樣和前面相似,我們先添加IP  ZYNQ7,然后進行IP配置,選中uart sd gpio

EMIO的 gpio

APB AP transaction error, DAP status f0000021 問題解決方法

我們可以簡單的理解為zynq這個芯片是由這樣幾部分組成,ddr區,PS區,PL區。DDR區是存儲區,包括我們的芯片運行SDK的程序時候也是下載到這里。所以在我們沒有對應我們的板子配置好DDR時,會碰到這個錯誤信息 ==“APB AP transaction error, DAP status f0000021”== 這也是可以定位到我們在配置ddr信息時候沒有和開發板匹配,這里我進行操作的時候,我是添加了對應的板卡信息,ddr自動連線的時候會有一個加載預配置。 pynq板卡信息會自動幫你配置ddr的信息,這里我貼出pynqz2的ddr的具體信息,需要更改的地方我會標記指出:

EMIO和MIO的區別

前面提到了zynq7000的大致劃區,在ps區,也就是我們的arm核這里,一般都是引出了54個管腳進行開發,也就是我們在ZYNQ7的ip里在MIO config的可以配置的那些,這就是MIO我們可以針對這54個管腳進行配置自己想要的功能,一般不同的板卡會對應設計SD UART USB GPIO接口什么的,方便用戶進行PS端的單獨調試學習,那么,對于FPGA的PL端的引腳我們可以不可以進行PS操作調用呢?答案是肯定的!這就提到了EMIO的概念  EMIO的E就是 external的意思,也就是我們可以管腳定義了FPGA端的管腳進行擴展給PS端進行操作。 配置完成后如圖:

然后我們可以輸出生成頂層文件了

因為這里是用的EMIO,我們不能忘記新建約束文件進行管腳分配:

set_property -dict { PACKAGE_PIN R14   IOSTANDARD LVCMOS33 } [get_ports { GPIO0_tri_io[0] }]; #IO_L6N_T0_VREF_34 Sch=led[0]
set_property -dict { PACKAGE_PIN P14   IOSTANDARD LVCMOS33 } [get_ports { GPIO0_tri_io[1] }]; #IO_L4P_T0_35 Sch=btn[0]
set_property -dict { PACKAGE_PIN D20   IOSTANDARD LVCMOS33 } [get_ports { GPIO0_tri_io[2] }]; #IO_L4N_T0_35 Sch=btn[1]

最后綜合生成bit流,導出硬件,launch SDK

SDK軟件部分

運行SDK新建helloworld工程(不再多說,看前文),這里貼出SDK的main代碼:

#include 
#include "platform.h"
#include "xil_printf.h"
#include "xgpiops.h"
#include "xparameters.h"

#define GPIO_ID XPAR_PS7_GPIO_0_DEVICE_ID
#define LED0 54
#define BTN0 55
#define BTN1 56
static XGpioPs GpioPs;
static XGpioPs_Config *XGpioPs_Cfg;
int initGpio();
int main()
{
	u32 led = 0;
	int i,j;
	init_platform();
    initGpio();
    while(1){

    	for(i=0;i<1000;i++){
    		for(j=0;j<1000;j++){
    			usleep(1);
    			if(iBaseAddr);
	if( status != XST_SUCCESS){
		return XST_FAILURE;
	}
	XGpioPs_SetDirectionPin(&GpioPs,LED0,0x01);
	XGpioPs_SetOutputEnablePin(&GpioPs,LED0,0x01);
	XGpioPs_SetDirectionPin(&GpioPs,BTN0,0x00);
	XGpioPs_SetOutputEnablePin(&GpioPs,BTN0,0x00);
	XGpioPs_SetDirectionPin(&GpioPs,BTN1,0x00);
	XGpioPs_SetOutputEnablePin(&GpioPs,BTN1,0x00);
}

部分代碼解釋

#include "xgpiops.h"
#include "xparameters.h"

#define GPIO_ID XPAR_PS7_GPIO_0_DEVICE_ID
#define LED0 54
#define BTN0 55
#define BTN1 56

這里的XPAR_PS7_GPIO_0_DEVICE_ID可以在 "xparameters.h" 尋到,對于LED0 BTN0 BTN1的定義,正是因為前文提到的EMIO的概念,直接PS課操作的管腳54個,是從MIO 0 -- MIO 53 所以這里的EMIO的擴展引腳編號就是54往后,從GPIO0_tri_io 0 依次往后進行編號,也可以理解為管腳號。

int initGpio(){
	int status;
	XGpioPs_Cfg = XGpioPs_LookupConfig(GPIO_ID);
	status = XGpioPs_CfgInitialize(&GpioPs,XGpioPs_Cfg,XGpioPs_Cfg->BaseAddr);
	if( status != XST_SUCCESS){
		return XST_FAILURE;
	}
	XGpioPs_SetDirectionPin(&GpioPs,LED0,0x01);
	XGpioPs_SetOutputEnablePin(&GpioPs,LED0,0x01);
	XGpioPs_SetDirectionPin(&GpioPs,BTN0,0x00);
	XGpioPs_SetOutputEnablePin(&GpioPs,BTN0,0x00);
	XGpioPs_SetDirectionPin(&GpioPs,BTN1,0x00);
	XGpioPs_SetOutputEnablePin(&GpioPs,BTN1,0x00);
}

初始化函數同前文iic的配置,和keil開發32的流程類似,聲明結構體進行初始化,然后設置GPIO的方向,輸入還是輸出模式。

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 2
收藏 3
關注 20
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧