基于Xilinx N4板和MicroBlaze核的走马管

建工程

先用ise套餐里面的Xilinx Platform Studio(XPS)的最小系统生成器(Basic System Builder(BSB))创建一个XPS工程(Local Mem32Kb)。

在BUS Interfaces里面可以看到模块的连接,在Ports里面可以看到模块的IP端口连接。Adress可以看每个外设模块的地址空间。

产生网表,产生硬件比特流文件,导出硬件设计到SDK中,创建板级支持包,BSP OS选择StandAlone,创建C语言工程(选择已有的BSP)

 

错误1:生成比特流文件时报错说我没加分号,可是我确实是加了分号的:

NET"CLK" TNM_NET = sys_clk_pin;

TIMESPECTS_sys_clk_pin = PERIOD sys_clk_pin 100000 kHz;

 

NET"CLK"     LOC ="E3"  |= IOSTANDARD ="LVCOMS33";

NET"RESET"      LOC = "E16" |= IOSTANDARD ="LVCOMS33";

NET"RX"      LOC ="C4"  |= IOSTANDARD ="LVCOMS33";

NET"TX"      LOC ="D4"  |= IOSTANDARD = "LVCOMS33";

不能解决的方法:关闭软件重新打开,删掉重新打,新建工程

可以解决的办法:把第二个等号删掉

由此可以推知,那个“|”的意思不是“或”,而是表面,它的后面是解释说明性的语句,即电压为3.3V

更改后如下:

NET"CLK" TNM_NET = sys_clk_pin;

TIMESPECTS_sys_clk_pin = PERIOD sys_clk_pin 100000 kHz;

 

NET"CLK"     LOC ="E3"  | IOSTANDARD = "LVCOMS33";

NET"RESET"      LOC = "E16" | IOSTANDARD ="LVCOMS33";

NET"RX"      LOC ="C4"  | IOSTANDARD = "LVCOMS33";

NET"TX"      LOC = "D4"  | IOSTANDARD = "LVCOMS33";

 

错误2

能解决的办法:把COMS改为CMOS。

更改之后的代码如下:

NET "CLK" TNM_NET = sys_clk_pin;

TIMESPEC TS_sys_clk_pin = PERIOD sys_clk_pin 100000 kHz;

 

NET "CLK"     LOC= "E3"  | IOSTANDARD ="LVCMOS33";

NET "RESET"      LOC ="E16" | IOSTANDARD = "LVCMOS33";

NET "RX"      LOC= "C4"  | IOSTANDARD ="LVCMOS33";

NET "TX"      LOC= "D4"  | IOSTANDARD ="LVCMOS33";

OK终于不报错了。

一:数码管滚动显示

1.  硬件连接

1).UART:RX接C4,TX接D4引脚。

2).GPIO:书的P89页有详细的板子上开关/LED/按键/数码管的引脚连接图

3).中断:a.添加IP核模块,b.将外设(GPIO,DebugMode)挂到中断控制器上,c.把中断控制器连接到MicroBlaze的中断上

4).定时器:把定时器的中断连接到中断控制器上

5).UCF

 

NET"CLK" TNM_NET = sys_clk_pin;

TIMESPECTS_sys_clk_pin = PERIOD sys_clk_pin 100000 kHz;

 

NET"CLK"     LOC ="E3"  | IOSTANDARD ="LVCMOS33";

NET"RESET"      LOC = "E16" | IOSTANDARD ="LVCMOS33";

NET"RX"      LOC ="C4"  | IOSTANDARD ="LVCMOS33";

NET"TX"      LOC ="D4"  | IOSTANDARD ="LVCMOS33";

 

NET"Bits<0>" LOC = "M1" | IOSTANDARD ="LVCMOS33";

NET"Bits<1>" LOC = "L1" | IOSTANDARD ="LVCMOS33";

NET"Bits<2>" LOC = "N4" | IOSTANDARD ="LVCMOS33";

NET"Bits<3>" LOC = "N2" | IOSTANDARD ="LVCMOS33";

NET"Bits<4>" LOC = "N5" | IOSTANDARD ="LVCMOS33";

NET"Bits<5>" LOC = "M3" | IOSTANDARD ="LVCMOS33";

NET"Bits<6>" LOC = "M6" | IOSTANDARD ="LVCMOS33";

