動態

詳情 返回 返回

《ESP32-S3使用指南—IDF版 V1.6》第二十五章 IIC_AP3216C實驗 - 動態 詳情

第二十五章 IIC_AP3216C實驗

1)實驗平台:正點原子DNESP32S3開發板

2)章節摘自【正點原子】ESP32-S3使用指南—IDF版 V1.6

3)購買鏈接:https://detail.tmall.com/item.htm?&id=768499342659

4)全套實驗源碼+手冊+視頻下載地址:http://www.openedv.com/docs/boards/esp32/ATK-DNESP32S3.html

5)正點原子官方B站:https://space.bilibili.com/394620890

6)正點原子DNESP32S3開發板技術交流羣:132780729

本章,我們將繼續使用ESP32-S3的硬件IIC接口去驅動AP3216C傳感器,檢測環境光強度(ALS)、接近距離(PS)和紅外線強度(IR)等環境參數。本章分為如下幾個小節:
本章分為如下幾個小節:
25.1 AP3216C簡介
25.2 硬件設計
25.3 程序設計
25.4 下載驗證

25.1 AP3216C介紹

AP3216C是敦南科技推出的一款三合一環境傳感器, 包含了:數字環境光傳感器(ALS)、接近傳感器(PS)和一個紅外LED(IR)。該芯片通過IIC接口和MCU連接,並支持中斷(INT)輸出。AP3216C實物圖如下圖所示:

圖25.1.1 AP3216C實物圖

AP3216C的特點如下:
l IIC接口,支持高達400KHz通信速率
l 支持多種工作模式(ALS、PS+IR、ALS+PS+IR等)
l 內置温度補償電路
l 工作温度支持-30~80℃
l 環境光傳感器具有16位分辨率
l 接近傳感器具有10位分辨率
l 紅外傳感器具有10位分辨率
l 超小封裝(4.12.41.35mm)
因為以上一些特性,AP3216C被廣泛應用於智能手機上面,用來檢測光強度(自動背光控制),和接近開關控制(聽筒靠近耳朵,手機自動滅屏功能)。
AP3216C的框圖如下圖所示。

圖25.1.2 AP3216C框圖

AP3216C的引腳説明如下表所示。

表25.1.1 AP3216C引腳説明

AP3216C和主控芯片只需要連接SCL、SDA和INT,就可以實現驅動。其SCL和SDA同24C02、XL9555共用,連接在IO41和IO42上,INT腳連接在XL9555的P0_0上。

25.1.1 AP3216C尋址

要進行IIC通信,首先得知道器件地址,AP3216C器件地址是7位的,具體格式如下表。

表25.1.1.1 AP3216C地址格式

AP3216C器件地址為“0011110”即0x1E。讀操作地址就為0x3D(0x1E<< 1 | 0x1),即0011 1101;寫操作地址就為0x3C(0x1E<< 1 | 0x0),即0011 1100。

25.1.2 AP3216C寄存器介紹

AP3216C有一系列寄存器,由這些寄存器來控制AP3216C的工作模式,以及中斷配置和數據輸出等。這裏我們僅介紹在本章需要用到的一些寄存器,其他寄存器的描述和説明,請大家參考AP3216C的數據手冊。本章需要用到AP3216C的寄存器如下表所示。

表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的寫寄存器時序如下圖所示。

圖25.1.3.1 AP3216C寫寄存器時序

圖中,先發送AP3216C的寫操作地址0x3C(器件地址0X1E << 1 | 讀寫位0x0),隨後發送8位寄存器地址,最後發送8位寄存器值。其中:S,表示IIC起始信號;W,表示讀/寫標誌位(W=0表示寫,W=1表示讀);A,表示應答信號;P,表示IIC停止信號。
讀寄存器時序圖
AP3216C的讀寄存器時序如下圖所示。

圖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_SET和LCD_DC相連)
PWR- IO1_3(XL9555)
RST- IO1_2(XL9555)
4.AP3216C
IIC_SDA-IO41
IIC_SCL-IO42
AP_INT-IO0_0(XL9555)

25.2.3 原理圖

