详解AP3216C(三合一sensor: 光照、距离、照射强度)驱动开发

news2024/11/18 23:26:57

目录

概述

1 认识AP3216C

1.1 AP3216C特性

1.2 AP3216C内部结构

1.3 AP3216C 硬件电路

1.4 AP3216C工作时序

1.4.1 I2C 写数据协议

1.4.2 I2C 读数据协议

1.5 重要的寄存器

1.5.1 系统配置寄存器

1.5.2 和中断相关寄存器

1.5.3 IR数据寄存器

1.5.4 ALS 数据寄存器

1.5.5 PS 数据寄存器

2 驱动开发

2.1 查看i2c总线下的设备

2.2 编写驱动代码 

 3 编写测试代码

3.1 测试代码实现

3.2 Makefile

4 测试

4.1 编译代码

4.2 运行测试程序


概述

        本文详细介绍AP3216C的特性,内部结构,操作时序和寄存器的参数意义,并使用linux platform tree 下i2c 驱动接口,实现了AP3216C的驱动程序。并且编写了一个测试范例,验证该驱动程序的性能。 其可以正确的读出sensor内部的数据。

源代码下载地址: AP3216Clinux环境下的驱动程序资源-CSDN文库

1 认识AP3216C

1.1 AP3216C特性

AP3216C是敦南科技出品的一款集成sensor, 其中包括 :ALS(数字型环境光线感应 sensor),PS(测距sensor)IR(照射sensor)。这款sensor主要用在手机、平板电脑、电视、显示器、数码相机等产品上。

1)驱动方式: 采用标准的I2C接口,且工作在快速模式(400K Hz)

2)输出模块可选: ALS, PS+IR, ALS+PS+IR, PD,ALS once, SW Reset, PS+IR once and ALS+PS+IR once.

3) 高分辨率:

数字型环境光线感应 sensor ,采用 16-bit 有效数据输出,数据采集范围( 0~65535 )

测距sensor,采用 10-bit 有效数据输出, 数据采集范围( 0~1023 )

1.2 AP3216C内部结构

由下结构图可以看见: ALS和PS分别和ADC模块连接,以采集外部数据 。IR本分隔在一个单独的模块。

1.3 AP3216C 硬件电路

AP3216C采用标准的i2c驱动模式,其和MCU之间通过3个线连接,SDA和SCL是I2C的驱动线,还提供一个中断引脚INT

1.4 AP3216C工作时序

AP3216C采用标准的i2c驱动接口,其slave 设备地址为:0x1e

1.4.1 I2C 写数据协议

1) 写方式一: 写寄存器地址

S: start 信号

Slave address : 7 bit

W: 写数据bit

A: ACK信号

Register Address: 寄存器地址

P: Stop信号

详细时序图:

2) 写方式二: 写寄存器地址 和数据

S: start 信号

Slave address : 7 bit

W: 使能写数据bit

A: ACK信号

Register Address: 寄存器地址

register Command: 写寄存器数据

P: Stop信号

详细时序图:

1.4.2 I2C 读数据协议

1) 读方式一: 读寄存器地址

S: start 信号

Slave address : 7 bit

R: 使能读数据bit

A: ACK信号

Register command: 寄存器数据

N: NACK信号

P: Stop信号

详细时序图:

2) 读方式二: 读寄存器地址的数据

S: start 信号

Slave address : 7 bit

R: 使能读数据bit

W: 使能写数据bit

A: ACK信号

Register command: 寄存器数据

N: NACK信号

P: Stop信号

详细时序图:

1.5 重要的寄存器

