STM32H750XB_RT-THREAD/I2C—AP3216C(光照三合一)/3.AP3216C全功能例程_(硬件I2C)/User/ap3216c/ap3216c.c

569 lines
14 KiB
C
Raw Permalink Normal View History

2025-07-21 06:34:29 +00:00
/**
******************************************************************************
* @file ap3216.c
* @author fire
* @version V1.0
* @date 2019-xx-xx
* @brief AP3216C <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
******************************************************************************
* @attention
*
* ʵ<EFBFBD><EFBFBD>ƽ̨:Ұ<EFBFBD><EFBFBD> STM32 H750 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD>̳ :http://www.firebbs.cn
* <EFBFBD>Ա<EFBFBD> :http://firestm32.taobao.com
*
******************************************************************************
*/
#include "./ap3216c/ap3216c.h"
#include "./i2c/bsp_i2c.h"
#include "./delay/core_delay.h"
#define PKG_USING_AP3216C
#ifdef PKG_USING_AP3216C
//System Register
#define AP3216C_SYS_CONFIGURATION_REG 0x00 //default
#define AP3216C_SYS_INT_STATUS_REG 0x01
#define AP3216C_SYS_INT_CLEAR_MANNER_REG 0x02
#define AP3216C_IR_DATA_L_REG 0x0A
#define AP3216C_IR_DATA_H_REG 0x0B
#define AP3216C_ALS_DATA_L_REG 0x0C
#define AP3216C_ALS_DATA_H_REG 0x0D
#define AP3216C_PS_DATA_L_REG 0x0E
#define AP3216C_PS_DATA_H_REG 0x0F
//ALS Register
#define AP3216C_ALS_CONFIGURATION_REG 0x10 //range 5:4,persist 3:0
#define AP3216C_ALS_CALIBRATION_REG 0x19
#define AP3216C_ALS_THRESHOLD_LOW_L_REG 0x1A //bit 7:0
#define AP3216C_ALS_THRESHOLD_LOW_H_REG 0x1B //bit 15:8
#define AP3216C_ALS_THRESHOLD_HIGH_L_REG 0x1C //bit 7:0
#define AP3216C_ALS_THRESHOLD_HIGH_H_REG 0x1D //bit 15:8
//PS Register
#define AP3216C_PS_CONFIGURATION_REG 0x20
#define AP3216C_PS_LED_DRIVER_REG 0x21
#define AP3216C_PS_INT_FORM_REG 0x22
#define AP3216C_PS_MEAN_TIME_REG 0x23
#define AP3216C_PS_LED_WAITING_TIME_REG 0x24
#define AP3216C_PS_CALIBRATION_L_REG 0x28
#define AP3216C_PS_CALIBRATION_H_REG 0x29
#define AP3216C_PS_THRESHOLD_LOW_L_REG 0x2A //bit 1:0
#define AP3216C_PS_THRESHOLD_LOW_H_REG 0x2B //bit 9:2
#define AP3216C_PS_THRESHOLD_HIGH_L_REG 0x2C //bit 1:0
#define AP3216C_PS_THRESHOLD_HIGH_H_REG 0x2D //bit 9:2
#define AP3216C_ADDR 0x1e /*0x3c=0x1e<<1*/ // AP3216C <20><> 7 λ<><CEBB>ַ
#define AP3216C_ERROR I2C_ERROR
#define AP3216C_INFO I2C_INFO
/* д<>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ */
static void write_reg(uint8_t reg, uint8_t data)
{
Sensors_I2C_WriteRegister(AP3216C_ADDR << 1, reg, 1, &data);
}
/* <20><><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ֵ */
static void read_regs(uint8_t reg, uint8_t len, uint8_t *buf)
{
Sensors_I2C_ReadRegister(AP3216C_ADDR << 1, reg, len, buf);
}
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
static void reset_sensor(void)
{
write_reg(AP3216C_SYS_CONFIGURATION_REG, AP3216C_MODE_SW_RESET); //reset
}
/**
* This function is convenient to getting data except including high and low data for this sensor.
* note:after reading lower register first,reading higher add one.
*/
static uint32_t read_low_and_high(uint8_t reg, uint8_t len)
{
uint32_t data;
uint8_t buf = 0;
read_regs( reg, len, &buf); // <20><><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD>
data = buf;
read_regs( reg + 1, len, &buf); // <20><><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD>
data = data + (buf << len * 8); // <20>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD>
return data;
}
/**
* This function is only used to set threshold without filtering times
*
* @param cmd first register , and other cmd count by it.
* @param threshold threshold and filtering times of als threshold
*/
static void set_als_threshold(ap3216c_cmd_t cmd, ap3216c_threshold_t threshold)
{
uint8_t Resolution;
double DB;
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǿ<EFBFBD>ȵķ<C8B5>Χ */
ap3216c_get_param(AP3216C_ALS_RANGE, &Resolution);
if (Resolution == AP3216C_ALS_RANGE_20661) // <20><><EFBFBD><EFBFBD>ǿ<EFBFBD>ȷ<EFBFBD>Χ 0 - 20661
{
DB = 0.35; // <20><><EFBFBD><EFBFBD>ǿ<EFBFBD>ȵķֱ<C4B7><D6B1><EFBFBD>
}
else if (Resolution == AP3216C_ALS_RANGE_5162) // <20><><EFBFBD><EFBFBD>ǿ<EFBFBD>ȷ<EFBFBD>Χ 0 - 5162
{
DB = 0.0788; // <20><><EFBFBD><EFBFBD>ǿ<EFBFBD>ȵķֱ<C4B7><D6B1><EFBFBD>
}
else if (Resolution == AP3216C_ALS_RANGE_1291) // <20><><EFBFBD><EFBFBD>ǿ<EFBFBD>ȷ<EFBFBD>Χ 0 - 1291
{
DB = 0.0197; // <20><><EFBFBD><EFBFBD>ǿ<EFBFBD>ȵķֱ<C4B7><D6B1><EFBFBD>
}
else if (Resolution == AP3216C_ALS_RANGE_323) // <20><><EFBFBD><EFBFBD>ǿ<EFBFBD>ȷ<EFBFBD>Χ 0 - 323
{
DB = 0.0049; // <20><><EFBFBD><EFBFBD>ǿ<EFBFBD>ȵķֱ<C4B7><D6B1><EFBFBD>
}
threshold.min /= DB; // <20><><EFBFBD>ݲ<EFBFBD>ͬ<EFBFBD>ķֱ<C4B7><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
threshold.max /= DB;
ap3216c_set_param(cmd, (threshold.min & 0xff));
ap3216c_set_param((ap3216c_cmd_t)(cmd + 1), (threshold.min >> 8));
ap3216c_set_param((ap3216c_cmd_t)(cmd + 2), (threshold.max & 0xff));
ap3216c_set_param((ap3216c_cmd_t)(cmd + 3), threshold.max >> 8);
}
static void set_ps_threshold(ap3216c_cmd_t cmd, ap3216c_threshold_t threshold)
{
if (threshold.min > 1020) // <20><><EFBFBD><EFBFBD>1020 ʱ<><CAB1>Ҫ<EFBFBD><D2AA><EFBFBD>õ<EFBFBD><C3B5>ֽڵĵ<DAB5><C4B5><EFBFBD>λ
ap3216c_set_param(cmd, (threshold.min - 1020 & 0x03));
ap3216c_set_param((ap3216c_cmd_t)(cmd + 1), threshold.min/4); // <20><><EFBFBD>ø<EFBFBD><C3B8>ֽڲ<D6BD><DAB2><EFBFBD>
if (threshold.max > 1020) // <20><><EFBFBD><EFBFBD>1020 ʱ<><CAB1>Ҫ<EFBFBD><D2AA><EFBFBD>õ<EFBFBD><C3B5>ֽڵĵ<DAB5><C4B5><EFBFBD>λ
ap3216c_set_param((ap3216c_cmd_t)(cmd + 2), (threshold.max - 1020 & 0x03));
ap3216c_set_param((ap3216c_cmd_t)(cmd + 3), threshold.max/4); // <20><><EFBFBD>ø<EFBFBD><C3B8>ֽڲ<D6BD><DAB2><EFBFBD>
}
/**
* This function reads status register by ap3216c sensor measurement
*
* @param no
*
* @return status register value.
*/
uint8_t ap3216c_get_IntStatus(void)
{
uint8_t IntStatus;
/* <20><><EFBFBD>ж<EFBFBD>״̬<D7B4>Ĵ<EFBFBD><C4B4><EFBFBD> */
read_regs(AP3216C_SYS_INT_STATUS_REG, 1, &IntStatus);
// IntStatus <20><> 0 λ<><CEBB>ʾ ALS <20>жϣ<D0B6><CFA3><EFBFBD> 1 λ<><CEBB>ʾ PS <20>жϡ<D0B6>
return IntStatus; // <20><><EFBFBD><EFBFBD>״̬
}
static void ap3216c_int_init(void)
{
ap3216c_threshold_t threshold; // <20><><EFBFBD>ñ<EFBFBD><C3B1><EFBFBD>ֵ<EFBFBD><D6B5>ֵ<EFBFBD><EFBFBD><E1B9B9>
threshold.min = 10; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޲<EFBFBD><DEB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
threshold.max = 1000; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޲<EFBFBD><DEB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
threshold.noises_time = 1; // ALS <20><EFBFBD><EFB5BD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> threshold.noises_time * 4 <20><><EFBFBD><EFBFBD><EFBFBD>ں<EFBFBD><DABA><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> threshold.noises_time <20><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA> 15
set_als_threshold(AP3216C_ALS_LOW_THRESHOLD_L, threshold); // <20><><EFBFBD><EFBFBD> ALS <20>ı<EFBFBD><C4B1><EFBFBD>ֵ
threshold.min = 200; // PS <20><><EFBFBD><EFBFBD> 200 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
threshold.max = 500; // PS <20><><EFBFBD><EFBFBD> 500 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
set_ps_threshold(AP3216C_PS_LOW_THRESHOLD_L, threshold); // <20><><EFBFBD><EFBFBD> PS <20>ı<EFBFBD><C4B1><EFBFBD>ֵ
}
/**
* @brief <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param <EFBFBD><EFBFBD>
* @retval <EFBFBD><EFBFBD>
*/
void AP_INT_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>GPIO<49>ڵ<EFBFBD>ʱ<EFBFBD><CAB1>*/
AP_INT_GPIO_CLK_ENABLE();
/* ѡ<>񰴼<EFBFBD>1<EFBFBD><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
GPIO_InitStructure.Pin = AP_INT_GPIO_PIN;
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ģʽ */
GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ų<EFBFBD><C5B2><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
GPIO_InitStructure.Pull = GPIO_NOPULL;
/* ʹ<><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľṹ<C4BD><E1B9B9><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
HAL_GPIO_Init(AP_INT_GPIO_PORT, &GPIO_InitStructure);
}
/**
* This function initializes ap3216c registered device driver
*
* @param no
*
* @return the ap3216c device.
*/
void ap3216c_init(void)
{
I2C_Mode_Config();
/* <20>ر<EFBFBD><D8B1><EFBFBD><EFBFBD>й<EFBFBD><D0B9><EFBFBD> */
write_reg(AP3216C_SYS_CONFIGURATION_REG, 0x00);
/* reset ap3216c */
reset_sensor();
HAL_Delay(10);
ap3216c_set_param(AP3216C_SYSTEM_MODE, AP3216C_MODE_ALS_AND_PS);
// HAL_Delay(100); // delay at least 100ms
/* <20><><EFBFBD><EFBFBD><EFBFBD>жϽ<D0B6> <20><> <20>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD> */
ap3216c_int_init();
AP_INT_Config();
}
/**
* This function reads light by ap3216c sensor measurement
*
* @param no
*
* @return the ambient light converted to float data.
*/
float ap3216c_read_ambient_light(void)
{
float brightness = 0.0; // default error data
uint32_t read_data;
uint8_t temp;
read_data = read_low_and_high(AP3216C_ALS_DATA_L_REG, 1);
ap3216c_get_param(AP3216C_ALS_RANGE, &temp);
if (temp == AP3216C_ALS_RANGE_20661)
{
brightness = 0.35 * read_data; //sensor ambient light converse to reality
}
else if (temp == AP3216C_ALS_RANGE_5162)
{
brightness = 0.0788 * read_data; //sensor ambient light converse to reality
}
else if (temp == AP3216C_ALS_RANGE_1291)
{
brightness = 0.0197 * read_data; //sensor ambient light converse to reality
}
else if (temp == AP3216C_ALS_RANGE_323)
{
brightness = 0.0049 * read_data; //sensor ambient light converse to reality
}
return brightness;
}
/**
* This function reads proximity by ap3216c sensor measurement
*
* @param no
*
* @return the proximity data.
*/
uint16_t ap3216c_read_ps_data(void)
{
uint16_t proximity = 0;
uint32_t read_data;
read_data = read_low_and_high(AP3216C_PS_DATA_L_REG, 1); //read two data
if (1 == ((read_data >> 6) & 0x01 || (read_data >> 14) & 0x01))
{
return proximity = 55555; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD>IR<49><52><EFBFBD><EFBFBD>PS<50><53>Ч <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB> 55555 <20><><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>
}
proximity = (read_data & 0x000f) + (((read_data >> 8) & 0x3f) << 4); //sensor proximity converse to reality
proximity |= read_data & 0x8000; // ȡ<><C8A1><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>0 <20><>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>Զ<EFBFBD>룬1 <20><>ʾ<EFBFBD><CABE><EFBFBD>忿<EFBFBD><E5BFBF>
return proximity; // proximity <20><>ʮλ<CAAE><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λΪ״̬λ
}
/**
* This function reads ir by ap3216c sensor measurement
*
* @param no
*
* @return the ir data.
*/
uint16_t ap3216c_read_ir_data(void)
{
uint16_t proximity = 0;
uint32_t read_data;
read_data = read_low_and_high(AP3216C_IR_DATA_L_REG, 1); //read two data
proximity = (read_data & 0x0003) + ((read_data >> 8) & 0xFF); //sensor proximity converse to reality
return proximity;
}
/**
* This function sets parameter of ap3216c sensor
*
* @param cmd the parameter cmd of device
* @param value for setting value in cmd register
*
* @return the setting parameter status,RT_EOK reprensents setting successfully.
*/
void ap3216c_set_param(ap3216c_cmd_t cmd, uint8_t value)
{
switch (cmd)
{
case AP3216C_SYSTEM_MODE:
{
/* default 000,power down */
write_reg(AP3216C_SYS_CONFIGURATION_REG, value);
break;
}
case AP3216C_INT_PARAM:
{
write_reg(AP3216C_SYS_INT_CLEAR_MANNER_REG, value);
break;
}
case AP3216C_ALS_RANGE:
{
uint8_t args;
read_regs( AP3216C_ALS_CONFIGURATION_REG, 1, &args);
args &= 0xcf;
args |= value << 4;
write_reg( AP3216C_ALS_CONFIGURATION_REG, args);
break;
}
case AP3216C_ALS_PERSIST:
{
uint8_t args = 0;
read_regs(AP3216C_ALS_CONFIGURATION_REG, 1, &args);
args &= 0xf0;
args |= value;
write_reg(AP3216C_ALS_CONFIGURATION_REG, args);
break;
}
case AP3216C_ALS_LOW_THRESHOLD_L:
{
write_reg(AP3216C_ALS_THRESHOLD_LOW_L_REG, value);
break;
}
case AP3216C_ALS_LOW_THRESHOLD_H:
{
write_reg(AP3216C_ALS_THRESHOLD_LOW_H_REG, value);
break;
}
case AP3216C_ALS_HIGH_THRESHOLD_L:
{
write_reg(AP3216C_ALS_THRESHOLD_HIGH_L_REG, value);
break;
}
case AP3216C_ALS_HIGH_THRESHOLD_H:
{
write_reg(AP3216C_ALS_THRESHOLD_HIGH_H_REG, value);
break;
}
case AP3216C_PS_GAIN:
{
uint8_t args = 0;
read_regs(AP3216C_PS_CONFIGURATION_REG, 1, &args);
args &= 0xf3;
args |= value;
write_reg(AP3216C_PS_CONFIGURATION_REG, args);
break;
}
case AP3216C_PS_PERSIST:
{
uint8_t args = 0;
read_regs(AP3216C_PS_CONFIGURATION_REG, 1, &args);
args &= 0xfc;
args |= value;
write_reg(AP3216C_PS_CONFIGURATION_REG, args);
break;
}
case AP3216C_PS_LOW_THRESHOLD_L:
{
write_reg( AP3216C_PS_THRESHOLD_LOW_L_REG, value);
break;
}
case AP3216C_PS_LOW_THRESHOLD_H:
{
write_reg( AP3216C_PS_THRESHOLD_LOW_H_REG, value);
break;
}
case AP3216C_PS_HIGH_THRESHOLD_L:
{
write_reg( AP3216C_PS_THRESHOLD_HIGH_L_REG, value);
break;
}
case AP3216C_PS_HIGH_THRESHOLD_H:
{
write_reg( AP3216C_PS_THRESHOLD_HIGH_H_REG, value);
break;
}
default:
{
}
}
}
/**
* This function gets parameter of ap3216c sensor
*
* @param cmd the parameter cmd of device
* @param value to get value in cmd register
*
* @return the getting parameter status,RT_EOK reprensents getting successfully.
*/
void ap3216c_get_param(ap3216c_cmd_t cmd, uint8_t *value)
{
switch (cmd)
{
case AP3216C_SYSTEM_MODE:
{
read_regs( AP3216C_SYS_CONFIGURATION_REG, 1, value);
break;
}
case AP3216C_INT_PARAM:
{
read_regs( AP3216C_SYS_INT_CLEAR_MANNER_REG, 1, value);
break;
}
case AP3216C_ALS_RANGE:
{
uint8_t temp;
read_regs( AP3216C_ALS_CONFIGURATION_REG, 1, value);
temp = (*value & 0xff) >> 4;
*value = temp;
break;
}
case AP3216C_ALS_PERSIST:
{
uint8_t temp;
read_regs( AP3216C_ALS_CONFIGURATION_REG, 1, value);
temp = *value & 0x0f;
*value = temp;
break;
}
case AP3216C_ALS_LOW_THRESHOLD_L:
{
read_regs( AP3216C_ALS_THRESHOLD_LOW_L_REG, 1, value);
break;
}
case AP3216C_ALS_LOW_THRESHOLD_H:
{
read_regs( AP3216C_ALS_THRESHOLD_LOW_H_REG, 1, value);
break;
}
case AP3216C_ALS_HIGH_THRESHOLD_L:
{
read_regs( AP3216C_ALS_THRESHOLD_HIGH_L_REG, 1, value);
break;
}
case AP3216C_ALS_HIGH_THRESHOLD_H:
{
read_regs( AP3216C_ALS_THRESHOLD_HIGH_H_REG, 1, value);
break;
}
case AP3216C_PS_GAIN:
{
uint8_t temp;
read_regs( AP3216C_PS_CONFIGURATION_REG, 1, &temp);
*value = (temp & 0xc) >> 2;
break;
}
case AP3216C_PS_PERSIST:
{
uint8_t temp;
read_regs( AP3216C_PS_CONFIGURATION_REG, 1, &temp);
*value = temp & 0x3;
break;
}
case AP3216C_PS_LOW_THRESHOLD_L:
{
read_regs( AP3216C_PS_THRESHOLD_LOW_L_REG, 1, value);
break;
}
case AP3216C_PS_LOW_THRESHOLD_H:
{
read_regs( AP3216C_PS_THRESHOLD_LOW_H_REG, 1, value);
break;
}
case AP3216C_PS_HIGH_THRESHOLD_L:
{
read_regs( AP3216C_PS_THRESHOLD_HIGH_L_REG, 1, value);
break;
}
case AP3216C_PS_HIGH_THRESHOLD_H:
{
read_regs( AP3216C_PS_THRESHOLD_HIGH_H_REG, 1, value);
break;
}
default:
{
}
}
}
#endif /* PKG_USING_AP3216C */