这是本人第一次写博客,我的毕设在用FPGA去读取LSM303D传感器的中的三轴的磁场强度数据,这也是我第一次用zynq-7010板子,第一次接触Vivado,我用了将近两个月的时间摸索,中间经历了很多失败的尝试,还好最近有了突破,因为目前网上基本没有关于FPGA读取LSM303D的资料,所以这也是我写这篇博文的出发点。
废话不多说,让我来一步步介绍如何通过I2C总线完成对LSM303D传感器数据的读取。本篇博文所用到的软件是Vivado 2014.4和Xilinx SDK 2014.4,用到的开发板是Zybo-7010.
首先,我们打开Vivado软件(我用的是2014.4版本),主界面如图1所示。
点击“Create New Project”,在弹出的新建工程向导中点击“Next”,弹出设置工程名和工程路径的对话框,如图2所示。在“Project name”项中输入工程名LSM303D,在“Project location”项中输入或选择工程的路径,而“Create project subdirectory”如果勾选,则会在所选的工程路径中创建一个名字与工程名一样的用于存放工程的新文件,否则直接在所选工程路径下创建工程。
点击“Next”,弹出选择工程类型的对话框,如图3所示。选择RTL类型,请注意RTL类型下有“Do not specify sources at this time”选项,意思是在新建工程过程中不指定源文件。
点击“Next”,弹出选择器件型号的对话框,我们在“Search”栏里输入xc7z010clg400,选择xc7z010clg400-1,如图4所示。
点击“Next”,在弹出的对话框中点击“Finish”完成工程的创建。创建工程后的主界面如图5所示,其中左侧面板是设计流程的管理,从源文件的添加到综合、仿真、布局布线、到最后板级调试,都可以通过点击相应的按键来完成;中间上面的面板是工程文件的管理;右侧面板是工程信息总结,包括工程的基本信息、综合实现所消耗的资源信息等;底部面板是各种信息的输出,包括编译信息、报告等。
在主界面左侧的“IP Integrator”下点击“Create Block Design”,在弹出的“Design name”对话框中输入LSM303D,如图6所示。
点击“OK”,出现如图7所示界面,此时的Block Design里还没有任何的IP核,因此我们要添加IP来完成我们的Block Design。
点击右侧Diagram中高亮的“Add IP”来添加IP核,首先我们在输入框内输入ZYNQ,在筛选出的结果下选择第一个“ZYNQ7 Processing System”,Diagram中便会出现ZYNQ7 Processing System IP,如图8、图9所示。
点击“Run Block Automation”,在弹出的对话框中点击“OK”,系统会自动连线,如图10所示。
接着双击ZYNQ7 Processing System IP进行配置,在弹出的对话框中点击上方的“Import XPS Settings”,导入ZYBO_zynq_def.xml 文件(可自行百度下载),如图11所示。
导入完成后如图12所示。
点击“DDR Configuration”,在“DDR Controller Configuration”中对“Memory Part”选择“MT41K256M16 HA-125”,如图13所示。
配置完成后点击“OK”,退出对ZYNQ7 Proccessing System IP的配置。系统会如图14所示。
接着,我们在Diagram中空白处右键然后点击“Add IP”,在“Search”栏中搜索IIC,在搜索结果中点击“AXI IIC”,结果如图15所示。
点击“Run Connection Automation”,在弹出的对话框中给“All Automation”选项打钩,然后点击“OK”,系统便会将两个IP自动连线,系统就设计完成了,结果如图16所示。
我们可以双击AXI IIC IP查看内部配置,如图17所示,我们可以知道建立的IIC总线的SCL时钟是100KHz,也就是标准传输模式,地址模式使用的是7位地址寻址模式。
接着我们点击中间的“Source”,可以在“Design Source”文件夹下看到“LSM303D”的Block Design工程,此时还没有生成v文件,我们需要右键“LSM303D”,点击“Generate Output Products”,在弹出的对话框中点击“Generate”,如图18所示。
再次右键“LSM303D”,点击“Create HDL Wrapper”,在弹出的对话框中选择“Let Vivado manage wrapper and auto-update”然后点击“OK”,便会自动生成v文件,结果如图19所示。
然后在左侧的“Flow Navigator”下的“Implementation”中点击“Run Implementation”,在弹出的对话框中点击“OK”,然后点击“Save”,系统就开始按流程跑综合、跑实例了,现在我们能做的就是等它跑完。跑完且不报错会弹出如图20所示对话框,点击“Open Implementation Design”开始进行管脚约束。
在打开的界面中,我们点击下方的“I/O Ports”,对iic_rtl_scl_io和iic_rtl_sda_io进行管脚约束配置,“I/O Std” 选择LVCMOS33, iic_rtl_scl_io管脚选择H15、iic_rtl_sda_io 管脚选择J15,两者的“Pull Type”均选择PULLUP,如图21所示。
然后我们按“Ctrl + S”进行文件保存,在弹出对话框中点击“OK”之后,在“File name”中输入LSM303D_Constraints后点击“OK”,便生成了约束文件,如图22所示。
然后在左侧的“Flow Navigator”下的“Program and debug”中点击“Generate Bitstream”,在弹出的对话框中点击“Yes”系统便开始生成bit文件,这时我们开始等待系统完成bit文件的生成。完成且没有报错后,在弹出的对话框中点击“OK”,接着我们点击左上角的“File”,选择“Export”,点击“Export Hardware”,在弹出的对话框中选中“Include bitstream”后,点击“OK”,如图23所示。
接着再次点击“File”,选择“Launch SDK”,点击“OK”,将自动打开SDK软件。如图24所示。
进入SDK后,点击左上角的“File”,选择“New”,点击“Application Project”,在弹出的对话框的“Project name”中输入LSM303D,如图25所示,然后点击“Next”,选择“Hello World”模板,如图26所示,点击“Finish”完成工程建立。
在左侧LSM303D文件夹下打开“src”文件夹,右键“Rename”helloworld.c文件的文件名,修改成main.c,结果如图27所示。
然后我们将main.c中的代码修改成如下代码:
#include
#include
#include "platform.h"
#include
#include
#include
#define BaseAddr 0x41600000
#define Slaveaddress 0x1E
/*
* ------------------------------------------------
* Slave Registers Configuration:
OUT_X_L_M_Reg = 0x08
OUT_Y_L_M_Reg = 0x0A
OUT_Z_L_M_Reg = 0x0C
CTRL7_Reg = 0x26 //(Data: 0x00) => Continuious Data
**Other registers are default**
* ------------------------------------------------
*/
#define OUT_X_L_M_Reg 0x08
#define OUT_Y_L_M_Reg 0x0A
#define OUT_Z_L_M_Reg 0x0C
#define CTRL7_Reg 0x26
int t;
int i;
u8 H1,L1;
s16 mdata;
float mdatax,mdatay,mdataz;
void LSM303D_Config(u32 BaseAddress,u8 Slvaddr, u8 Address, u8 Data);
u8 Read(u32 BaseAddress, u8 Slvaddr,u8 Address);
int main()
{
init_platform();
printf("Hello World\n\r");
LSM303D_Config( BaseAddr,Slaveaddress, CTRL7_Reg, 0x00);//Continuous Conversion Mode.
while(1)
{
printf("Magnetic Data: \r\n");
//Read X-axis Magnetic Data.
L1 = Read( BaseAddr,Slaveaddress, OUT_X_L_M_Reg);
H1 = Read( BaseAddr,Slaveaddress, OUT_X_L_M_Reg + 0x01);
mdata = (H1 << 8) + L1;
mdatax = mdata * 0.16;
printf("X_M= %f \r ",mdatax );
//Read Y-axis Magnetic Data.
L1 = Read( BaseAddr,Slaveaddress, OUT_Y_L_M_Reg);
H1 = Read( BaseAddr,Slaveaddress, OUT_Y_L_M_Reg + 0x01);
mdata = (H1 << 8) + L1;
mdatay = mdata *0.16;
printf("Y_M= %f \r ",mdatay );
//Read Z-axis Magnetic Data.
L1 = Read( BaseAddr,Slaveaddress, OUT_Z_L_M_Reg);
H1 = Read( BaseAddr,Slaveaddress, OUT_Z_L_M_Reg + 0x01);
mdata = (H1 << 8) + L1;
mdataz = mdata * 0.16;
printf("Z_M= %f \r ",mdataz );
printf("\r\n");
for(t=0;t<50000000;t++);//Delay
}
cleanup_platform();
return 0;
}
void LSM303D_Config(u32 BaseAddress, u8 Slvaddr, u8 Address, u8 Data)
{
unsigned Result;
u8 A[2] = {Address,Data};
u8 *Ptr = A;
Result = XIic_Send(BaseAddress, Slvaddr, Ptr, 2, XIIC_STOP);
}
u8 Read(u32 BaseAddress,u8 Slvaddr, u8 Address)
{
unsigned Result;
u8 A[1] = {Address};
u8 *Ptr = A;
u8 Buffer[1];
Result = XIic_Send(BaseAddress, Slvaddr, Ptr, 1, XIIC_STOP);
Result = XIic_Recv( BaseAddress, Slvaddr, Buffer, 1, XIIC_STOP);
return Buffer[0];
}
输入并保存好代码后,我们就可以建立嵌入式系统了,首先建立fsbl工程。点击“File”,选择“New”,点击“Application Project”,在“Project name”中输入fsbl,点击“Next”选择“Zynq FSBL”,如图30所示。
点击“Finish”,右键“fsbl”文件夹,点击“Create Boot Image”,在弹出的对话框中选择“Create Image”,如图31所示。
用同样的方法,对工程文件夹“LSM303D”建立Boot Image,如图32所示。
我们首先将传感器和板子连线,开发板跳线记得要接QSPI模式,LSM303D传感器上SCL脚接板子的H15口,SDA脚接板子的J15口,SD0/SA0脚接地,CS1脚接地,CS2脚接3.3V高电平,接线如图33所示。
接着,我们打开Vivado,在左边的“Program and debug”中点击“Open Hardware Manager”,点击“Open Target”,点击“Open New Target”,点击“Next”,再次点击“Next”,弹出如图34所示对话框,点击“Next”,点击“Finish”。
接着我们选择需要烧录的flash型号,在“Hardware”界面中右键xc7x010_1,点击“Add Configuration Memory Device”,在弹出的对话框中的“Search”中输入s25fl128s,在结果中选择“s25fl128s-3.3v-qspi-x4-single”,如图35所示。
点击“OK”,再次点击“OK”,在弹出的窗口中的“Configuration file”中选择工程文件夹下的sdk文件夹,在LSM303D文件夹中打开bootimage文件夹,找到BOOT.bin文件并选中,如图36所示。
点击“OK”,开始烧录驱动程序,等待烧录完成后,我们打开串口调试工具,我用的是SSCOM32,波特率选择1152000bps,接着按下开发板上的PGOOD键(重启键),就可以在串口调试工具中接收到传感器发来的数据了,如图37所示。
以上就是用如何在zynq-7010下运用I2C总线完成对LSM303D传感器的数据读取的步骤,整个流程都是本人历时近两个月慢慢摸索出来的。希望能对需要用FPGA来读取LSM303D传感器的人有所帮助~