本帖最后由 andeyqi 于 2019-8-8 11:26 编辑
RPR-0521RS是将光学式接近传感器和红外LED(IrLED)、数字照度传感器整合在1chip中的模块。
接近传感器 (PS)通过对IrLED发射光线的接近物产生的反射光,检测出人及物体的接近。另外,照度传感器(ALS)可测量从昏暗光线到直射日光的广泛照度。根据照度数据调整LCD显示器及按键的亮度,从而提高组件的节电性能和画面的可视性。
RPR-0521RS系列光学传感器特点: ·兼容I2C BUS接口(支持f/s模式); ·兼容1.8V逻辑接口; ·掉电模式下,电流损耗低; ·有两种ALS输出值:可见光(Data0)对应光谱响应峰值;红外线光(Data1)对应光照度计算。 ·能检测到从黑暗环境乃至直接太阳光照的环境范围,具有广泛的照度测量; ·具有抑制(工频)50Hz/60Hz光噪声(ALS功能下); ·光学接近传感探测范围在1~100mm(可通过I2C接口调整); ·内置电流配置的IrLED驱动器; ·提供卷带包装,符合RoHS欧盟标准。
RPR-0521RS系列光学传感器应用: ·智能手机 ·移动手机 ·数码相机 ·便携式游戏机 ·摄像—录影一体机 ·PDA ·LCD显示屏
模块原理图如下:
内部寄存器map如下及框图.
寄存器描述:
bit7-设置为1,bit6-设置为0即可,bit5设置脉冲宽度按照默认即可,bit4设置为为默认值bit0-3设定测量时间。
距离传感器和光照传感器模式设定。 根据官方的测试代码移植到rtthrad,测试代码如下: - #include <rtthread.h>
- #include <rtdevice.h>
- #include <board.h>
- #include <stdio.h>
- #include "finsh.h"
- #include "i2c_utilise.h"
- #include "rpr0521.h"
- unsigned short _als_data0_gain;
- unsigned short _als_data1_gain;
- unsigned short _als_measure_time;
- void rpr0521_init(void)
- {
- struct rt_i2c_bus_device* bus = NULL;
- rt_uint8_t deviceid = 0,reg = 0,partid = 0;
- rt_uint8_t buff[2] = {0};
-
- unsigned char index;
- unsigned char als_gain_table[] = {1, 2, 64, 128};
- unsigned short als_meas_time_table[] = {0,0,0,0,0,100,100,100,100,100,400,400,50,0,0,0};
-
- bus = rt_i2c_bus_device_find("i2c1");
- if(!bus)
- {
- rt_kprintf("can't find i2c device\n");
- return ;
- }
- write_cmd(bus,RPR0521RS_DEVICE_ADDRESS,RPR0521RS_SYSTEM_CONTROL);
- read_reg(bus,RPR0521RS_DEVICE_ADDRESS,1,&partid);
- if((partid&0x3f) != RPR0521RS_PART_ID_VAL)
- {
- rt_kprintf("partid is not right 0x%x\n",partid);
- return;
- }
- write_cmd(bus,RPR0521RS_DEVICE_ADDRESS,RPR0521RS_MANUFACT_ID);
- read_reg(bus,RPR0521RS_DEVICE_ADDRESS,1,®);
- if(reg != RPR0521RS_MANUFACT_ID_VAL)
- {
- rt_kprintf("manufactid is not right 0x%x\n",reg);
- return;
- }
- /* RPR0521RS_ALS_PS_CONTROL_DATA0_GAIN_X1
- RPR0521RS_ALS_PS_CONTROL_DATA1_GAIN_X1
- RPR0521RS_ALS_PS_CONTROL_LED_CURRENT_100MA
- */
- write_reg(bus,RPR0521RS_DEVICE_ADDRESS,RPR0521RS_ALS_PS_CONTROL,RPR0521RS_ALS_PS_CONTROL_VAL);
- /* set RPR0521RS_PS_CONTROL_PS_GAINX1 */
- write_cmd(bus,RPR0521RS_DEVICE_ADDRESS,RPR0521RS_PS_CONTROL);
- read_reg(bus,RPR0521RS_DEVICE_ADDRESS,1,®);
- rt_kprintf("read RPR0521RS_PS_CONTROL data is 0x%x\n",reg);
- reg |= RPR0521RS_PS_CONTROL_VAL;
- write_reg(bus,RPR0521RS_DEVICE_ADDRESS,RPR0521RS_PS_CONTROL,reg);
- rt_kprintf("write RPR0521RS_PS_CONTROL data is 0x%x\n",reg);
- /*
- RPR0521RS_MODE_CONTROL_MEASTIME_100_100MS
- RPR0521RS_MODE_CONTROL_PS_EN
- RPR0521RS_MODE_CONTROL_ALS_EN
- */
- reg = RPR0521RS_MODE_CONTROL_VAL;
- write_reg(bus,RPR0521RS_DEVICE_ADDRESS,RPR0521RS_MODE_CONTROL,reg);
-
- reg = RPR0521RS_ALS_PS_CONTROL_VAL;
- index = (reg >> 4) & 0x03;
- _als_data0_gain = als_gain_table[index];
- index = (reg >> 2) & 0x03;
- _als_data1_gain = als_gain_table[index];
- index = RPR0521RS_MODE_CONTROL_VAL & 0x0F;
- _als_measure_time = als_meas_time_table[index];
- }
- void get_rawpsalsval(unsigned char *data)
- {
- struct rt_i2c_bus_device* bus = NULL;
- rt_uint8_t status = 0;
- bus = rt_i2c_bus_device_find("i2c1");
- if(!bus)
- {
- rt_kprintf("can't find i2c device\n");
- return ;
- }
- write_cmd(bus,RPR0521RS_DEVICE_ADDRESS,RPR0521RS_PS_DATA_LSB);
- read_reg(bus,RPR0521RS_DEVICE_ADDRESS,6,data);
- }
- float convert_lx(unsigned short *data)
- {
- float lx;
- float d0, d1, d1_d0;
- if (_als_data0_gain == 0) {
- return (RPR0521RS_ERROR);
- }
- if (_als_data1_gain == 0) {
- return (RPR0521RS_ERROR);
- }
- if (_als_measure_time == 0) {
- return (RPR0521RS_ERROR);
- } else if (_als_measure_time == 50) {
- if ((data[0] & 0x8000) == 0x8000) {
- data[0] = 0x7FFF;
- }
- if ((data[1] & 0x8000) == 0x8000) {
- data[1] = 0x7FFF;
- }
- }
- d0 = (float)data[0] * (100 / _als_measure_time) / _als_data0_gain;
- d1 = (float)data[1] * (100 / _als_measure_time) / _als_data1_gain;
- if (d0 == 0) {
- lx = 0;
- return (lx);
- }
- d1_d0 = d1 / d0;
- if (d1_d0 < 0.595) {
- lx = (1.682 * d0 - 1.877 * d1);
- } else if (d1_d0 < 1.015) {
- lx = (0.644 * d0 - 0.132 * d1);
- } else if (d1_d0 < 1.352) {
- lx = (0.756 * d0 - 0.243 * d1);
- } else if (d1_d0 < 3.053) {
- lx = (0.766 * d0 - 0.25 * d1);
- } else {
- lx = 0;
- }
- return (lx);
- }
- void get_psalsval(unsigned short *ps, float *als)
- {
- unsigned char val[6];
- unsigned short rawps;
- unsigned short rawals[2];
- get_rawpsalsval(val);
- rawps = ((unsigned short)val[1] << 8) | val[0];
- rawals[0] = ((unsigned short)val[3] << 8) | val[2];
- rawals[1] = ((unsigned short)val[5] << 8) | val[4];
- *ps = rawps;
- *als = convert_lx(rawals);
- }
- unsigned char check_near_far(unsigned short data)
- {
- if (data >= RPR0521RS_NEAR_THRESH) {
- return (RPR0521RS_NEAR_VAL);
- } else {
- return (RPR0521RS_FAR_VAL);
- }
- }
- long rpr0521(void)
- {
- static rt_uint8_t isinit = 0;
- rt_uint16_t count = 1000;
- float data[3] = {0.0};
- char buff[50] = {0};
-
- unsigned short ps_val;
- float als_val;
- unsigned char near_far;
-
- if(!isinit)
- {
- rpr0521_init();
- isinit =1;
- }
- while(count--)
- {
- get_psalsval(&ps_val, &als_val);
- near_far = check_near_far(ps_val);
- if (near_far == RPR0521RS_NEAR_VAL)
- {
- rt_kprintf(" Near\n");
- }
- else
- {
- rt_kprintf(" Far\n");
- }
-
- if (als_val != RPR0521RS_ERROR) {
- sprintf(buff,"=%.3f",als_val);
- rt_kprintf(" RPR-0521RS (Ambient Light) %s\n",buff);
- rt_thread_mdelay(500);
- }
- }
- return 0;
- }
- FINSH_FUNCTION_EXPORT(rpr0521, show rpr0521 data);
- MSH_CMD_EXPORT(rpr0521, show rpr0521 data);
复制代码 测试时发现,靠近的话会输出near,改变光照强度对应的强度值会发生变化,输出如下:
程序和芯片手册如下。
|