[X]关闭
0

(基础篇)S05-CH02-GPIO-LED

摘要: 上一章我们讲解了如何搭建一个MicroBlaze最小系统,并在SDK中跑了一个Hello World历程。这节课将继续学习MicroBlaze软核,本节将通过软核控制一个GPIO以达到LED的流水效果,这是MicroBlaze的一个比较经典的案例。

软件版本:VIVADO2017.4

操作系统:WIN10

硬件平台: ARTIX-7 系列开发板

米联客(MSXBO)论坛www.osrc.cn答疑解惑专栏开通,欢迎大家给我提供!!!

2.1 概述

       上一章我们讲解了如何搭建一个MicroBlaze最小系统,并在SDK中跑了一个Hello World历程。这节课将继续学习MicroBlaze软核,本节将通过软核控制一个GPIO以达到LED的流水效果,这是MicroBlaze的一个比较经典的案例。

2.2 硬件工程搭建

      在上一章当中,我们将bd文件导出为了一个tcl文件,那么在本章就将使用到这个tcl脚本。我们将其拷贝到本章工程文件夹下,创建一个名为tcl的文件夹,将其放置在这个文件夹下,然后就可以正式开始硬件工程搭建。

Step1:创建一个名为System的vivado工程(还不会的请回顾之前的课程)。

Step2:在tcl控制台中输入下面的指令运行上一节产生的tcl文件。

上图中,source是运行命令,后面跟的是tcl文件的存放路径,注意要根据自身的情况进行调整,按Enter键之后开始运行。

Step3:运行完成之后,系统自动创建完成了与上一章相同的硬件。这时候我们只需要根据自身的需求进行增加即可。这里我们添加一个GPIO。

Step4:双击GPIO,将其位宽改为4,因为开发板上有4个LED。

Step5:将GPIO输出引脚的名字改为LED(不知道怎么改的回顾本季第一章),如下图所示:

Step6:选中S_AXI,选择OK。

至此,硬件系统就搭建完成了,可以发现,工作量减少了很多,设计效率显著提高。

Step7: 选中top.bd,右单击然后选择Generate Output Products。

Step8:在弹出来的窗口中,如下图所示,然后单击OK。

Step8:选中top.bd,右单击然后选择Create HDL Wrapper,在弹出来的窗口中直接点击OK。

Step9:添加约束文件。

Step10:单击产生Bit文件。

Step11:生成Bit文件之后,单击File-Export-Export Hardware。

Step12:单击File-Launch SDK,加载SDK。

2.3 软件设计

Step1:单击File-New-Application Project开始创建一个SDK工程。

Step2:在新弹出来的窗口中,输入工程名字GPIO_Test (注意不能有非法字符)。

Step3:单击Next,然后在左侧选择Empty Application(空白工程),最后选择Finish。

       创建完成之后,这里分享一个xilinx SDK开发的小技巧。当创建完成一个SDK工程之后,会发现新跳出来一个MSS的界面,如下图所示:


      从上图中可以看到,红色方框中有个Import Example,这个就是官方提供给我们的驱动,我们可以用鼠标点击这个Import Example,就比如今天要驱动的AXI_GPIO,点击之后如下图所示:

然后点击第一项的xgpio_example.c,点击之后如下表所示:

/***************************** Include Files *********************************/


#include "xparameters.h"

#include "xgpio.h"

#include "sleep.h"



/************************** Constant Definitions *****************************/


#define LED 0x01   /* Assumes bit 0 of GPIO is connected to an LED  */


/*

 * The following constants map to the XPAR parameters created in the

 * xparameters.h file. They are defined here such that a user can easily

 * change all the needed parameters in one place.

 */

#define GPIO_EXAMPLE_DEVICE_ID  XPAR_GPIO_0_DEVICE_ID


/*

 * The following constant is used to wait after an LED is turned on to make

 * sure that it is visible to the human eye.  This constant might need to be

 * tuned for faster or slower processor speeds.

 */

#define LED_DELAY     10000000


/*

 * The following constant is used to determine which channel of the GPIO is

 * used for the LED if there are 2 channels supported.

 */

#define LED_CHANNEL 1


/**************************** Type Definitions *******************************/



/***************** Macros (Inline Functions) Definitions *********************/


#ifdef PRE_2_00A_APPLICATION


/*

 * The following macros are provided to allow an application to compile that

 * uses an older version of the driver (pre 2.00a) which did not have a channel

 * parameter. Note that the channel parameter is fixed as channel 1.

 */

#define XGpio_SetDataDirection(InstancePtr, DirectionMask) \

        XGpio_SetDataDirection(InstancePtr, LED_CHANNEL, DirectionMask)


#define XGpio_DiscreteRead(InstancePtr) \

        XGpio_DiscreteRead(InstancePtr, LED_CHANNEL)


#define XGpio_DiscreteWrite(InstancePtr, Mask) \

        XGpio_DiscreteWrite(InstancePtr, LED_CHANNEL, Mask)


#define XGpio_DiscreteSet(InstancePtr, Mask) \

        XGpio_DiscreteSet(InstancePtr, LED_CHANNEL, Mask)


#endif


/************************** Function Prototypes ******************************/



/************************** Variable Definitions *****************************/


/*

 * The following are declared globally so they are zeroed and so they are

 * easily accessible from a debugger

 */


XGpio Gpio; /* The Instance of the GPIO Driver */


/*****************************************************************************/

