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

目录

概述

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+IRap3216c_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-striptest_ap3216: test_ap3216.o drv_ap3216.o$(CC) $(CFLAGS) -o test_ap3216 test_ap3216.o drv_ap3216.o$(STRIP) -s test_ap3216clean:rm -f test_ap3216 test_ap3216.o drv_ap3216.o

4 测试

4.1 编译代码

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

4.2 运行测试程序

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

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

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

相关文章

代码随想录算法训练营第59天 | 583.两个字符串的删除操作 + 72.编辑距离 + 编辑距离总结篇

今日任务 583. 两个字符串的删除操作 72. 编辑距离 编辑距离总结篇 583.两个字符串的删除操作 - Medium 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。 每步 可以…

【数学建模规则】2024年第九届数维杯大学生数学建模挑战赛参赛指南

一、竞赛介绍 数维杯大学生数学建模挑战赛每年分为两场&#xff0c;每年上半年为数维杯国赛&#xff08;5月&#xff0c;俗称小国赛&#xff09;&#xff0c;下半年为数维杯国际赛(11月)&#xff0c;2023年第八届数维杯大学生数学建模挑战赛共有近1.4万名学生参赛&#xff0c;…

Unity之PUN2插件实现多人联机射击游戏

目录 &#x1f4d6;一、准备工作 &#x1f4fa;二、UI界面处理 &#x1f4f1;2.1 登录UI并连接PUN2服务器 &#x1f4f1;2.2 游戏大厅界面UI &#x1f4f1;2.3 创建房间UI &#x1f4f1;2.4 进入房间UI &#x1f4f1;2.5 玩家准备状态 &#x1f4f1;2.6 加载战斗场景…

vue proxy解决跨域问题

https://blog.csdn.net/tttttrrrhh/article/details/127685318 cims系统ui

java 面向对象-上:类的结构之二

类的设计中&#xff0c;两个重要结构之二&#xff1a;方法 方法 描述类应该具的功能。 比如&#xff1a;Math类&#xff1a;sqrt()\random() \... Scanner类&#xff1a;nextXxx() ... Arrays类&#xff1a;sort() \ binarySearch() \ toString() \ equals() \ ... 1.举例 p…

[Java 项目亮点] 三层限流设计

思路来源&#xff1a;bilibili 河北王校长 文章目录 面试官可能会问你能详细介绍一下Nginx的http_limit_req_module模块吗&#xff1f;你能解释一下如何在Nginx中配置http_limit_req_module模块吗&#xff1f;你知道如何调整Nginx的http_limit_req_module模块以适应不同的业务需…

【服务器数据恢复】通过reed-solomon算法恢复raid6数据的案例

服务器数据恢复环境&#xff1a; 一台网站服务器中有一组由6块磁盘组建的RAID6磁盘阵列&#xff0c;操作系统层面运行MySQL数据库和存放一些其他类型文件。 服务器故障&#xff1a; 该服务器在工作过程中&#xff0c;raid6磁盘阵列中有两块磁盘先后离线&#xff0c;不知道是管理…

Linux--自定义shell

shell shell就是操作系统提供给用户与操作系统进行交互的命令行界面。它可以理解为一个用户与操作系统之间的接口&#xff0c;用户可以通过输入命令来执行各种操作&#xff0c;如文件管理、进程控制、软件安装等。Shell还可以通过脚本编程实现自动化任务。 常见的Unix系统中使…

创新性3D数据合成模型,微软推出EgoGen

随着AR、VR等设备的广泛应用,第一人称的应用开始增多。但在研发方面面临不同的挑战,例如&#xff0c;图像模糊、视觉混乱、遮挡更严重等&#xff0c;给视觉模型的训练带来重大挑战。 一方面,人工标注真实第一视角数据集&#xff0c;来培训深度学习模型的成本和难度都很高。另一…

Java 泛型

