先叠甲下,个人在学习单片机开发,有很多不足之处请见谅。其次APDS-9930我在开发中发现虽然有环境光检测(ALS)但是无论是按照官方文档还是按照普通写法,环境光检测都不准,但是我只需要9930的接近检测。所以暂时就开发到这里了,环境光检测我用的GY-30的BH1750FVI开发的。
#ifndef _distance_H_
#define _distance_H_
#include "myiic.h" //
#define APDS9930_ADDR 0x39 // APDS-9930 的I2C地址
//APDS-9930寄存器地址
//ALS :环境光检测
//Ch0 光电二极管 可见光加红外
//Ch1 红外响应(IR)光电二极管
/*
APDS-9930 通过使用两个光电二极管解决了这个问题。其
中一个光电二极管称为 Ch0 通道,对可见光和红外光都敏
感,而第二个光电二极管主要对红外光敏感。两个积分
ADC 将光电二极管电流转换为数字输出。ch1 数据数字值
用于补偿光的红外成分对 ch0 数据数字值的影响。两个通
道的 ADC 数字输出用于一个公式,以获得一个近似于人眼
响应的值(单位为勒克斯)。
*/
#define APDS9930_ENABLE 0x80
#define APDS9930_ATIME 0x81
#define APDS9930_PTIME 0x82
#define APDS9930_WTIME 0x83
#define APDS9930_AILTL 0x84
#define APDS9930_AILTH 0x85
#define APDS9930_AIHTL 0x86
#define APDS9930_AIHTH 0x87
#define APDS9930_PILTL 0x88 //接近中断低阈值低字节
#define APDS9930_PILTH 0x89 //接近中断低阈值高字节
#define APDS9930_PIHTL 0x8A //接近中断高阈值低字节
#define APDS9930_PIHTH 0x8B //接近中断高阈值高字节
#define APDS9930_PERS 0x8C
#define APDS9930_CONFIG 0x8D //配置寄存器
#define APDS9930_PPULSE 0x8E //接近脉冲计数
#define APDS9930_CONTROL 0x8F //增益控制寄存器
#define APDS9930_ID 0x92
#define APDS9930_STATUS 0x93
#define APDS9930_CH0DATAL 0x94
#define APDS9930_CH0DATAH 0x95
#define APDS9930_CH1DATAL 0x96
#define APDS9930_CH1DATAH 0x97
#define APDS9930_PDATAL 0x98
#define APDS9930_PDATAH 0x99
#define APDS9930_POFFSET 0x9E
// 函数声明
uint16_t Max(uint16_t a,uint16_t b);
void APDS9930_Init(void);
//uint16_t APDS9930_ReadALSData(uint8_t regAddress);
uint16_t APDS9930_ReadAmbientLight(void);
uint16_t APDS9930_ReadProximity(void);
#endif
#include "distance.h"
#include "delay.h"
/*
uint8 ATIME, PIME, WTIME, PPULSE;
ATIME = 0xff; // 2.7 ms – minimum ALS integration time 最短ALS积分时间
PTIME = 0xff; // 2.7 ms – minimum Prox integration time 最短Prox积分时间
WTIME = 0xff; // 2.7 ms – minimum Wait time 最短等待时间
PPULSE = 1; // Minimum prox pulse count 最小接近脉冲计数
WriteRegData(0, 0); //Disable and Powerdown 禁用和关闭
WriteRegData (1, ATIME);
WriteRegData (2, PTIME);
WriteRegData (3, WTIME);
WriteRegData (0xe, PPULSE);
uint8 PDRIVE, PDIODE, PGAIN, AGAIN;
PDRIVE = 0; //100mA of LED Power 100mA的LED电源
PDIODE = 0x20; // CH1 Diode
PGAIN = 0; //1x Prox gain 1倍接近增益
AGAIN = 0; //1x ALS gain 1倍ALS增益
WriteRegData (0xf, PDRIVE | PDIODE | PGAIN | AGAIN);
uint8 WEN, PEN, AEN, PON;
WEN = 8; // Enable Wait 启用等待
PEN = 4; // Enable Prox 启用接近
AEN = 2; // Enable ALS 启用ALS
PON = 1; // Enable Power On 启用开机
WriteRegData (0, WEN | PEN | AEN | PON); // WriteRegData(0,0x0f);
Wait(12); //Wait for 12 ms 等待12ms
int CH0_data, CH1_data, Prox_data;
CH0_data = Read_Word(0x14);
CH1_data = Read_Word(0x16);
Prox_data = Read_Word(0x18);
WriteRegData(uint8 reg, uint8 data)
{
m_I2CBus.WriteI2C(0x39, 0x80 | reg, 1, &data);
}
uint16 Read_Word(uint8 reg);
{
uint8 barr[2];
m_I2CBus.ReadI2C(0x39, 0xA0 | reg, 2, ref barr);
return (uint16)(barr[0] + 256 * barr[1]);
}
*/
uint16_t Max(uint16_t a,uint16_t b)
{
return (a > b) ? a : b;
}
void APDS9930_Init(void)
{
//APDS9930_CONTROL的地址0x0F中的8个位组成,从高位到地位,每个变量占用2个位
u8 PDRIVE, PDIODE, PGAIN, AGAIN;
//APDS9930_ENABLE的地址0x00中的8个位组成,从高位到地位,分别是Reserved,SAI,PIEN,AIEN,WEN,PEN,AEN,PON
//定义低四位:WEN,等待使能。 PEN,接近启用。 AEN,ALS启用。 PON,打开电源。 置0屏蔽,置1启用
//PIEN和AIEN分别是接近中断和ALS中断,置0屏蔽,置1启用
//SAI是中断后睡眠。置0屏蔽,置1启用
u8 WEN, PEN, AEN, PON;
IIC_Init(); // 初始化I2C接口
// 关闭器件
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_ENABLE, 0x00);
delay_ms(10);
// 设置ALS积分时间(例如设置为200ms)
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_ATIME, 0xC0); //AI给的0xEB,自己查询0xC0(175ms)
// 设置接近检测脉冲宽度(例如设置为16us)
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_PTIME, 0xFF); //AI给的0x01,自己查询的0xFF(2.73ms)
// 设置接等待时间(例如设置为2.73ms)
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_WTIME, 0xFF); //2.73ms
// 接近脉冲计数寄存器(PPULSE = 0x01 Minimum Prox Pulse Count 最小接近脉冲计数)
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_PPULSE, 0x01); //2.73ms
// 设置LED电流(例如设置为100mA),接近使用CH1二极管,1倍接近增益,1倍ALS增益
PDRIVE = 0; //100mA of LED Power 100mA的LED电源。00是100mA,01是50mA,10是25mA,11是12.5mA
PDIODE = 0x20; // CH1 Diode 接近使用CH1二极管
PGAIN = 0; //1x Prox gain 1倍接近增益。00是1倍,01是2倍,10是4倍,11是8倍
AGAIN = 0; //1x ALS gain 1倍ALS增益。00是1倍,01是8倍,10是16倍,11是120倍
//APDS9930_CONTROL的地址0x0F中由8个位(bit)组成,从高位到地位分别是PDRIVE PDIODE PGAIN AGAIN,每个占用2个bit
//例如:0b01100101也是0x65送到0x0F中,就表示LED电流50mA,接近使用CH1二极管,2倍接近增益,8倍ALS增益
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_CONTROL, PDRIVE | PDIODE | PGAIN | AGAIN);
// 设置中断阈值(默认全量程)
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_AILTL, 0x00);
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_AILTH, 0xFF);
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_AIHTL, 0x00);
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_AIHTH, 0xFF);
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_PILTL, 0x00);
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_PILTH, 0xFF);
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_PIHTL, 0x00);
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_PIHTH, 0xFF);
// 启用 ALS 和 Proximity 功能,同时禁用中断并打开电源
WEN=0x08; //1000 参考66行
PEN=0x04; //0100
AEN=0x02; //0010
PON=0x01; //0001
IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_ENABLE, WEN|PEN|AEN|PON);
//IIC_Write_One_Byte(APDS9930_ADDR, APDS9930_ENABLE, 0x0F); //同上
delay_ms(12); // 延时等待器件稳定
}
// 获取环境光亮度
//uint16_t APDS9930_ReadALSData(uint8_t regAddress)
//{
// uint16_t result;
// uint16_t resultH;
// IIC_Start();
// IIC_Send_Byte(APDS9930_ADDR << 1); // 注意此处是写地址
// IIC_Wait_Ack();
// IIC_Send_Byte(regAddress);
// IIC_Wait_Ack();
// IIC_Start();
// IIC_Send_Byte((APDS9930_ADDR << 1) | 0x01); // 注意此处是读地址
// IIC_Wait_Ack();
// result = IIC_Read_Byte(1) & 0xFF; //读取到低位
// resultH = IIC_Read_Byte(0) & 0xFF;
// IIC_Stop();
// //CH0DATA = 256 * Ch0DATAH (r0x15) + Ch0DATAL (r0x14)
// //CH1DATA = 256 * Ch1DATAH (r0x17) + Ch1DATAL (r0x16)
// result |= ((resultH * 256) << 8); //读取到的值左移8位变成高位
// return result ;
//}
//uint16_t APDS9930_ReadAmbientLight(void)
//{
// uint16_t ambient_light,CH0DATA,CH1DATA,IAC1,IAC2,IAC;
//
// /*
// ALSIT = 2.73 ms * (256 – ATIME)
// ALSIT = 2.73 * (256 - 2.73)
// ALSIT = 691
// AGAIN = 1
// LPC = GA x DF / (ALSIT × AGAIN)
// LPC = 0.49 x 52 / (691 x 1)
// LPC = 0.036
//
// DF = 52 for APDS-9930
// GA = 0.49
// B = 1.862
// C = 0.746
// D = 1.291
//
// IAC1 = CH0DATA – B x CH1DATA
// IAC2 = C x CH0DATA – D x CH1DATA
// IAC = Max (IAC1, IAC2, 0)
// LPC = GA x DF / (ALSIT × AGAIN)
// Lux = IAC x LPC
//*/
// CH0DATA = APDS9930_ReadALSData(APDS9930_CH0DATAL);
// CH1DATA = APDS9930_ReadALSData(APDS9930_CH1DATAL);
//
// IAC1 = CH0DATA - 1.862f * CH1DATA;
// IAC2 = 0.746f * CH0DATA - 1.291f * CH1DATA;
// IAC = Max(IAC1,IAC2);
//
// ambient_light = IAC * 0.036f;
// return ambient_light;
//}
uint16_t APDS9930_ReadAmbientLight(void)
{
uint16_t ambient_light;
IIC_Start();
IIC_Send_Byte(APDS9930_ADDR << 1);
IIC_Wait_Ack();
IIC_Send_Byte(APDS9930_CH0DATAL); //0x14
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte((APDS9930_ADDR << 1) | 0x01);
IIC_Wait_Ack();
ambient_light = IIC_Read_Byte(1) & 0xFF;
ambient_light |= (IIC_Read_Byte(0) << 8);
IIC_Stop();
return ambient_light;
}
// 获取接近感应值
uint16_t APDS9930_ReadProximity(void)
{
uint16_t proximity;
IIC_Start();
IIC_Send_Byte(APDS9930_ADDR << 1);
IIC_Wait_Ack();
IIC_Send_Byte(APDS9930_PDATAL);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte((APDS9930_ADDR << 1) | 0x01);
IIC_Wait_Ack();
proximity = IIC_Read_Byte(1) & 0xFF;
proximity |= (IIC_Read_Byte(0) << 8);
IIC_Stop();
return proximity;
}