创建工程与ZYNQ配置的部分不在此处赘述,如有不会者请查看我以前的文章。
创建好工程后新建IP核,选择AXI外设。
修改IP核的名称与存放地址,选择Lite,Slave模式,由于要使用4个LED,所以接口数量选择4。
创建好后,把IP核添加到工程中,右键单击添加的IP核选择Edit in IP Packager,修改IP核。点击确定后会弹出一个Vivado界面出来,选择顶层代码进行修改。
顶层部分一般是用来设置外接接口的,我们这里需要使用到LED,所以我们在这里添加4个外接LED接口,LED为输出外设所以端口模式为输出,并把LED端口引到底层部分。
然后打开底层代码,在接口处添加led接口,在最后添加LED的逻辑代码。创建IP的时候设置了4个接口,这里就有4个slv_reg,他们是PS通过AXI总线与PL通信的接口,用于接收PS的数据,slv_reg是32位的总线,这里只需要用到一位控制LED。
修改完保存后,点击Package IP窗口,选择前面没有打勾的界面,点击箭头所指的地方,把修改的内容跟新到IP核内。选择Identification选项,修改IP核的版本,以区分后面添加的IP核是否是最新的内容。
最后选择Review and Package界面,点击Re-Package IP打包IP核。打包完成后会自动关闭界面。
在工程里添加刚刚修改的IP核,注意IP核的版本是否正确,然后自动连线并且把LED端口引出。生成HDL文件,添加引脚约束文件,生成比特流。这些步骤不会可以去看我以前的文章。
在等待生成比特流后时可以打开SDK,编写PS端的代码,打开SDK后新建 helloworld工程,然后对代码进行修改,代码如下。
#include <stdio.h>
#include "platform.h"
//添加GPIO相关函数库
#include "xgpiops.h"
#include "xgpiops_hw.h"
//定义MIOled的引脚
#define led1 40
#define led2 41
#define led3 42
#define led4 43
//PL端的AXI总线通讯传输函数,addr对应slv_reg0-3,data为传输的内容
void led( unsigned int addr ,unsigned int data )
{
*(volatile unsigned int * ) (0x80000000 + (4*addr)) = data ;
}
//MIO led的初始化函数
XGpioPs XGpio;
XGpioPs_Config *XGpioPs_C;
void led_init()
{
XGpioPs_C = XGpioPs_LookupConfig(XPAR_XGPIOPS_0_DEVICE_ID);
XGpioPs_CfgInitialize(&XGpio,XGpioPs_C,XGpioPs_C->BaseAddr);
XGpioPs_SetOutputEnablePin(&XGpio,led1 ,1);
XGpioPs_SetDirectionPin(&XGpio,led1 ,1);
XGpioPs_SetOutputEnablePin(&XGpio,led2 ,1);
XGpioPs_SetDirectionPin(&XGpio,led2 ,1);
XGpioPs_SetOutputEnablePin(&XGpio,led3 ,1);
XGpioPs_SetDirectionPin(&XGpio,led3 ,1);
XGpioPs_SetOutputEnablePin(&XGpio,led4 ,1);
XGpioPs_SetDirectionPin(&XGpio,led4 ,1);
}
//led控制函数
void led_wire(int i,int j)
{
XGpioPs_WritePin(&XGpio ,i,(j!=0));
}
int main()
{
init_platform();
led_init();
int i=0;
while(1)
{
i++;
led(0,(0x1 & i)? 1 : 0);
led(1,(0x2 & i)? 1 : 0);
led(2,(0x4 & i)? 1 : 0);
led(3,(0x8 & i)? 1 : 0);
led_wire(led1,(0x1 & i)? 1 : 0);
led_wire(led2,(0x2 & i)? 1 : 0);
led_wire(led3,(0x4 & i)? 1 : 0);
led_wire(led4,(0x8 & i)? 1 : 0);
sleep(1);
}
cleanup_platform();
return 0;
}
代码烧写进去后的效果图如下,烧写方式可查询我之前的文章