/**

*

* The purpose of this function is to illustrate how to use the GPIO

* driver to turn on and off an LED.

*

* @param None

*

* @return XST_FAILURE to indicate that the GPIO Initialization had

* failed.

*

* @note This function will not return if the test is running.

*

******************************************************************************/

int main(void)

{

int Status;

volatile int Delay;


/* Initialize the GPIO driver */

Status = XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);

if (Status != XST_SUCCESS) {

return XST_FAILURE;

}


/* Set the direction for all signals as inputs except the LED output */

XGpio_SetDataDirection(&Gpio, LED_CHANNEL, ~LED);


/* Loop forever blinking the LED */


while (1) {

/* Set the LED to High */

XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, LED);


/* Wait a small amount of time so the LED is visible */

for (Delay = 0; Delay < LED_DELAY; Delay++);


/* Clear the LED bit */

XGpio_DiscreteClear(&Gpio, LED_CHANNEL, LED);


/* Wait a small amount of time so the LED is visible */

for (Delay = 0; Delay < LED_DELAY; Delay++);

}


return XST_SUCCESS;

}

       上表中的程序就是官方提供的IP的驱动函数,掌握了这个技巧,就不至于对一款刚设计的IP感到无从下手,本节的程序也是由上面的程序进行改动得来。

Step4:展开GPIO_Test,然后选中src,右单击选择New-Source file,创建新文件。

Step5:命名为main.c.

Step6:双击main.c,将以下程序拷贝进去:

/***************************** Include Files *********************************/


#include "xparameters.h"

#include "xgpio.h"

#include "xil_printf.h"

#include "sleep.h"

/************************** Constant Definitions *****************************/


/*

 * The following constants map to the XPAR parameters created in the

 * xparameters.h file. They are defined here such that a user can easily

 * change all the needed parameters in one place.

 */

#define GPIO_EXAMPLE_DEVICE_ID  XPAR_GPIO_0_DEVICE_ID



/*

 * The following constant is used to determine which channel of the GPIO is

 * used for the LED if there are 2 channels supported.

 */

#define LED_CHANNEL 1



/*

 * The following are declared globally so they are zeroed and so they are

 * easily accessible from a debugger

 */


XGpio Gpio; /* The Instance of the GPIO Driver */


/*****************************************************************************/

/**

*

* The purpose of this function is to illustrate how to use the GPIO

* driver to turn on and off an LED.

*

* @param None

*

* @return XST_FAILURE to indicate that the GPIO Initialization had

* failed.

*

* @note This function will not return if the test is running.

*

******************************************************************************/

int main(void)

{

int Status;

int i;


/* Initialize the GPIO driver */

Status = XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);

if (Status != XST_SUCCESS) {

return XST_FAILURE;

}


/* Set the direction for all signals as inputs except the LED output */

XGpio_SetDataDirection(&Gpio, LED_CHANNEL, 0);


/* Loop forever blinking the LED */


while (1) {

for(i=0; i< 4; i++){

XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, 0x01 <<i);

usleep(10000);

}

}


return XST_SUCCESS;

}


Step7:选中SDK工程文件,右单击选择Debug as-Debug configuration。

Step8:在弹出来的新窗口中,双击下图圈出部分,然后勾选箭头所示参数

Step9:单击APPly,然后单击Debug(进行这一步之前,先给开发板上电)。


2.4 程序分析

       本章的程序可以看出都是由官方提供的驱动程序修改而来,本章的程序也比较简单,首先看到XGpio_Initialize这个函数,将鼠标悬停在这个函数的上方,然后按F3或者右单击选择Open Declaration,如下图所示:

       系统将跟踪到这个函数的原函数,在原函数中,可以了解到很多的信息,比如函数的功能,参数的意思,返回值的意思等等,只要是xilinx官方提供的驱动函数,都会有详细的函数头,如下图所示:

         从上面的函数头中就可以得知,此函数是从给定的DeviceID中对Gpio的实例结构进行初始化。第一个参数为GPio的实例结构,第二个是设备ID。

         然后看到第二个函数XGpio_SetDataDirection,用同样的方法查看其原函数,如下图所示:

       可以看到这是一个用于设置GPIO是输出还是输入的功能函数,第一个参数是实例,第二个是选择GPIO的通道,第三个是输出的方向,当为0时为输出,1时为输入,所以本章程序将其设置为了0,如下图所示:

接下来看到最后一个函数,直接看其源函数:

       从上图可知,这个函数用于将数据写入到指定GPIO通道的寄存器中,也就相当于向GPIO赋值。这个函数主要关注第三个参数,这个参数就是我们要写入到GPIO的数据。然后再来看到本章的程序,意思就非常的清楚了,这里用了一个for语句,每次写入的数据从0x01依次四次移位操作,这样子就是一个流水灯的效果。

       在上面程序中还用到了一个us级延时语句usleep,以此让LED的闪烁不要太快,让我们能观察到流水效果。

2.5 本章小结

       本章为大家介绍了一种使用GPIO实现流水灯的方法,通过这种方法,重点需要掌握的是MicroBlaze的设计流程和本章节提到的查看官方驱动程序的方法,这在以后的设计中是很重要的一项技能。


路过

雷人

握手

鲜花

鸡蛋

最新评论

本文作者
2019-11-6 10:44
  • 1
    粉丝
  • 2664
    阅读
  • 0
    回复

关注uisrc网络

扫描关注,了解最新资讯

电话:0519-80699907
EMAIL:270682667@qq.com
地址:常州溧阳市天目云谷3号楼北楼
热门评论
排行榜