AP3216C内部有许多寄存器,其地址空间(0x00 ~ 0x2d ),由于篇幅所限,这里不对每个寄存器做一一介绍。如需了解,可参看文档:AP3216C Rev0.86. pdf。 本文主要介绍系统寄存器部分,地址空间(0x00 ~ 0x0f。各个寄存器的功能,看下表:

1.5.1 系统配置寄存器

该寄存器地址位0x00, 低位3个bit(bit-0 bit-1,bit-2)用于配置系统工作模式

具体模式如下表:

1.5.2 和中断相关寄存器

中断状态寄存器: address = 0x01

BIT-0: ALS-INT 用来表示中断是否发生, B0=1 表示ALS中断被触发, B0 =0 示ALS中断未被被触发

BIT-1: PS-INT 用来表示中断是否发生, B0=1 表示PS中断被触发, B0 =0 示PS中断未被被触发

中断清除寄存器: address = 0x02

当配置CLR_MNR = 0时, 在读取寄存器(0x0C, 0x0D, 0x0E, 0x0F)的值后,芯片会自动清除中断;

当配置CLR_MNR = 1时,需要软件强制把寄存器0x01的对应位置位为1,清除中断;

1.5.3 IR数据寄存器

对应地址: 0x0a 和0x0b

0x0a地址中,bit0和bit1 为数据位,表示低字节位, IR_OF为数据溢出标记,当IR_OF=1, 表明IR值过高,其会影响PS的数据的有效性

0x0b地址中,为IR 数据高字节位

1.5.4 ALS 数据寄存器

对应地址: 0x0c 和0x0d

1.5.5 PS 数据寄存器

对应地址: 0x0E 和0x0F

IR_OF = 1,表示读取的数据有效。IR_OF = 0,表示读取的数据无效。

2 驱动开发

2.1 查看i2c总线下的设备

i2c总线上可以挂载多个device,其要求在同一条总线上,每个设备的地址必须唯一性。如果两个设备的地址一样,会出现时序混乱。 下面通过命令来探测一下i2c总线下的设备情况。

查看i2c-0下设备情况

使用命令

 i2cdetect -a 0

执行该命令后,列出设备地址信息: 该总线下有两个设备,其地址分别为:0x1a和0x1e

2.2 编写驱动代码 

创建drv_ap3216c.c,编写如下代码

/***************************************************************
Copyright  2024-2029. All rights reserved.
文件名     : drv_ap3216c.c
作者       : tangmingfei2013@126.com
版本       : V1.0
描述       : ap3216c 驱动程序
其他       : 无
日志       : 初版V1.0 2024/02/01

***************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/types.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <linux/fs.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <time.h>
#include "drv_ap3216.h"

#define DEV_FILE               "/dev/i2c-0"


static int fd = -1;

static void msleep(unsigned int time)
{
    struct timespec sleeper, temp;

    sleeper.tv_sec = (time_t)(time/1000);
    sleeper.tv_nsec = (long)(time%1000)*1000000;
    nanosleep(&sleeper, &temp);
}

static int ap3216c_write_reg( unsigned char reg, unsigned char cmd)
{
    int              ret = -1;
    unsigned char    buf[2] = {0};

    buf[0] = reg;
    buf[1] = cmd;
    
    ret = write(fd, buf, 2);
    if( ret < 0 )
    {
        printf("write cmd to ap3216c register failure.\n");
        return -1;
    }
    
    return 0;
}

static int ap3216c_read_reg( unsigned char reg, unsigned char *val)
{
    int           ret = -1;
    unsigned char buf[1] = {0};

    buf[0] = reg;           //send register address 
    ret = write( fd, buf, 1);
    if( ret < 0 )
    {
        printf("write cmd to ap3216c register failure.\n");
        return -1;
    }
    
    ret = read(fd, buf, 1);  //read data from the register 
    if( ret < 0 )
    {
        printf("get the humidy failure.\n");
        return -1;
    }
    *val = buf[0];
    
    return 0;
}

void ap3216c_read_datas(ap3216c_data *pdata)
{
    unsigned char i =0;
    unsigned char buf[6], val = 0;
    
    /* read all sensor‘ data */
    for( i = 0; i < 6; i++)    
    {
        ap3216c_read_reg( AP3216C_IRDATALOW + i, &val); 
        buf[i] = val;
    }

     /* IR   */
    if(buf[0] & 0X80){  /* IR_OF位为1,则数据无效 */
        pdata->ir = 0;
    }        
    else {        
        pdata->ir = ((unsigned short)buf[1] << 2) | (buf[0] & 0X03); 
    }        
    
    /* ALS  */  
    pdata->als = ((unsigned short)buf[3] << 8) | buf[2]; 
    
    /* PS */
    if(buf[4] & 0x40){    /* IR_OF位为1,则数据无效 */
        pdata->ps = 0; 
    }        
    else{                
        pdata->ps = ((unsigned short)(buf[5] & 0X3F) << 4) | (buf[4] & 0X0F); 
    }
}

