0
点赞
收藏
分享

微信扫一扫

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30


学习内容

使用SDK和提供的API进行初始化IIC,并驱动iic接口的光强度传感器GY-30。

开发环境

vivado 18.3 && SDK
开发板 pynq-z2
(由于这里的pynq的开发板没有相应的MIO可以供直接使用ARM端进行开发,所以本次内容仅仅用于模拟流程开发)
已经更新,使用EMIO驱动完成光强传感器的读取

IIC知识部分

​​嵌入式-iic通信的一些概念​​ 网上自行查找,不再赘述。

硬件平台搭建

首先我们需要打开我们的vivado进行block design的建立,方法同前文helloworld

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_数据


添加zynq ip

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_数据_02


对ip进行相应的配置,这里没有用到ps-pl部分,仅仅实现的是zynq的arm端的配置,所以这里的config勾选全部去掉。

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_初始化_03


设置选中sd,uart,iic,并根据自己的开发板进行合适的配置,由于zynq没有MIO对应空闲的引脚,(看了半天原理图只有一个,所以就随便配置下吧,MIO的位置)

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_数据_04


配置完成后,点击auto,生成下图

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_初始化_05


如果没啥问题,就进行生成HDL Wrapper,生成顶层文件。

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_数据_06


然后综合生成bit流文件

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_#include_07


生成bit流文件后选中导出hardware,

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_数据_08


并包含bit流文件

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_数据_09


运行sdk

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_数据_10

SDK软件部分

新建project

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_初始化_11


生成默认的helloworld后可以对相应的helloworld.c进行改名,(通常使用main.c,和keil的习惯相同),然后我们就要找到,官方给出的API,进行iic的开发。在bsp的目录下,我们可以很容易的找到各种头文件方便我们调用,和stm32的库相类似

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_初始化_12


如果我们想查看我们已经定义的功能区的所要用的函数,可以在system.mss中查看

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_初始化_13


打开后,可以看到我们之前在bd中配置的东西这里都会有相应的使用api的文件

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_#include_14


点击打开iicps的文件,我们就可以查看相应的api的使用方法。

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_数据_15


ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_数据_16

初始化外设需要的函数

XIicPs_LookupConfig();//查找外设的配置结构体
XIicPs_CfgInitialize();//初始化外设
XIicPs_SetSClk();//设置IIC速度

XIicPs_LookupConfig()

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_数据_17

根据唯一的设备ID查找设备配置。
表格包含系统中每个设备的配置信息。
参数DeviceId包含要为其查找配置的设备的ID。 返回指向找到的配置的指针;如果未找到指定的设备ID,则返回NULL。 有关XIicPs_Config的定义,请参见xiicps.h。

XIicPs_CfgInitialize()

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_初始化_18

初始化特定的XIicPs实例,以便驱动程序可以使用。
初始化后设备的状态为:禁用设备从模式参数InstancePtr是指向XIicPs实例的指针。 ConfigPtr是对包含有关特定IIC设备信息的结构的引用。 此函数为Config的内容指定的特定设备初始化InstancePtr对象。
EffectiveAddr是虚拟内存地址空间中的设备基地址。
一旦调用此函数,调用方负责保持从EffectiveAddr到设备物理基址的地址映射不变。
如果在调用此函数后地址映射发生更改,可能会发生意外错误。 如果不使用地址转换,请对该参数使用ConfigPtr->
BaseAddress,而是传递物理地址。 返回值如果成功,则返回值为XST_SUCCESS。

XIicPs_SetSClk();//设置IIC速度

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_数据_19

该功能设置IIC设备的串行时钟速率。
在设置这些设备选项之前,设备必须处于空闲状态而不是忙于传输数据。
数据速率由控制寄存器中的值设置。 确定正确寄存器值的公式为:Fscl = Fpclk /(22 x(divisor_a + 1)x(divisor_b + 1))有关设置串行时钟速率的完整说明,请参见硬件数据手册。
参数InstancePtr是指向XIicPs实例的指针。 FsclHz是以Hz为单位的时钟频率。 两种最常见的时钟频率是100KHz和400KHz。 如果成功设置了选项,则返回XST_SUCCESS。
XST_DEVICE_IS_STARTED(如果设备当前正在传输数据)。 设置选项之前,传输必须完成或中止。
如果无法设置Fscl频率,则为XST_FAILURE。