AP3216C相關原理圖,如下圖所示。

圖25.2.3.1 AP3216C原理圖

這裏説明一下,AP3216C的AP_INT腳是連接在XL9555器件的IO0_0腳上,如果大家要使用AP3216C的中斷輸出功能,必須先初始化XL9555器件並配置IO0_0為輸入功能,監測XL9555中斷引腳是否有中斷產生。若發現有中斷產生,則判斷是否是IO0_0導致的,從而檢測到AP3216C的中斷。在本章中,並沒有用到AP3216C中斷功能,所以沒有對XL9555器件的IO0_0做設置。

25.3 程序設計

25.3.1 程序流程圖

程序流程圖能幫助我們更好的理解一個工程的功能和實現的過程,對學習和設計工程有很好的主導作用。下面看看本實驗的程序流程圖:

圖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)

該函數的形參描述,如下表所示:

表25.3.2.1 函數ap3216c_write_one_byte ()形參描述

返回值:ESP_OK表示配置成功。其他表示配置失敗。
2,讀取開啓ALS和PS+IR指令
該函數用於復位AP3216C,並封裝在ap3216c_comfig()函數中,其函數原型如下所示:

esp_err_t ap3216c_read_one_byte(uint8_t* data, uint8_t reg)

該函數的形參描述,如下表所示:

表25.3.2.2 函數ap3216c_read_one_byte ()形參描述

返回值:ESP_OK表示復位成功。其他表示復位失敗。
該函數通過一個指向數據存儲區的指針再配合一寄存器地址的方式來讀取之前寫入系統配置寄存器的值0x03,通過判斷寄存器是否寫入了0x03來決定AP3216C的初始化是否真正完成。

25.3.3 IIC_AP3216C驅動解析

在IDF版15_ap3216c例程中,作者在15_ap3216c\components\BSP路徑下新增了一個AP3216C文件夾,分別用於存放ap3216c.c、ap3216c.h這兩個文件。其中,ap3216c.h文件負責聲明AP3216C相關的函數和變量,而ap3216c.c文件則實現了AP3216C的驅動代碼。下面,我們將詳細解析這兩個文件的實現內容。
1,ap3216c.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。
2,ap3216c.c文件

/**
*@brief       讀取ap3216c的16位IO值
*@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寫入16位IO值
*@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);     /* 開啓ALS、PS+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_byte對AP3216C進行軟件復位,然後開啓光強度ALS、接近距離PS和紅外線強度IR功能檢測。後面再通過調用該ap3216c_read_one_byte函數讀一下剛剛寫入的配置參數看是否正常寫入,以此作為判斷AP3216C是否正常的依據。
至於軟件復位為什麼要傳入0x00和0x04,我們通過查找數據手冊能夠知道:

圖25.3.3.1形參值的具體描述

上圖所示的便是復位AP3216C的指令通過簡單的二進制向十六進制轉換而得出。
同樣地,我們通過查看數據手冊也能得到,復位結束後需要寫入開啓ALS和PS+IR指令,如下圖所示:

圖25.3.3.2形參值的具體描述

初始化好AP3216C傳感器之後,就可以對其採集到的數據進行獲取,實現這個讀取過程的函數為ap3216c_read_data,代碼如下:

/**
* @brief   讀取AP3216C的數據
* @note    讀取原始數據,包括ALS,PS和IR
*           如果同時打開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顯示IR、PS、ALS信息。在while循環中,間隔200毫秒調用ap3216c_read_data函數獲取AP3216C傳感器的IR、PS和ALS數據,然後在LCD進行顯示。

25.4 下載驗證

程序下載成功後,LCD會顯示光環境傳感器的ALS+PS+IR數據,同時,LED閃爍,提示系統正在運行,並且串口打印實驗現象。
大家可以用手遮擋/靠近AP3216C傳感器,可以看到三個傳感器的數據變化,説明我們的代碼是正常的。

圖25.4.1 SPI LCD顯示效果圖

user avatar gedyh 頭像 qeasy_cloud 頭像 chongdongdeludeng 頭像
點贊 3 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.