NET"Bits<7>" LOC = "N6" | IOSTANDARD ="LVCMOS33";#wei gaodizhi

 

NET"P<0>" LOC = "L3" | IOSTANDARD ="LVCMOS33"; #a0duan didizhi

NET"P<1>" LOC = "N1" | IOSTANDARD ="LVCMOS33"; #b0

NET"P<2>" LOC = "L5" | IOSTANDARD ="LVCMOS33"; #c0

NET"P<3>" LOC = "L4" | IOSTANDARD ="LVCMOS33"; #d0

NET"P<4>" LOC = "K3" | IOSTANDARD ="LVCMOS33"; #e1

NET"P<5>" LOC = "M2" | IOSTANDARD ="LVCMOS33"; #f1

NET"P<6>" LOC = "L6" | IOSTANDARD ="LVCMOS33"; #g0

NET"P<7>" LOC = "M4" | IOSTANDARD = "LVCMOS33";#dp1  0xb0

2.  软件编写

用SDK进行应用程序的编写

先添加头文件

#include <stdio.h>

#include "platform.h"

 

#include "xparameters.h"(硬件端口的定义参数)

#include "xtmrctr.h"

#include "xintc.h"

#include "xil_exception.h"

#include "xil_io.h"

声明实例

XIntcInterruptController;

XTmrCtrTimerCounterInst;

定义函数

void print(char*str);

void Initialize(void);

1).初始化

a.

①初始化中断控制器:Xintc_Initialize(&InterrupptController , INTC_DEVICE_ID)

②初始化定时器:XTmrCtr_Initialize(&TimerCounterInst, XPAR_TMR_0_DEVICE_ID)。(x代表Xilinx,par代表parameter)

b.配置中断:配置定时器:

①配置定时器产生中断:XTmrCtr_SetHandler(&TimerCounterInst, TimerCounterHandler , &TimerCounterInst)

②配置定时器模式:XtmrCtr_SetOptions(&TimeCounterInst, TIMER_CNTR_0,XTC_INT_MODE_OPTION|XTC_AUTO_RELOAD_OPTION|XTC_DOWN_COUNT_OPTION)

③重装载值XTmrCtr_Reset_Value(&TimerCounterInst , TIMER_CNTR_0,RESET_VALUE)

④对中断控制器进行中断源使能Xintc_Enable(&InterrupptController , TMRCTR_Interruppt_ID)

⑤注册中断服务函数XIntc_Connect (Xintc*, u8, XinterrupteHandler, void*)

⑥允许处理器中断microblaze_enable_interrupts(void);

⑦注册处理器中断控制器处理函数microblaze_regesister_handler ((XInterruptHandller)Xintc_InterruptHandler,(void*)&intCtrl)

⑧启动中断控制器Xintc_Start(&intCtrl , XIN_REAL_MODE)

⑨启动定时器XTmrCtr_Start(&TimerCounterInst,TIMER_CNTR_0)

2).死循环

3).中断处理函数

VoidTimerCounterHandler(void * , u8 TmrCtrNumber)

3.  下载调试

错误1:在生成模板Hello Word程序的时候,进度条一直卡在73%

能解决的办法:不管它,继续编程

错误2:Program进度条在100%的时候,卡死

能解决的办法:在XilinX Tools的program FPGA的选项里,把soft ware configuration 的microblaze0的内容,由boot loop改为SDK的导出elf文件。

错误3:找不到xtmrcrt.h头文件,发现microblaze核里面根本没有

能解决的办法

不能解决的办法:认为是硬件问题,重新搭建定时器和中断控制器

能解决的办法:在SDK里面删除整个BSP(从磁盘删除),然后自己新建一个新的BSP,即可。其实是自动导出的BSP包会缺失头文件。

错误4:从本word粘贴函数进去,并且检查过跟书上的函数一模一样,但是却报warning,说函数未被声明。

能解决的办法:从库文件里赋值粘贴函数名字过去就好了。

错误5:烧写进去之后,数码管不会亮

能解决的办法:换成GPIO的API函数,首先添加Xgpio.h的库文件,再定义GPIO的实例XGpio ShuMaGuan;然后在初始化函数里添加    XGpio_Initialize (&ShuMaGuan, XPAR_GPIO_0_DEVICE_ID ) ;接着配置1,2通道为输出模式: XGpio_SetDataDirection(&ShuMaGuan,1,0x00); XGpio_SetDataDirection(&ShuMaGuan,2,0x00);

