STM32F103C8T6开发APDS-9930程序

        先叠甲下,个人在学习单片机开发,有很多不足之处请见谅。其次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;
}

  

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值