void ap3216c_release( void )
{
    close( fd );
}

int ap3216c_init(void)
{
    // init i2c 
    fd = open(DEV_FILE, O_RDWR);
    if( fd < 0 )
    {
        close( fd );
        printf("%s %s i2c device open failure: %s\n", __FILE__, __FUNCTION__, strerror(errno));
        return -1;
    }

    ioctl(fd, I2C_TENBIT, 0);
    ioctl(fd, I2C_SLAVE, AP3216C_ADDR);
    
    // reset sensor 
    ap3216c_write_reg( AP3216C_SYSTEMCONG, 0x04);
    msleep(2);
    
    // enable ALS、PS+IR
    ap3216c_write_reg( AP3216C_SYSTEMCONG, 0X03);
    msleep(2);
    
    return fd;
}

在drv_ap3216c.h中,编写如下代码:

#ifndef __DRV__AP3216_H
#define __DRV__AP3216_H

#ifdef __cplusplus
extern "C" {
#endif

#define AP3216C_ADDR          0X1E

/* AP3316C寄存器 */
#define AP3216C_SYSTEMCONG    0x00    /* 配置寄存器       */
#define AP3216C_INTSTATUS     0X01    /* 中断状态寄存器   */
#define AP3216C_INTCLEAR      0X02    /* 中断清除寄存器   */
#define AP3216C_IRDATALOW     0x0A    /* IR数据低字节     */
#define AP3216C_IRDATAHIGH    0x0B    /* IR数据高字节     */
#define AP3216C_ALSDATALOW    0x0C    /* ALS数据低字节    */
#define AP3216C_ALSDATAHIGH   0X0D    /* ALS数据高字节    */
#define AP3216C_PSDATALOW     0X0E    /* PS数据低字节     */
#define AP3216C_PSDATAHIGH    0X0F    /* PS数据高字节     */

typedef struct _ap3216c_data{
   unsigned short ir; 
   unsigned short als; 
   unsigned short ps;      /* */ 
}ap3216c_data;

void ap3216c_read_datas(ap3216c_data *pdata);
int ap3216c_init(void);


#ifdef __cplusplus
}
#endif

#endif /* __DRV__AP3216_H */

 3 编写测试代码

测试主要实现,调用驱动程序接口,读取ALS,PS,IR数据,并打印出来

3.1 测试代码实现

创建一个test_ap3216.c,编写如下代码:

/***************************************************************
Copyright  2024-2029. All rights reserved.
文件名     : test_ap3216.c
作者       : tangmingfei2013@126.com
版本       : V1.0
描述       : 验证dev_ap3216.c 
其他       : 无
日志       : 初版V1.0 2024/02/1

***************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/types.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <linux/fs.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <time.h>
#include "drv_ap3216.h"

int main(void)
{
    ap3216c_data stru_data;
    int count_run = 100;
    int set;

    set = ap3216c_init();
    if( set < 0){
        printf("initial ap3216c failure.\n");
        return -1;
    }

    while( count_run > 0){
        ap3216c_read_datas( &stru_data );
        
        printf("ir = %d, als = %d, ps = %d \r\n", 
               stru_data.ir, stru_data.als, stru_data.ps);
        count_run--;
        sleep(1);
    }

    ap3216c_release();

    return 0;
}

3.2 Makefile

在测试程序的目录下,创建一个makefile文件,编写如下代码

CFLAGS= -Wall -O2
CC=/home/ctools/gcc-linaro-4.9.4-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc
STRIP=/home/ctools/gcc-linaro-4.9.4-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-strip

test_ap3216: test_ap3216.o drv_ap3216.o
	$(CC) $(CFLAGS) -o test_ap3216 test_ap3216.o drv_ap3216.o
	$(STRIP) -s test_ap3216

clean:
	rm -f test_ap3216 test_ap3216.o drv_ap3216.o

4 测试

4.1 编译代码

使用Make命令编译代码,然后将生成的可执行文件copy到NFS的共享目录下,方便在板卡中运行程序。

4.2 运行测试程序

 运行测试程序,可以看见在终端上打印出来sensor的数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1466786.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++之stack与queue的模拟实现

一、 stack的介绍和使用 1. stack的介绍 stack 的文档介绍 翻译&#xff1a; 1. stack 是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入与提取操作。 2. stack 是作为容器适配器被实现的&#xff…

C++的queue容器->基本概念、常用接口

#include<iostream> using namespace std; #include <queue> #include <string> //队列 queue class Person { public: Person(string name, int age) { this->m_Name name; this->m_Age age; } string m_Name; int…

.netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项

1、SqlSugarCore 相关 1.1 主项目添加数据&#xff0c;否则会报数据库连接错误&#xff1a; <InvariantGlobalization>false</InvariantGlobalization> <PropertyGroup><TargetFramework>net8.0</TargetFramework><Nullable>enable</…

PostMan使用自带js库base64编码、sha256摘要、环境变量的使用

目录 1、环境变量的使用2、base64编码、sha256摘要、以及脚本的使用3、脚本代码 在请求调试接口的过程中&#xff0c;因为要使用大量相同的参数&#xff0c;使用变量的方式能很大程度上减轻接口调用的工作量 版本说明&#xff1a;Postman for Windows&#xff0c;Version&#…

【办公类-16-10-02】“2023下学期 6个中班 自主游戏观察记录(python 排班表系列)

背景需求&#xff1a; 已经制作了本学期的中4班自主游戏观察记录表 【办公类-16-10-01】“2023下学期 中4班 自主游戏观察记录&#xff08;python 排班表系列&#xff09;-CSDN博客文章浏览阅读398次&#xff0c;点赞10次&#xff0c;收藏3次。【办公类-16-10-01】“2023下学…

无人机竞赛常用目标检测方法--色块检测

本次开源计划主要针对大学生无人机相关竞赛的视觉算法开发。 开源代码仓库链接&#xff1a;https://github.com/zzhmx/Using-color-gamut-limitations-such-as-HSV-and-RGB-for-object-detection.git 主要使用传统算法&#xff0c;如果想要使用进阶版机器学习算法&#xff0c;请…

golang tun设备创建并监听

golang tun设备创建并监听 linux tun设备文件地址为/dev/net/tun.直接打开即可(关闭文件描述符创建的tun虚拟接口自动注销) fd,err:syscall.Open("/dev/net/tun",syscall.O_RDWR,0640)//关闭 syscall.Close(fd)初始化 配置ip地址启动虚拟网卡 ip addr add xxx.xx…

【数据分享】中国首套1公里高分辨率大气湿度指数数据集(6个指标\免费获取)

湿度数据是气象学和许多其他领域中至关重要的数据&#xff0c;可用于气象预测与气候研究。之前我们分享过Excel格式和GIS矢量格式&#xff08;均可查看之前的文章获悉详情&#xff09;的2000-2020年全国各城市逐日、逐月和逐年的湿度数据。 本次我们给大家带来的是中国首套1公…

【Linux网络】网络编程套接字(TCP)

目录 地址转换函数 字符串IP转整数IP 整数IP转字符串IP 关于inet_ntoa 简单的单执行流TCP网络程序 TCP socket API 详解及封装TCP socket 服务端创建套接字 服务端绑定 服务端监听 服务端获取连接 服务端处理请求 客户端创建套接字 客户端连接服务器 客户端…

2023年的AI模型学习/部署/优化

可以的话&#xff0c;github上给点一个小心心&#xff0c;感谢观看。 LDC边缘检测的轻量级密集卷积神经网络&#xff1a; meiqisheng/LDC (github.com)https://github.com/meiqisheng/LDC segment-anything分割一切的图像分割算法模型&#xff1a; meiqisheng/segment-anyt…

vue2+element医院安全(不良)事件报告管理系统源代码

目录 安全不良事件类型 源码技术栈 医院安全&#xff08;不良&#xff09;事件报告管理系统采用无责的、自愿的填报不良事件方式&#xff0c;有效地减轻医护人员的思想压力&#xff0c;实现以事件为主要对象&#xff0c;可以自动、及时、实际地反应医院的安全、不良、近失事件…

flink state原理,TTL,状态后端,数据倾斜一文全

flink state原理 1. 状态、状态后端、Checkpoint 三者之间的区别及关系&#xff1f;2 算子状态与键控状态的区别2.1 算子状态2.2 键控状态2.3 算子状态api2.4 键控状态api 3 HashMapStateBackend 状态后端4 EmBeddedRocksDbStateBackend 状态后端5 状态数据结构介绍5.1 算子状态…

129 Linux 系统编程8 IO操作 系统函数 open

系统调用 什么是系统调用&#xff1a; 由操作系统实现并提供给外部应用程序的编程接口。(Application Programming Interface&#xff0c;API)。是应用程序同系统之间数据交互的桥梁。 C标准函数和系统函数调用关系。一个helloworld如何打印到屏幕。 回忆我们前面学过的C标准…

ArcgisForJS如何使用ArcGIS Server发布的切片地图服务?

文章目录 0.引言1.准备海量地理数据2.ArcGIS Server发布切片地图服务3.ArcgisForJS使用ArcGIS Server发布的切片地图服务 0.引言 ArcGIS Server是一个由Esri开发的地理信息系统&#xff08;GIS&#xff09;服务器软件&#xff0c;它提供了许多功能&#xff0c;包括发布切片地图…

MIT-6.824-Lab2,Raft部分笔记|Use Go

文章目录 前记Paper6&#xff1a;RaftLEC5、6&#xff1a;RaftLAB22AtaskHintlockingstructureguide设计与编码 2BtaskHint设计与编码 2CtaskHint question后记 LEC5&#xff1a;GO, Threads, and Raftgo threads技巧raft实验易错点debug技巧 前记 趁着研一考完期末有点点空余…

springboot751社区维修平台

springboot751社区维修平台 获取源码——》公主号&#xff1a;计算机专业毕设大全

【Logback】Logback 日志框架的架构

目录 1、Logger&#xff08;记录器&#xff09; &#xff08;1&#xff09;有效级别和级别继承 &#xff08;2&#xff09;日志打印和日志筛选 &#xff08;3&#xff09;记录器命名 2、Appenders&#xff08;追加器&#xff09; 3、Layouts&#xff08;布局&#xff09;…

C语言-指针初学速成

1.指针是什么 C语言指针是一种特殊的变量&#xff0c;用于存储内存地址。它可以指向其他变量或者其他数据结构&#xff0c;通过指针可以直接访问或修改存储在指定地址的值。指针可以帮助我们在程序中动态地分配和释放内存&#xff0c;以及进行复杂的数据操作。在C语言中&#…

数字化魔方:旋转到本地部署还是SaaS模式?

数字化系统部署策略的选择&#xff0c;无论是本地部署还是SaaS模式&#xff0c;其核心在于契合企业的个性化需求、成本考量、安全要求以及未来发展战略。两种部署方式各有优势和挑战&#xff0c;需要企业深入分析自身情况&#xff0c;审慎抉择。 对于本地部署而言&#xff0c;它…

二手货wordpress企业网站主题模板

二手车wordpress主题模板 简洁的二手车wordpress主题模板&#xff0c;适合做二手车业务的公司官方网站使用。 https://www.jianzhanpress.com/?p3473 wordpress二手物资回收主题 绿色wordpress二手物资回收主题&#xff0c;用于二手物资回收公司WP建站使用。 https://www.…