OK终于成功了

不能解决的办法:①DeBug:在文件栏的elf文件上单击右键,选择Debug as-> Lunch on Hardware;按F8运行。②改成    Xil_Out16 ( XPAR_GPIO_0_BASEADDR, 0x0000);试图全部输出低电平。

错误6:数码管滚动不正常

不能解决的办法:把pos改为U8,改为int

能解决的办法:把pos改为u32

错误7:数码管不能按照0xb0那样显示3,总是显示全8

能解决的办法:在main函数里面注释掉Xil_Out16(XPAR_GPIO_0_BASEADDR,0x00);。从这个地方也可以看出来,前面尝试过的直接输出的办法是可行的,只是存在一些仍然需要探索的bug

所有代码如下:

 

#include<stdio.h>

#include"platform.h"

 

#include"xparameters.h"

#include"xtmrctr.h"

#include"xintc.h"

#include"xil_exception.h"

#include"xil_io.h"

#include"xgpio.h"

 

XIntcInterruptController;

XTmrCtrTimerCounterInst;

XGpioShuMaGuan;

u32pos=0xff7f;//1111 1111 0111 1111

inti=0;

 

voidprint(char *str);

voidInitialize(void);

voidTimerCounterHandler(void* CallBackRef , u8 TmrCtrNumber);

 

intmain()

{

    init_platform();

    print("Start\n\r");

 

    Initialize();

    //Xil_Out16(XPAR_GPIO_0_BASEADDR, 0x00);

    return 0;

}

voidInitialize()

{

    XIntc_Initialize(&InterruptController ,XPAR_INTC_0_DEVICE_ID);//INTC_DEVICE_ID

    XTmrCtr_Initialize(&TimerCounterInst,XPAR_TMRCTR_0_DEVICE_ID);//XPAR_TMRCTR_0_DEVICE_ID

 

   XTmrCtr_SetHandler(&TimerCounterInst,TimerCounterHandler , &TimerCounterInst);

    XTmrCtr_SetOptions(&TimerCounterInst,0,XTC_INT_MODE_OPTION|XTC_AUTO_RELOAD_OPTION| XTC_DOWN_COUNT_OPTION);

    XTmrCtr_SetResetValue(&TimerCounterInst, 0, 0x5F5E100);

 

    XIntc_Enable(&InterruptController ,XPAR_INTC_0_TMRCTR_0_VEC_ID);//TMRCTR_Interruppt_ID

    XIntc_Connect(&InterruptController,XPAR_INTC_0_TMRCTR_0_VEC_ID,(XInterruptHandler)XTmrCtr_InterruptHandler,(void*)&TimerCounterInst);

 

    microblaze_enable_interrupts();

    microblaze_register_handler((XInterruptHandler)XIntc_InterruptHandler,&InterruptController);

 

    XIntc_Start(&InterruptController ,XIN_REAL_MODE);

    XTmrCtr_Start(&TimerCounterInst,0);

 

    XGpio_Initialize(&ShuMaGuan,XPAR_GPIO_0_DEVICE_ID);

    XGpio_SetDataDirection(&ShuMaGuan,1,0x00);

    XGpio_SetDataDirection(&ShuMaGuan,2,0x00);

    XGpio_DiscreteWrite(&ShuMaGuan, 1,  0xffb0);//Chnnel1连接到了数码管的段

}

voidTimerCounterHandler(void* CallBackRef , u8 TmrCtrNumber)

{

    //XGpio_DiscreteWrite(&ShuMaGuan,1,  0xffb0);//Chnnel1连接到了数码管的段

    //Xil_Out8(XPAR_axi_gpio_0_BASEADDR ,  0xff);//NUM 3

    //Xil_Out8(XPAR_GPIO_0_BASEADDR+0X8 , 0xff);

    XGpio_DiscreteWrite(&ShuMaGuan, 2,pos);//Chnnel2连接到了Bits

    pos=pos>>1;

 

    i++;

    if(i==8){

       i=0;

       pos=0xff7f;}

     print("1\n\r");

}

基于Xilinx N4板和MicroBlaze核的走马管