单片机/MCU论坛
直播中

jf_85110202

未满1年用户 269经验值
擅长:嵌入式技术 开发板 仪表仪器 单片机
私信 关注
[文章]

《DNESP32S3使用指南-IDF版_V1.6》第二十五章 IIC_AP3216C实验

第二十五章 IIC_AP3216C实验

本章,我们将继续使用ESP32-S3的硬件IIC接口去驱动AP3216C传感器,检测环境光强度(ALS)、接近距离(PS)和红外线强度(IR)等环境参数。本章分为如下几个小节:
本章分为如下几个小节:
25.1 AP3216C简介
25.2 硬件设计
25.3 程序设计
25.4 下载验证


25.1 AP3216C介绍
AP3216C是敦南科技推出的一款三合一环境传感器, 包含了:数字环境光传感器(ALS)、接近传感器(PS)和一个红外LEDIR)。该芯片通过IIC接口和MCU连接,并支持中断(INT)输出。AP3216C实物图如下图所示:
第二十五章 IIC298.png
25.1.1 AP3216C实物图
AP3216C的特点如下:
l IIC接口,支持高达400KHz通信速率
l 支持多种工作模式(ALSPS+IRALS+PS+IR等)
l 内置温度补偿电路
l 工作温度支持-30~80
l 环境光传感器具有16位分辨率
l 接近传感器具有10位分辨率
l 红外传感器具有10位分辨率
l 超小封装(4.1*2.4*1.35mm
因为以上一些特性,AP3216C被广泛应用于智能手机上面,用来检测光强度(自动背光控制),和接近开关控制(听筒靠近耳朵,手机自动灭屏功能)。
AP3216C的框图如下图所示。
第二十五章 IIC560.png
25.1.2 AP3216C框图
AP3216C的引脚说明如下表所示。
引脚编号
标号
说明
1
VDD
电源,接3.3V
2
SCL
IIC时钟信号,开漏
3
GND
地线
4
LEDA
LED阳极,接3.3V
5
LEDC
LED阴极,一般连接LDR
6
LDR
LED驱动输出脚,一般接LEDC
7
INT
中断输出脚
8
SDA
IIC数据信号,开漏
25.1.1 AP3216C引脚说明
AP3216C和主控芯片只需要连接SCLSDAINT,就可以实现驱动。其SCLSDA24C02XL9555共用,连接在IO41IO42上,INT脚连接在XL9555P0_0上。
25.1.1 AP3216C寻址
要进行IIC通信,首先得知道器件地址,AP3216C器件地址是7位的,具体格式如下表。
Bit
7
6
5
4
3
2
1
0
Symbol
0
0
1
1
1
1
0
R/W
器件地址
读写位
25.1.1.1 AP3216C地址格式
        AP3216C器件地址为“0011110”即0x1E。读操作地址就为0x3D0x1E << 1 | 0x1,即0011 1101;写操作地址就为0x3C0x1E << 1 | 0x0,即0011 1100
25.1.2 AP3216C寄存器介绍
AP3216C有一系列寄存器,由这些寄存器来控制AP3216C的工作模式,以及中断配置和数据输出等。这里我们仅介绍在本章需要用到的一些寄存器,其他寄存器的描述和说明,请大家参考AP3216C的数据手册。本章需要用到AP3216C的寄存器如下表所示。
地址
有效位
指令
说明
0X00
2:0
系统模式
000:掉电模式(默认)
001ALS功能激活
010PS+IR功能激活
011ALS+PS+IR功能激活
100:软复位
101ALS单次模式
110PS+IR单次模式
111ALS+PS+IR单次模式
0X0A
7
IR低位数据
0IR&PS数据有效;1:无效
1:0
IR最低2位数据
0X0B
7:0
IR高位数据
IR8位数据
0X0C
7:0
ALS低位数据
ALS8位数据
0X0D
7:0
ALS高位数据
ALS8位数据
0X0E
7
PS低位数据
0:物体在远离;1:物体在靠近
6
0IR数据有效;1IR数据无效
3:0
PS最低4位数据
0X0F
7
PS高位数据
0:物体在远离;1:物体在靠近
6
0IR数据有效;1IR数据无效
5:0
PS6位数据
25.1.2.1 AP3216C相关寄存器及其说明
上表中,0X00是一个系统模式控制寄存器,主要在初始化的时候配置,初始化的时候,我们先设置其值为100,实行一次软复位,随后设置其值为011,开启ALS+PS+IR检测功能。
剩下的6个寄存器为数据寄存器,输出AP3216C内部三个传感器所检测到的数据(ADC值),并且还存在数据有效位以便判断寄存器的数据是否是有效的,描述如上表所示。
这里需要注意的是:读取间隔至少要大于112.5ms,因为,AP3216C内部完成一次ALS+PS+IR的数据转换,需要112.5ms的时间。
25.1.3 AP3216C时序介绍
ESP32-S3是通过IIC总线跟AP3216C进行通信的,对AP3216C相关寄存器进行写入配置,后面就是对相关数据寄存器进行读取。这里的时序主要就是写寄存器时序和读寄存器时序,我们一一介绍。
写寄存器时序
AP3216C的写寄存器时序如下图所示。
第二十五章 IIC2079.png
25.1.3.1 AP3216C写寄存器时序
图中,先发送AP3216C的写操作地址0x3C(器件地址0X1E << 1 | 读写位0x0),随后发送8位寄存器地址,最后发送8位寄存器值。其中:S,表示IIC起始信号;W,表示读/写标志位(W=0表示写,W=1表示读);A,表示应答信号;P,表示IIC停止信号。
读寄存器时序图
AP3216C的读寄存器时序如下图所示。
第二十五章 IIC2268.png
25.1.3.2 AP3216C读寄存器时序
图中,同样是先发送AP3216C的写操作地址0x3C,然后再发送寄存器地址,随后,重新发送起始信号(Sr),发送AP3216C的读操作地址0x3D(器件地址0X1E << 1 | 读写位0x1),然后读取寄存器值。其中:Sr,表示重新发送IIC起始信号;N,表示不对AP3216C进行应答;其他简写同上。
AP3216C的简介,我们就介绍到这里,关于该芯片的详细说明,请大家参考其数据手册。
25.2 硬件设计
25.2.1 例程功能
开机的时候先检测AP3216C是否存在,如检测不到AP3216C,则在LCD屏上面显示报错信息。如果检测到AP3216C,则显示正常,并在主循环里面,循环读取ALS+PS+IR的传感器数据,并显示在LCD屏幕上面。
25.2.2 硬件资源
1.USART0
U0TXD-IO43
U0RXD-IO44
2.XL9555
IIC_SDA-IO41
IIC_SCL-IO42
3.SPILCD
CS-IO21
SCK-IO12
SDA-IO11
DC-IO40(在P5端口,使用跳线帽将IO_SETLCD_DC相连)
PWR- IO1_3XL9555
RST- IO1_2XL9555
4.AP3216C
IIC_SDA-IO41
IIC_SCL-IO42
AP_INT-IO0_0XL9555
25.2.3 原理图
AP3216C相关原理图,如下图所示。
第二十五章 IIC2896.png
25.2.3.1 AP3216C原理图
这里说明一下,AP3216CAP_INT脚是连接在XL9555器件的IO0_0脚上,如果大家要使用AP3216C的中断输出功能,必须先初始化XL9555器件并配置IO0_0为输入功能,监测XL9555中断引脚是否有中断产生。若发现有中断产生,则判断是否是IO0_0导致的,从而检测到AP3216C的中断。在本章中,并没有用到AP3216C中断功能,所以没有对XL9555器件的IO0_0做设置。
25.3 程序设计
25.3.1 程序流程图
程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。下面看看本实验的程序流程图:
第二十五章 IIC3228.png

25.3.1.1 IIC_AP3216C实验程序流程图
25.3.2 IIC_AP3216C函数解析
ESP-IDF提供了一套API来配置IIC。要使用此功能,需要导入必要的头文件:
#include "driver/i2c.h"
关于配置IIC的函数在前面的章节已经详细讲明,在此不再赘述,请读者回顾之前第十九章节的相关内容。
1写数据
该函数用于复位AP3216C,并封装在ap3216c_comfig()函数中,其函数原型如下所示:
esp_err_t ap3216c_write_one_byte(uint8_t reg, uint8_t data)
该函数的形参描述,如下表所示:
形参
描述
reg
要写入数据的寄存器地址
data
要写入的数据
25.3.2.1 函数ap3216c_write_one_byte ()形参描述
返回值:ESP_OK表示配置成功。其他表示配置失败。
2,读取开启ALSPS+IR指令
该函数用于复位AP3216C,并封装在ap3216c_comfig()函数中,其函数原型如下所示:
esp_err_t ap3216c_read_one_byte(uint8_t* data, uint8_t reg)
该函数的形参描述,如下表所示:
形参
描述
data
指向数据存储区的指针类型
reg
寄存器地址
25.3.2.2 函数ap3216c_read_one_byte ()形参描述
返回值:ESP_OK表示复位成功。其他表示复位失败。
该函数通过一个指向数据存储区的指针再配合一寄存器地址的方式来读取之前写入系统配置寄存器的值0x03,通过判断寄存器是否写入了0x03来决定AP3216C的初始化是否真正完成。
25.3.3 IIC_AP3216C驱动解析
IDF15_ap3216c例程中,作者在15_ap3216c \components\BSP路径下新增了一个AP3216C文件夹,分别用于存放ap3216c.cap3216c.h这两个文件。其中,ap3216c.h文件负责声明AP3216C相关的函数和变量,而ap3216c.c文件则实现了AP3216C的驱动代码。下面,我们将详细解析这两个文件的实现内容。
1ap3216c.h文件
/* AP3216C信息 */
typedef struct _ap3216c_value_t
{
    uint16_t ir;
    uint16_t als;
    uint16_t ps;
} ap3216c_value_t;
/* 相关参数定义 */
#define AP3216C_INT     xl9555_pin_read(AP_INT_IO)
#define AP3216C_ADDR    0X1E                          /* AP3216C地址 */
我们选择使用IO42作为IIC时钟线,IO41作为IIC数据线,AP3216C的器件地址为0x1E
2ap3216c.c文件
/**
* @Brief       读取ap3216c16IO
* @param       data:存储区
* @param       reg :寄存器
* @retval      ESP_OK:读取成功;其他:读取失败
*/
static esp_err_t ap3216c_read_one_byte(uint8_t* data, uint8_t reg)
{
    uint8_t reg_buf[1];
    reg_buf[0] = reg;
    i2c_buf_t buf[2] = {
        {.len = 1, .buf = reg_buf},
        {.len = 1, .buf = data},
    };
i2c_transfer(&ap3216c_master,
                                 AP3216C_ADDR,
                                 2,
                                 buf,
                                 I2C_FLAG_WRITE |
                                 I2C_FLAG_READ |
                                 I2C_FLAG_STOP);
    return ESP_OK;
}
/**
* @brief       ap3216c写入16IO
* @param       data:要写入的数据
* @retval      ESP_OK:读取成功;其他:读取失败
*/
static esp_err_t ap3216c_write_one_byte(uint8_t reg, uint8_t data)
{
    uint8_t reg_buf[1];
    reg_buf[0] = reg;
   
    i2c_buf_t buf[2] = {
        {.len = 1, .buf = reg_buf},
        {.len = 1, .buf = &data},
    };
i2c_transfer(&ap3216c_master,
                                 AP3216C_ADDR,
                                 2,
                                 buf,
                                 I2C_FLAG_STOP); /* 传输传感器地址 */
    return ESP_OK;
}
/**
* @brief       初始化AP3216C
* @param      
* @retval      
*/
void ap3216c_init(i2c_obj_t self)
{
    if (self.init_flag == ESP_FAIL)
    {
        iic_init(I2C_NUM_0);    /* 初始化IIC */
    }
    ap3216c_master = self;
    while (ap3216c_comfig())    /* 检测不到AP3216C */
    {
        ESP_LOGE("ap3216c", "ap3216c init fail!!!");
        vTaskDelay(500);
    }
}
/**
* @brief       初始化AP3216C
* @param      
* @retval      0, 成功;
*              1, 失败;
*/
uint8_t ap3216c_comfig(void)
{
    uint8_t temp;
   
    ap3216c_write_one_byte(0x00, 0X04);         /* 复位AP3216C */
    vTaskDelay(50);                             /* AP33216C复位至少10ms */
    ap3216c_write_one_byte(0x00, 0X03);         /* 开启ALSPS+IR */
    ap3216c_read_one_byte(&temp,0X00);          /* 读取刚刚写进去的0X03 */
    if (temp == 0X03)
    {
        ESP_LOGE("ap3216c", "AP3216C success!!!");
        return 0;                                               /* AP3216C正常 */
    }
    else
    {
        ESP_LOGE("ap3216c", "AP3216C fail!!!");
        return 1;                                               /* AP3216C失败 */
}
}
ap3216c_init()函数中,通过判断IIC初始化标志位,确认IIC是否已经初始化,如果没有则进行IIC初始化,已经初始化了则跳过。然后把IIC_SDA引脚和IIC_SCL引脚作为I2C_NUM_0的数据线和时钟线使用。由于AP3216C手册中描述到400kHz通信频率,所以这里直接把I2C_NUM_0的通信速率设为400kHz
ap3216c_comfig()中,通过调用ap3216c_write_one_byteAP3216C进行软件复位,然后开启光强度ALS、接近距离PS和红外线强度IR功能检测。后面再通过调用该ap3216c_read_one_byte函数读一下刚刚写入的配置参数看是否正常写入,以此作为判断AP3216C是否正常的依据。
至于软件复位为什么要传入0x000x04,我们通过查找数据手册能够知道:
第二十五章 IIC6880.png
25.3.3.1形参值的具体描述
上图所示的便是复位AP3216C的指令通过简单的二进制向十六进制转换而得出。
同样地,我们通过查看数据手册也能得到,复位结束后需要写入开启ALSPS+IR指令,如下图所示:
第二十五章 IIC6988.png
25.3.3.2形参值的具体描述
初始化好AP3216C传感器之后,就可以对其采集到的数据进行获取,实现这个读取过程的函数为ap3216c_read_data,代码如下:
/**
* @brief         读取AP3216C的数据
* @NOTE         读取原始数据,包括ALS,PSIR
*                 如果同时打开ALS,IR+PS的话两次数据读取的时间间隔要大于112.5ms
* @param          ir        : IR传感器值
* @param        ps        : PS传感器值
* @param          als        : ALS传感器值
* @retval  
*/
void ap3216c_read_data(uint16_t *ir, uint16_t *ps, uint16_t *als)
{
    uint8_t buf[6];
    uint8_t i;
    for (i = 0; i < 6; i++)
    {
        buf = ap3216c_read_one_byte(0X0A + i);                /* 循环读取所有传感器数据 */
    }
    if (buf[0] & 0X80)
    {
        *ir = 0;                                                                                /* IR_OF位为1,则数据无效 */
    }
    else
    {
        *ir = ((uint16_t)buf[1] << 2) | (buf[0] & 0X03);/* 读取IR传感器数据 */
    }
    *als = ((uint16_t)buf[3] << 8) | buf[2];                        /* 读取ALS传感器数据 */
    if (buf[4] & 0x40)
    {
        *ps = 0;                                                                                 /* IR_OF位为1,则数据无效 */
    }
    else
{
        /* 读取PS传感器的数据 */
        *ps = ((uint16_t)(buf[5] & 0X3F) << 4) | (buf[4] & 0X0F);
    }
}
该函数用于读取AP3216C传感器的ALS+PS+IR数据。通过调用ap3216c_read_data函数读取相关寄存器的值,然后判断数据有效位,再整合得到IR值、ALS值、PS值。
25.3.4 CMakeLists.txt文件
打开本实验BSP下的CMakeLists.txt文件,其内容如下所示:
set(src_dirs
            AP3216C
            IIC
            LCD
            LED
            SPI
            XL9555)
set(include_dirs
            AP3216C
            IIC
            LCD
            LED
            SPI
            XL9555)
set(requires
            driver)
idf_component_register(SRC_DIRS ${src_dirs}
INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})
component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)
上述的红色AP3216C驱动需要由开发者自行添加,以确保AP3216C驱动能够顺利集成到构建系统中。这一步骤是必不可少的,它确保了AP3216C驱动的正确性和可用性,为后续的开发工作提供了坚实的基础。
25.3.5 实验应用代码
打开main/main.c文件,该文件定义了工程入口函数,名为app_main。该函数代码如下。
i2c_obj_t i2c0_master;
/**
* @brief       程序入口
* @param      
* @retval      
*/
void app_main(void)
{
    uint16_t ir, als, ps;
    esp_err_t ret;
   
    ret = nvs_flash_init();                                           /* 初始化NVS */
if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
            ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    led_init();                                                       /* 初始化LED */
    i2c0_master = iic_init(I2C_NUM_0);                          /* 初始化IIC0 */
    spi2_init();                                                /* 初始化SPI2 */
    xl9555_init(i2c0_master);                                   /* 初始化XL9555 */
    lcd_init();                                                 /* 初始化LCD */
    ap3216c_init(i2c0_master);                                  /* 初始化AP3216C */
    lcd_show_string(30, 50, 200, 16, 16, "ESP32", RED);
    lcd_show_string(30, 70, 200, 16, 16, "AP3216C TEST", RED);
    lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    lcd_show_string(30, 130, 200, 16, 16, "AP3216C Ready!", RED);
    lcd_show_string(30, 150, 200, 16, 16, "IR :", RED);
    lcd_show_string(30, 170, 200, 16, 16, "PS :", RED);
    lcd_show_string(30, 190, 200, 16, 16, "ALS:", RED);
    while(1)
    {
        ap3216c_read_data(&ir, &ps, &als);                      /* 读取数据  */
        lcd_show_num(30 + 40, 150, ir, 5, 16, BLUE);            /* 显示IR数据 */
        lcd_show_num(30 + 40, 170, ps, 5, 16, BLUE);            /* 显示PS数据 */
        lcd_show_num(30 + 40, 190, als, 5, 16, BLUE);           /* 显示ALS数据  */
        LED_TOGGLE();                                           /* 提示系统正在运行 */
        vTaskDelay(200);
    }
}
app_main函数中,完成一系列外设初始化后,调用ap3216c_init函数完成AP3216C初始化,LCD显示IRPSALS信息。在while循环中,间隔200毫秒调用ap3216c_read_data函数获取AP3216C传感器的IRPSALS数据,然后在LCD进行显示。
25.4 下载验证
程序下载成功后,LCD会显示光环境传感器的ALS+PS+IR数据,同时,LED闪烁,提示系统正在运行,并且串口打印实验现象。
大家可以用手遮挡/靠近AP3216C传感器,可以看到三个传感器的数据变化,说明我们的代码是正常的。
第二十五章 IIC10607.png
25.4.1 SPI LCD显示效果图

更多回帖

×
20
完善资料,
赚取积分