优质博文&#xff1a;IT-BLOG-CN 一、为什么要有泛型 【1】解决元素存储的安全性问题。 【2】解决获取数据元素时&#xff0c;需要类型强转的问题。 【3】可以统一数据类型&#xff0c;便于操作。 【4】将运行时的异常提前到了编译时&#xff0c;提高了效率。 【5】实现代码的…

Day20_网络编程(软件结构,网络编程三要素,UDP网络编程,TCP网络编程)

文章目录 Day20 网络编程学习目标1 软件结构2 网络编程三要素2.1 IP地址和域名1、IP地址2、域名3、InetAddress类 2.2 端口号2.3 网络通信协议1、OSI参考模型和TCP/IP参考模型2、UDP协议3、TCP协议 2.4 Socket编程 3 UDP网络编程3.1 DatagramSocket和DatagramPacket1、Datagram…

小世界网络:直径、分形、同配性

1.小世界网络特点 —— 网络直径接近于网络中节点数量的自然对数 2.小世界分形网络 —— 移除弱链接的小世界网络 3.同配性分析 —— Pearson相关系数、邻居相关度 在宏观层面上&#xff0c;关注平均度、度分布和聚类等全局结构特征的影响。更高的平均度被认为会导致更…

Zookeeper简介及选举机制

1.概述 Zookeeper是一个开源的&#xff0c;分布式的&#xff0c;为分布式框架&#xff08;如下图中的Hadoop和Hive&#xff09;提供协调服务的Apache项目。 工作机制&#xff1a;基于观察者设计模式的分布式服务管理框架&#xff0c;负责存储和管理数据&#xff0c;接受观察者…

[算法沉淀记录] 排序算法 —— 归并排序

排序算法 —— 归并排序 算法介绍 归并排序是一种分治算法&#xff0c;由约翰冯诺伊曼在1945年发明。它的工作原理是将未排序的列表划分为n个子列表&#xff0c;每个子列表包含一个元素(包含一个元素的列表被认为是有序的)&#xff0c;然后重复合并子列表以生成新的有序子列表…

ClickHouse 指南(三)最佳实践 -- 稀疏主索引

在ClickHouse主索引的实用介绍 ClickHouse release 24.1, 2024-01-30 1、简介 在本指南中&#xff0c;我们将深入研究ClickHouse索引。我们将详细说明和讨论: ClickHouse中的索引与传统的关系数据库管理系统有何不同ClickHouse是如何构建和使用表的稀疏主索引的什么是在Clic…

JavaScript原型继承与面向对象编程思想

原型继承与面向对象编程思想 在JavaScript中&#xff0c;原型(prototype)、构造函数(constructor)和实例对象(instance)是面向对象编程中的重要概念&#xff0c;并且它们之间存在着紧密的关系。 原型(prototype)&#xff1a;原型是JavaScript中对象之间关联的一种机制。每个Ja…

js使用import到本js文件中的函数时报错 Error [ERR_MODULE_NOT_FOUND]: Cannot find module

node:internal/process/esm_loader:97internalBinding(errors).triggerUncaughtException(^Error [ERR_MODULE_NOT_FOUND]: Cannot find module D:\桌面\Pagesizedetection\lib\screensize imported from D:\桌面\Pagesizedetection\index.js Did you mean to import ../lib/sc…

网页数据的存储--存储为文本文件(TXT、JSON、CSV)

用解析器解析出数据后&#xff0c;接下来就是存储数据了。数据的存储有多种多样&#xff0c;其中最简单的一种是将数据直接保存为文本文件&#xff0c;如TXT、JSON、CSV等。这里就介绍将数据直接保存为文本文件。 目录 一、Python存储数据的方法 1、 文件读取 2、 文件写入…

【Logback】Logback 日志框架的架构

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

npm install 失败,需要node 切换到 对应版本号

npm install 失败 原本node 的版本号是16.9&#xff0c;就会报以上错误 node版本问题了&#xff0c;我切到这个版本&#xff0c;报同样的错。降一下node&#xff08;14.18&#xff09;版本就好了 具体的方法&#xff1a;&#xff08;需要在项目根目录下切换&#xff09; 1. …