实现功能:使用 MicroBlaze软核,配置GPIO用拨码开关控制LED灯
Vivado版本:2018.3
目录
引言
在“ MicroBlaze软核开发(一):Hello World ”中通过串口打印 Hello World 的例子成功跑通了 Microblaze 软核,对相关设计步骤作了一个介绍。本文将基于上一节的工程,继续介绍如何使用 Microblaze 软核,配置GPIO,用4个拨码开关对应控制4个LED灯。
vivado部分:
一、配置GPIO
(1)点击添加按钮,搜索GPIO,双击 AXI GPIO 添加IP ,如图所示
(2)双击GPIO模块进行配置:因为要实现4个拨码开关对应控制4个LED灯,所以LED为4位输出,拨码开关为4位输入;又因为后续输入输出需要分开设置通道,故将GPIO1通道作为LED灯的4位输出,将GPIO2通道作为拨码快关的4位输入。
(3)点击“运行自动连接”,勾选全部点击OK
(4)点击“自动布局”,最后得到电路如下,右下角为添加的gpio部分,这里把 GPIO 模块的通道1引脚命名为“gpio_led”,把通道2引脚命名为“gpio_switch” (后面会用到,注意!)
二、生成HDL文件编译
这一部分和 “ MicroBlaze软核开发(一):Hello World ” 中相同,不再赘述
(1)到src栏右键设计块,生成HDL包装文件
(2)依次进行:Run Synthesis 综合、Run implementation 部署
(3)再配置管脚:需要配置的管脚如图所示,根据开发板情况自行配置
(4)最后 Generate Bitstream 生成比特流文件
SDK部分:
一、导出硬件启动SDK
这一部分和 “ MicroBlaze软核开发(一):Hello World ” 中相同,不再赘述
(1)File -> Export -> Export Hardware 导出硬件: 注意勾选“Include bitstream”再导出
(2)File -> Launch SDK 启动SDK:保持默认点击OK。
二、新建应用程序工程
(1)因为是基于(一)的工程进行,会发现已有hello的工程,这里打开该工程 bsp 文件夹(Board Support Package文件夹,封装了特定硬件平台如开发板、FPGA等所需的软件支持),再打开 system.mss 文件,里面会根据 Vivado 内的软核设计提供驱动程序 (Vivado给添加了uart和gpio,可以发现它就提供了uart 和 gpio 的驱动程序的工程模板),选择axi_gpio 的工程创建。
(2)选择axi_gpio 的工程模板,他一共提供4个模板,这里选最基本的第一个即可。
(3)打开生成的模板工程的.C文件,可以看到模板功能是使用 AXI GPIO 驱动 LED 灯,
其中LED灯为GPIO通道1的第0位
(4)先分析运行模板的代码:(SDK中按住Ctrl再点击函数可以跳转查看函数定义,直接烧录并运行该模板程序的现象是LED的第0位循环亮灭)
/***************************** Include Files 包含头文件 *********************************/
#include "xparameters.h"
#include "xgpio.h"
#include "xil_printf.h"
/************************** Constant Definitions 常量定义 *****************************/
#define LED 0x01 //LED的gpio的方向:第0位为1
#define GPIO_EXAMPLE_DEVICE_ID XPAR_GPIO_0_DEVICE_ID //获取的GPIO设备ID
#define LED_DELAY 10000000 //用于延时计数
#define LED_CHANNEL 1 //LED的gpio通道设为通道1
/************************** Variable Definitions 变量定义 ****************************/
XGpio Gpio; //实例化XGpio名为GPIO
/********************************** Main 主函数 *************************************/
int main(void)
{
int Status;
volatile int Delay;
/**** GPIO初始化 ****/
Status = XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("Gpio Initialization Failed\r\n");
return XST_FAILURE;
}
XGpio_SetDataDirection(&Gpio, LED_CHANNEL, ~LED); //设置LED的gpio方向,这里取反则仅第0位0,即只有第0位为输出
/**** LED循环闪烁 ****/
while (1) {
XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, LED);
for (Delay = 0; Delay < LED_DELAY; Delay++); //延时
XGpio_DiscreteClear(&Gpio, LED_CHANNEL, LED);
for (Delay = 0; Delay < LED_DELAY; Delay++); //延时
}
return XST_SUCCESS;
}
三、编写程序代码
因为要实现4个拨码开关对应控制4个LED灯,所以代码需要进行修改:需要添加拨码开关GPIO的通道2,并将LED的GPIO设为通道1、方向设为输出;将switch的GPIO设为通道2、方向设为输入:
/**************************** Include Files 包含头文件 ********************************/
#include "xparameters.h"
#include "xgpio.h"
#include "xil_printf.h"
/************************** Constant Definitions 常量定义 ****************************/
#define LED 0x00 //LED的gpio的方向:低四位全0表示,即全为输出
#define SW 0x0f //switch的gpio的方向:低四位全1表示,即全为输出
#define GPIO_EXAMPLE_DEVICE_ID XPAR_GPIO_0_DEVICE_ID //获取GPIO设备ID(如果有两个GPIO模块需要再加一个ID,这里只有一个XPAR_GPIO_0模块)
#define LED_CHANNEL 1 //LED的gpio通道为通道1
#define SW_CHANNEL 2 //switch的gpio通道为通道2
/************************** Variable Definitions 变量定义 ****************************/
XGpio Gpio; //实例化XGpio名为GPIO
u32 data; //定义u32类型变量data
/********************************** Main 主函数 *************************************/
int main(void)
{
/*** GPIO初始化 ***/
int Status;
Status = XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("Gpio Initialization Failed\r\n");
return XST_FAILURE;
}
XGpio_SetDataDirection(&Gpio, LED_CHANNEL, LED); //设置LED通道的方向为输出
XGpio_SetDataDirection(&Gpio, SW_CHANNEL, SW); //设置Switch通道的方向为输入
while (1) {
data = XGpio_DiscreteRead(&Gpio, SW_CHANNEL); //将switch的GPIO输入数据读取到data
XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, data); //data数据输出给led的GPIO
}
return XST_SUCCESS;
}
(6)修改结束进行烧录,再运行该程序。效果为4个拨码开关可以对应控制4个LED灯,到此GPIO的配置与简单使用介绍结束。