建工程
先用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");
}