1199 字
6 分钟
STM32中的I2C通信【AP3216C光传感器】
AP3216C
简介
AP3216C 是敦南科技推出的一款三合一环境传感器, 它包含了:数字环境光传感器(ALS)、接近传感器(PS)和一个红外 LED(IR)。该芯片通过 IIC 接口和 MCU 连接,并支持中断(INT)输出。AP3216C 的特点如下:
- IIC 接口,支持高达 400KHz 通信速率
- 支持多种工作模式(ALS、PS+IR、ALS+PS+IR 等)
- 内置温度补偿电路
- 工作温度支持-30~80℃
- 环境光传感器具有 16 位分辨率
- 接近传感器具有 10 位分辨率
- 红外传感器具有 10 位分辨率
- 超小封装(4.12.41.35mm)
因为以上一些特性,AP3216C 被广泛应用于智能手机上面,用来检测光强度(自动背光控制),和接近开关控制(听筒靠近耳朵,手机自动灭屏功能)。
写寄存器
先发送 AP3216C 的地址(7 位,为0X1E,左移一位后为 0X3C),最低位 W=0 表示写数据,随后发送 8 位寄存器地址,最后发送 8 位寄存器值。其中:S,表示 IIC 起始信号;W,表示读/写标志位(W=0 表示写,W=1 表示读);A,表示应答信号;P,表示 IIC 停止信号。
读寄存器

注意:AP3216C的读取间隔至少需要大于112.5ms(一次ALS+PS+IR转换的时间)
工程
ap3216c.h
#include "sys.h" #include "main.h"
#ifndef __AP3216C_H #define __AP3216C_H
#define AP3216C_ADDR 0x3C /* 原设备地址为0x1E,左移一位为0x3C*/
#endif
uint8_t ap3216c_init(void); uint8_t ap3216c_write_one_byte(uint8_t reg, uint8_t data); uint8_t ap3216c_read_one_byte(uint8_t reg); void ap3216c_read_data(uint16_t *ir, uint16_t *ps, uint16_t *als);ap3216c.c
#include "main.h" #include "sys.h" #include "ap3216c.h" #include "custom_i2c.h" #include "delay.h"
/*** @brief 初始化 AP3216C* @param 无* @retval 返回值:0,初始化成功; 1,初始化失败*/uint8_t ap3216c_init(void){ uint8_t temp = 0; iic_init();
ap3216c_write_one_byte(0x00, 0x04); /* 软复位AP3216C */ delay_ms(50); /* IC复位至少需要11.5ms */ ap3216c_write_one_byte(0x00, 0x03); /* ALS+PS+IR功能激活 */ temp = ap3216c_read_one_byte(0x00); /* 读取刚刚写入的0x03指令 */ if (temp == 0x03) return 0; /* IC初始化成功 */ else return 1; /* IC初始化失败 */}
/*** @brief AP3216C 写入一个字节* @param reg : AP3216C目标寄存器地址* @param data : 待写入数据* @retval 0, 成功; 1, 失败;*/uint8_t ap3216c_write_one_byte(uint8_t reg, uint8_t data){ iic_start();
iic_send_byte(AP3216C_ADDR | 0x00); /* 发送设备地址,最低位为0,写命令 */
if (iic_wait_ack()) /* 等待应答*/ { iic_stop(); /* 等待应答失败则直接停机 */ return 1; }
iic_send_byte(reg); /* 发送目标寄存器地址(指针)*/ iic_wait_ack(); /* 等待应答 */ iic_send_byte(data); /* 发送待写入数据 */
if (iic_wait_ack()) /* 等待应答*/ { iic_stop(); /* 等待应答失败则直接停机 */ return 1; }
iic_stop(); return 0;}
/*** @brief AP3216C 读取一个字节* @param reg : 待读取寄存器地址* @retval 读到的数据*/uint8_t ap3216c_read_one_byte(uint8_t reg){ uint8_t result;
iic_start();
iic_send_byte(AP3216C_ADDR | 0x00); /* 发送设备地址,最低位为0,写命令*/ iic_wait_ack();
iic_send_byte(reg); /* 发送待读取寄存器地址 */ iic_wait_ack();
iic_start(); /* 准备开始读取,重新启动IIC以切换模式 */ iic_send_byte(AP3216C_ADDR | 0x01); /* 发送设备地址,最低位为1,读命令*/ iic_wait_ack(); result = iic_read_byte(0); /* 读取一个字节,读完后发送NACK,表示读取结束 */ iic_stop();
return result; /* 返回读取结果 */}
/*** @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 rx_buf[6]; /* 读取缓冲区 */ uint8_t i;
for (i = 0; i < 6; i++) /* 循环6次以读取6个寄存器的值 */ { rx_buf[i] = ap3216c_read_one_byte(0x0A + i); }
/* 提取IR传感器值 */ if (rx_buf[0] & 0x80) /* 判断IR第7位是否为1 */ { *ir = 0; /* 第7位若为1则IR数据无效 */ } else { /* rx_buf[1] << 2:0x0B(IR高位)数据左移2位,给低位数据留出空余*/ /* rx_buf[0] & 0x03:提取0x0A(IR低位)数据的第0位和第1位,也就是IR的最低2位*/ /* 二者进行或运算得到IR的最终值 */ *ir = ((uint16_t)rx_buf[1] << 2) | (rx_buf[0] & 0x03); }
/* 提取ALS传感器值 */ *als = rx_buf[2] | ((uint16_t)rx_buf[3] << 8);
/* 提取PS传感器值 */ if (rx_buf[4] & 0x40) /* 判断0x0E第6位是否为1*/ { *ps = 0; /* PS数据无效 */ } else { /* (rx_buf[4] & 0x0F):取0x0E的3:0位,也就是PS的低4位 */ /* ((uint16_t)(rx_buf[5] & 0x3F) << 4):取0x0F的5:0位然后左移4位,给低4位留位置 */ /* 二者进行或运算得到PS的最终值 */ *ps = ((uint16_t)(rx_buf[5] & 0x3F) << 4) | (rx_buf[4] & 0x0F); }}main.c
/* USER CODE BEGIN 2 */ while (ap3216c_init()) /* AP3216C初始化失败 */ { uint8_t txbuf[] = "ap3216c init failed!\n"; HAL_UART_Transmit_IT(&huart1, txbuf, sizeof(txbuf)); led_red(1); } /* USER CODE END 2 */while (1) { /* USER CODE END WHILE */ ap3216c_read_data(&ir, &ps, &als);
uint8_t txbuf[23];
sprintf(txbuf, "ir:%d, ps:%d, als:%d\r\n", ir, ps, als); HAL_UART_Transmit_IT(&huart1, (uint8_t *)txbuf, sizeof(txbuf));
led_green_toggle(); delay_ms(120); /* 延时120ms以保证AP3216C采样正确 */ /* USER CODE BEGIN 3 */
}测试

STM32中的I2C通信【AP3216C光传感器】
https://arkmostima.pages.dev/posts/stm32中的i2c通信ap3216c光传感器/