DEVICE_ID的查找办法:

在bsp文件夹中的lib中找到xparameters.h的文件然后进行ctrl+f查找输入iic,快速定位到相对应的文件。

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_数据_20

初始化函数

首先初始化对应的结构体指针:

XIicPs *iicps;
XIicPs_Config * iicpscfgtr;

编写初始化函数

int InitIic(XIicPs *iips,XIicPs_Config * iiccfg){
int status;
iiccfg = XIicPs_LookupConfig(I2C_0_DEVICE_ID);
status = XIicPs_CfgInitialize(iips,iiccfg,iiccfg->BaseAddress);
if(status !=XST_SUCCESS){
return XST_FAILURE;
}
status = XIicPs_SetSClk(iips,I2C_0_CLK);
if(status !=XST_SUCCESS){
return XST_FAILURE;
}
return 0;
}

最后根据gy-30的手册进行编写读取光强的数据,完整main如下:

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xiicps.h"
#include "xparameters.h"
#include "sleep.h"
#define
#define
#define//定义器件在IIC总线中的从地址,根据ALT ADDRESS地址引脚不同修改
//ALT ADDRESS引脚接地时地址为0x46,接电源时地址为0xB8

// XIicPs* iicps;
XIicPs iicps;
XIicPs_Config * iicpscfgtr;


//初始化 iic
int InitIic(XIicPs *iips,XIicPs_Config *iiccfg);

int main()
{
int status;
double out=0;
unsigned short tmp;
unsigned char Cmdon = 0x01;
unsigned char Cmdlight = 0x10;
char temp[2];
init_platform();
status=InitIic(&iicps,iicpscfgtr);
if(status !=XST_SUCCESS){
return XST_FAILURE;
}
//初始化
status = XIicPs_MasterSendPolled(&iicps,&Cmdon,1,IIC_0_SALV_ADDR);
if(status !=XST_SUCCESS){
return XST_FAILURE;
}
usleep(10000);//延时10ms
printf("init iic successful!\n");
while(1){
status = XIicPs_MasterSendPolled(&iicps,&Cmdon,1,IIC_0_SALV_ADDR);
if(status !=XST_SUCCESS){
return XST_FAILURE;
}
status = XIicPs_MasterSendPolled(&iicps,&Cmdlight,1,IIC_0_SALV_ADDR);
if(status !=XST_SUCCESS){
return XST_FAILURE;
}
usleep(180000);//延时180ms
status = XIicPs_MasterRecvPolled(&iicps,&temp,2,IIC_0_SALV_ADDR);

//串口检测结果
tmp = (temp[0]<<8)| temp[1];
out = tmp/1.2;
printf("light intensity : %.1f lx\n",out);
usleep(1000000);
}
cleanup_platform();
return 0;
}
int InitIic(XIicPs *iips,XIicPs_Config * iiccfg){
int status;
iiccfg = XIicPs_LookupConfig(I2C_0_DEVICE_ID);
status = XIicPs_CfgInitialize(iips,iiccfg,iiccfg->BaseAddress);
if(status !=XST_SUCCESS){
return XST_FAILURE;
}
status = XIicPs_SelfTest(iips);
if (status != XST_SUCCESS) {
return XST_FAILURE;
}
status = XIicPs_SetSClk(iips,I2C_0_CLK);
if(status !=XST_SUCCESS){
return XST_FAILURE;
}
return 0;
}

summary

在使用sdk时候,有个小细节要注意,我用的是18.3版本的sdk,在每次编写代码完成后要点一下保存才会将之前的内容覆盖,也就是该版本的SDK,编译前不会自动保存刚刚写好的代码,这一点需要注意。

因为本次只是进行模拟实验,所以没有实验效果的反馈图,也不知道具体在启用读iic数据的正确性,往后再学习一些后,我将会使用ps和pl交互的管脚进行重跑本次实验。

更新配置EMIO后成功进行了传感器数据的读取。

ZYNQ-实现外设驱动开发-iic接口的光强度传感器GY-30_#include_21


举报

相关推荐

0 条评论