2. 基于PS调试流水灯
这一部分主要分为两个部分:
- PS通过EMIO控制PL端GPIO
- PS直接控制PS端GPIO
基于PS调试流水灯
该部分控制7个LED灯组成流水灯,其中A5、A6、A7、B8、T16是PL端的GPIO口;C19、G17是PS端的GPIO口。
其中,由A5、A6、A7、B8、C19组成一组流水灯;由T16、G17组成另外一组。
1. 创建Block
1. 创建一个ZYNQ Processing System
主要更改两个部分的内容:
- DDR Configuration 此处按照板卡的类型选择自己DDR的型号。
[参考自SoC第一讲——Vivado的Block Design 的使用] - MIO Configuration 此处由于需要使用MIO口,故而需要使能GPIO MIO端口
2. 创建一个AXI GPIO
这里为了实验需要允许了双通道的GPIO,正常一个GPIO通道即可完成5路GPIO口的控制。
然后让Vivado自动连接填补剩余模块即可。具体完成后就是如下的样子。
2. 约束文件编写
led.xdc
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_rtl_0_tri_io[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_rtl_0_tri_io[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_rtl_0_tri_io[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {gpio_rtl_0_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports gpio_rtl_1_tri_io]
set_property PACKAGE_PIN B8 [get_ports {gpio_rtl_0_tri_io[3]}]
set_property PACKAGE_PIN A6 [get_ports {gpio_rtl_0_tri_io[2]}]
set_property PACKAGE_PIN A7 [get_ports {gpio_rtl_0_tri_io[1]}]
set_property PACKAGE_PIN A5 [get_ports {gpio_rtl_0_tri_io[0]}]
set_property PACKAGE_PIN T16 [get_ports gpio_rtl_1_tri_io]
之后生成BitStream后导出硬件平台信息,由于这部分需要使用EMIO,需要包含bitstream库,之后可以征正常开始编写PS部分程序。
3. PS程序编写
通过Launch SDK打开Xilinx SDK。创建一个空的应用项目。由于没有使用串口,这一部分不可以使用HelloWorld模板。
先引入一部分必须引入的模块
#include "parameters.h" // 常数模块
#include "sleep.h" // 延时模块
1. PL部分GPIO口的控制
这一部分需要引入xgpio模块
#include "xgpio.h"
先实验一个基于PL部分的流水灯程序,这一部分主要是测试使用两个通道的GPIO口会有什么问题。测试下来,并没有什么问题。
用到的函数有
int XGpio_Initialize(
XGpio* InstancePtr,
u16 DeviceId
); //初始化
void XGpio_SetDataDirection(
XGpio *InstancePtr,
unsigned Channel,
u32 DirectionMask
); //设置GPIO口的读写方向
void XGpio_DiscreteWrite(
XGpio * InstancePtr,
unsigned Channel,
u32 Data
); //设置GPIO口的值
int usleep(
unsigned long useconds
); //设置延时时间
这些函数在官方文档以及官方例程里面给的比较详细,这里就无需说明。
针对PL口的流水灯的程序如下:
#include "xparameters.h"
#include "sleep.h"
#include "xgpio.h"
#define GPIO_DEVICE_ID XPAR_GPIO_0_DEVICE_ID
#define DELAY_LED 500000
#define LED_CHANNEL_1 1
#define LED_CHANNEL_2 2
#define LED0 0x01
#define LED1 0x02
#define LED2 0x04
#define LED3 0x08
#define LED4 0x01
XGpio gpio;
int main(){
int Status;
Status = XGpio_Initialize(&gpio, GPIO_DEVICE_ID);
if(Status != XST_SUCCESS){
return XST_FAILURE;
}
XGpio_SetDataDirection(&gpio, LED_CHANNEL_1, 0x00);
XGpio_SetDataDirection(&gpio, LED_CHANNEL_2, 0x00);
while(1){
XGpio_DiscreteWrite(&gpio, LED_CHANNEL_1, (~LED0) | LED1 | LED2 | LED3);
XGpio_DiscreteWrite(&gpio, LED_CHANNEL_2, LED4);
usleep(DELAY_LED);
XGpio_DiscreteWrite(&gpio, LED_CHANNEL_1, LED0 | (~LED1) | LED2 | LED3);
XGpio_DiscreteWrite(&gpio, LED_CHANNEL_2, LED4);
usleep(DELAY_LED);
XGpio_DiscreteWrite(&gpio, LED_CHANNEL_1, LED0 | LED1 | (~LED2) | LED3);
XGpio_DiscreteWrite(&gpio, LED_CHANNEL_2, LED4);
usleep(DELAY_LED);
XGpio_DiscreteWrite(&gpio, LED_CHANNEL_1, LED0 | LED1 | LED2 | (~LED3));
XGpio_DiscreteWrite(&gpio, LED_CHANNEL_2, LED4);
usleep(DELAY_LED);
XGpio_DiscreteWrite(&gpio, LED_CHANNEL_1