详解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+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的数据

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android 开发一个耳返程序(录音,实时播放)

本文目录 点击直达 Android 开发一个耳返程序程序编写1. 配置 AndroidManifast.xml2.编写耳返管理器3. 录音权限申请4. 使用注意 最后我还有一句话要说怕相思&#xff0c;已相思&#xff0c;轮到相思没处辞&#xff0c;眉间露一丝 Android 开发一个耳返程序 耳返程序是声音录入…

计算机网络实验八 利用 Java /C++开发网络聊天应用程序

一、实验目的和要求 1)基本掌握利用 Java 开发环境调试应用程序的方法。 2)理解基于套接字开发网络应用程序的过程,深入理解客户/服务器方式工作原理。 3)掌握基于Java和C++开发网络通信程序的方法。 二、实验环境 1)运行 Windows 2008 Server/XP/7 操作系统的 PC 2 台…

应急响应实战笔记03权限维持篇(3)

0x00 前言 攻击者在获取服务器权限后&#xff0c;会通过一些技巧来隐藏自己的踪迹和后门文件&#xff0c;本文介绍Linux下的几种隐藏技术。 0x01 隐藏文件 Linux 下创建一个隐藏文件&#xff1a;touch .test.txt touch 命令可以创建一个文件&#xff0c;文件名前面加一个 点…

一文读懂:AWS 网络对等互连(VPC peering)实用操作指南

VPC peering connection-网络对等互连在您的 Atlas VPC 和云提供商的 VPC 之间建立私有连接。该连接将流量与公共网络隔离以提高安全性。本篇文章有VPC peering的操作指南以及价格等信息。如还有疑问请联系我们MongoDB的销售&#xff0c;客户成功经理或解决方案架构师。 1 使用…

开源大语言模型作为 LangChain 智能体

概要 开源大型语言模型 (LLMs) 现已达到一种性能水平&#xff0c;使它们适合作为推动智能体工作流的推理引擎: Mixtral 甚至在我们的基准测试中 超过了 GPT-3.5&#xff0c;并且通过微调&#xff0c;其性能可以轻易的得到进一步增强。 引言 针对 因果语言建模 训练的大型语言模…

用买糖果的方式来理解正交匹配追踪(OMP)算法

在信号处理领域&#xff0c;压缩感知&#xff08;Compressed Sensing&#xff09;是一种能够从远少于传统奈奎斯特采样定理所要求的样本数目中重建稀疏信号的技术。压缩感知的理论基础在于一个前提假设&#xff0c;即许多自然信号都含有稀疏的表示&#xff0c;换句话说&#xf…

【Python】OpenCV-图像轮廓检测初学

图像轮廓检测初学 在图像处理领域中&#xff0c;轮廓检测是一项重要的任务&#xff0c;用于寻找并标定图像中的物体边缘。本文将介绍如何使用OpenCV库进行图像轮廓检测&#xff0c;并展示一个简单的示例代码。代码中的注释将详细解释每一步的操作。 1. 引言 图像轮廓检测是图…

决策树算法

目录 谷歌笔记本&#xff08;可选&#xff09; 决策树 决策树的一般流程 信息增益 划分数据集 递归构建决策树 使用Matplotlib注解绘制树形图 Matplotlib注解 构造注解树 测试和存储分类器 测试算法&#xff1a;使用决策树执行分类 使用算法&#xff1a;决策树的存…

RISC-V知识总结 —— 指令集

资源1: RISC-V China – RISC-V International 资源2: RISC-V International – RISC-V: The Open Standard RISC Instruction Set Architecture 资源3: RV32I, RV64I Instructions — riscv-isa-pages documentation 1. 指令集架构的类型 在讨论RISC-V或任何处理器架构时&…

基于springboot+vue的图书进销存管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

【Vue3】学习computed计算属性

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

华清远见嵌入式学习——驱动开发——day9

目录 作业要求&#xff1a; 作业答案&#xff1a; 代码效果&#xff1a; ​编辑 Platform总线驱动代码&#xff1a; 应用程序代码&#xff1a; 设备树配置&#xff1a; 作业要求&#xff1a; 通过platform总线驱动框架编写LED灯的驱动&#xff0c;编写应用程序测试&…

JAVA代码审计之XSS漏洞

Part1 漏洞案例demo&#xff1a; 没有java代码审计XSS漏洞拿赏金的案例。 所以将就看看demo吧 漏洞原理&#xff1a;关于XSS漏洞的漏洞原理核心其实没啥好说的&#xff0c;网上一查一大堆 反射性XSS漏洞 <% page language"java" contentType"text/html; c…

C# OpenCvSharp 利用白平衡技术进行图像修复

目录 效果 灰度世界(GrayworldWB)-白平衡算法 完美反射(SimpleWB)-白平衡算法 基于学习的(LearningBasedWB)-白平衡算法 代码 下载 C# OpenCvSharp 利用白平衡技术进行图像修复 OpenCV xphoto模块中提供了三种不同的白平衡算法&#xff0c;分别是&#xff1a;灰度世界(G…

bat脚本进程停止与启动

在Windows操作系统中&#xff0c;批处理&#xff08;Batch&#xff09;脚本是一种常见的自动化脚本工具&#xff0c;通过BAT文件来执行一系列DOS命令。通过BAT脚本&#xff0c;我们可以轻松地控制进程的启动和停止。 一、进程停止 在BAT脚本中&#xff0c;要停止一个进程&…

基于Redis限流(固定窗口、滑动窗口、漏桶、令牌桶)(肝货!!!)

近期redis复习的比较多&#xff0c;在限流这方面发现好像之前理解的限流算法有问题&#xff0c;索性花了一天“带薪摸鱼”时间肝了一天&#xff0c;有问题可以评论区探讨。 废话不多说&#xff0c;正片开始 目录 Maven固定窗口滑动窗口算法漏桶算法令牌桶算法 Maven 有些不用的…

B树的介绍

R-B Tree 简介特性B树特性m阶B树的性质&#xff08;这些性质是B树规定的&#xff09; B树的搜索B树的添加B树的删除——非叶子结点 简介 R-B Tree又称为Red-Black Tree&#xff0c;红黑树。是一种特殊的二叉查找树&#xff0c;红黑树的每个节点上都有存储为表示结点的颜色&…

3-Bean的生命周期

Bean的生命周期 创建对象和初始化是在AbstractAutowireCapableBeanFactory.doCreateBean()中完成的 创建对象 实例化&#xff08;构造方法&#xff09;依赖注入 初始化 执行Aware接口回调执行BeanPostProcessor.postProcessBeforeInitialization执行InitializingBean回调&…

ShardingSphere 5.x 系列【15】分布式主键生成器

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址:https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 概述2. 配置3. 内置算法3.1 UUID3.2 Snowflake3.3 NanoId3.4 CosId3.5 Co…

PostgreSQL教程(四):高级特性

一、简介 在之前的章节里我们已经涉及了使用SQL在PostgreSQL中存储和访问数据的基础知识。现在我们将要讨论SQL中一些更高级的特性&#xff0c;这些特性有助于简化管理和防止数据丢失或损坏。最后&#xff0c;我们还将介绍一些PostgreSQL扩展。 本章有时将引用教程&#xff0…