Microfelt.net | 微感论坛-传感器技术交流社区
返回列表 发布新帖
查看: 36|回复: 0

[技术交流] VCNL36821S STM32 HAL 库核心开发代码可直接移植

8

主题

7

回帖

48

积分

新手上路

发表于 7 天前 | 查看全部 |阅读模式
以下代码基于 STM32F103 系列,采用 I2C 通信方式,实现 VCNL36821S 初始化、近距离(PS)/ 环境光(ALS)数据读取、中断配置等核心功能,注释清晰,可直接适配主流 STM32 平台。
一、头文件与宏定义(vcnl36821s.h)
  1. <font face="宋体">#ifndef __VCNL36821S_H
  2. #define __VCNL36821S_H

  3. #include "stm32f1xx_hal.h"

  4. // *************************** 硬件配置 ***************************
  5. // VCNL36821S I2C地址(A0/A1接GND时为0x60,左移1位适配HAL库)
  6. #define VCNL36821S_I2C_ADDR    0x60 << 1
  7. // 绑定使用的I2C句柄(根据实际工程修改)
  8. #define VCNL36821S_I2C_HANDLE  &hi2c1

  9. // *************************** 寄存器地址 ***************************
  10. #define VCNL36821S_ID_REG        0x00    // 设备ID寄存器(默认值0x11)
  11. #define VCNL36821S_PS_CONF1_REG  0x03    // PS配置寄存器1
  12. #define VCNL36821S_PS_CONF2_REG  0x04    // PS配置寄存器2
  13. #define VCNL36821S_ALS_CONF_REG  0x06    // ALS配置寄存器
  14. #define VCNL36821S_ALS_THDL_REG  0x08    // ALS下限阈值寄存器(低字节)
  15. #define VCNL36821S_ALS_THDH_REG  0x09    // ALS上限阈值寄存器(低字节)
  16. #define VCNL36821S_PS_THDL_REG   0x0A    // PS下限阈值寄存器
  17. #define VCNL36821S_PS_THDH_REG   0x0B    // PS上限阈值寄存器
  18. #define VCNL36821S_INT_CTRL_REG  0x0D    // 中断控制寄存器
  19. #define VCNL36821S_ALS_DATA_REG  0x10    // ALS数据寄存器(低字节)
  20. #define VCNL36821S_PS_DATA_REG   0x18    // PS数据寄存器

  21. // *************************** 函数声明 ***************************
  22. /**
  23. * @brief  检测VCNL36821S设备ID,验证通信链路
  24. * @retval 1-检测成功,0-检测失败
  25. */
  26. uint8_t VCNL36821S_CheckID(void);

  27. /**
  28. * @brief  初始化VCNL36821S:配置ALS/PS工作模式
  29. * @note   默认配置:ALS高分辨率+50Hz工频抑制;PS中等发射功率+100ms检测周期
  30. */
  31. void VCNL36821S_Init(void);

  32. /**
  33. * @brief  读取环境光强度(ALS)
  34. * @retval 光强值(lx)
  35. */
  36. float VCNL36821S_ReadALS(void);

  37. /**
  38. * @brief  读取近距离检测值(PS)
  39. * @retval PS原始值(范围0~4095,数值越大距离越近)
  40. */
  41. uint16_t VCNL36821S_ReadPS(void);

  42. /**
  43. * @brief  配置PS/ALS中断阈值
  44. * @param  als_thdl: ALS下限阈值(0~65535)
  45. * @param  als_thdh: ALS上限阈值(0~65535)
  46. * @param  ps_thdl:  PS下限阈值(0~4095)
  47. * @param  ps_thdh:  PS上限阈值(0~4095)
  48. */
  49. void VCNL36821S_SetIntThreshold(uint16_t als_thdl, uint16_t als_thdh, uint16_t ps_thdl, uint16_t ps_thdh);

  50. /**
  51. * @brief  启用PS/ALS中断功能
  52. * @param  ps_int_en: 1-启用PS中断,0-禁用
  53. * @param  als_int_en:1-启用ALS中断,0-禁用
  54. */
  55. void VCNL36821S_EnableInt(uint8_t ps_int_en, uint8_t als_int_en);

  56. #endif</font>
复制代码
二、核心功能实现(vcnl36821s.c)
  1. <font face="宋体">#include "vcnl36821s.h"

  2. /**
  3. * @brief  I2C寄存器写函数(底层封装,方便移植)
  4. * @param  reg_addr: 寄存器地址
  5. * @param  data: 要写入的数据
  6. * @retval HAL状态
  7. */
  8. static HAL_StatusTypeDef VCNL36821S_WriteReg(uint8_t reg_addr, uint8_t data)
  9. {
  10.     return HAL_I2C_Mem_Write(VCNL36821S_I2C_HANDLE, VCNL36821S_I2C_ADDR,
  11.                              reg_addr, 1, &data, 1, 100);
  12. }

  13. /**
  14. * @brief  I2C寄存器读函数(底层封装,方便移植)
  15. * @param  reg_addr: 寄存器地址
  16. * @param  data: 读取数据缓冲区
  17. * @param  len: 读取长度
  18. * @retval HAL状态
  19. */
  20. static HAL_StatusTypeDef VCNL36821S_ReadReg(uint8_t reg_addr, uint8_t *data, uint16_t len)
  21. {
  22.     return HAL_I2C_Mem_Read(VCNL36821S_I2C_HANDLE, VCNL36821S_I2C_ADDR,
  23.                             reg_addr, 1, data, len, 100);
  24. }

  25. // 检测设备ID
  26. uint8_t VCNL36821S_CheckID(void)
  27. {
  28.     uint8_t dev_id = 0;
  29.     if(VCNL36821S_ReadReg(VCNL36821S_ID_REG, &dev_id, 1) != HAL_OK)
  30.     {
  31.         return 0;
  32.     }
  33.     // 验证威世VCNL36821S默认ID
  34.     return (dev_id == 0x11) ? 1 : 0;
  35. }

  36. // 传感器初始化
  37. void VCNL36821S_Init(void)
  38. {
  39.     // 通信失败直接退出
  40.     if(!VCNL36821S_CheckID()) return;

  41.     // ********************* PS配置 *********************
  42.     // PS_CONF1: 0x20 → PS检测周期100ms,16次平均滤波
  43.     VCNL36821S_WriteReg(VCNL36821S_PS_CONF1_REG, 0x20);
  44.     // PS_CONF2: 0x08 → LED发射功率中等(120mA),禁用PS唤醒
  45.     VCNL36821S_WriteReg(VCNL36821S_PS_CONF2_REG, 0x08);

  46.     // ********************* ALS配置 *********************
  47.     // ALS_CONF: 0x18 → ALS分辨率16位,启用50Hz工频抑制,测量速率10Hz
  48.     VCNL36821S_WriteReg(VCNL36821S_ALS_CONF_REG, 0x18);

  49.     // 等待传感器稳定
  50.     HAL_Delay(20);
  51. }

  52. // 读取环境光强度(转换为lx)
  53. float VCNL36821S_ReadALS(void)
  54. {
  55.     uint8_t als_data[2] = {0};
  56.     uint16_t als_raw = 0;
  57.     float als_lx = 0.0f;

  58.     // 读取ALS 16位数据(低字节+高字节)
  59.     if(VCNL36821S_ReadReg(VCNL36821S_ALS_DATA_REG, als_data, 2) != HAL_OK)
  60.     {
  61.         return 0.0f;
  62.     }

  63.     als_raw = (uint16_t)((als_data[1] << 8) | als_data[0]);
  64.     // 转换公式(参考威世官方手册):1LSB = 0.01 lx
  65.     als_lx = als_raw * 0.01f;

  66.     return als_lx;
  67. }

  68. // 读取近距离检测原始值
  69. uint16_t VCNL36821S_ReadPS(void)
  70. {
  71.     uint8_t ps_data[2] = {0};
  72.     uint16_t ps_raw = 0;

  73.     // 读取PS 12位数据(低字节+高字节,仅低12位有效)
  74.     if(VCNL36821S_ReadReg(VCNL36821S_PS_DATA_REG, ps_data, 2) != HAL_OK)
  75.     {
  76.         return 0;
  77.     }

  78.     ps_raw = (uint16_t)((ps_data[1] << 8) | ps_data[0]) & 0x0FFF; // 仅保留低12位
  79.     return ps_raw;
  80. }

  81. // 配置中断阈值
  82. void VCNL36821S_SetIntThreshold(uint16_t als_thdl, uint16_t als_thdh, uint16_t ps_thdl, uint16_t ps_thdh)
  83. {
  84.     // 配置ALS下限阈值(低字节)
  85.     VCNL36821S_WriteReg(VCNL36821S_ALS_THDL_REG, als_thdl & 0xFF);
  86.     VCNL36821S_WriteReg(VCNL36821S_ALS_THDL_REG + 1, (als_thdl >> 8) & 0xFF);
  87.     // 配置ALS上限阈值(低字节)
  88.     VCNL36821S_WriteReg(VCNL36821S_ALS_THDH_REG, als_thdh & 0xFF);
  89.     VCNL36821S_WriteReg(VCNL36821S_ALS_THDH_REG + 1, (als_thdh >> 8) & 0xFF);

  90.     // 配置PS下限阈值(12位)
  91.     VCNL36821S_WriteReg(VCNL36821S_PS_THDL_REG, ps_thdl & 0xFF);
  92.     VCNL36821S_WriteReg(VCNL36821S_PS_THDL_REG + 1, (ps_thdl >> 8) & 0x0F);
  93.     // 配置PS上限阈值(12位)
  94.     VCNL36821S_WriteReg(VCNL36821S_PS_THDH_REG, ps_thdh & 0xFF);
  95.     VCNL36821S_WriteReg(VCNL36821S_PS_THDH_REG + 1, (ps_thdh >> 8) & 0x0F);
  96. }

  97. // 启用中断功能
  98. void VCNL36821S_EnableInt(uint8_t ps_int_en, uint8_t als_int_en)
  99. {
  100.     uint8_t int_ctrl = 0;
  101.     // 读取当前中断控制寄存器值
  102.     VCNL36821S_ReadReg(VCNL36821S_INT_CTRL_REG, &int_ctrl, 1);

  103.     // 设置PS/ALS中断使能位
  104.     if(ps_int_en) int_ctrl |= 0x02;  // BIT1: PS中断使能
  105.     else int_ctrl &= ~0x02;

  106.     if(als_int_en) int_ctrl |= 0x01; // BIT0: ALS中断使能
  107.     else int_ctrl &= ~0x01;

  108.     // 写入配置
  109.     VCNL36821S_WriteReg(VCNL36821S_INT_CTRL_REG, int_ctrl);
  110. }</font>
复制代码

三、主函数调用示例(main.c)
  1. <font face="宋体">#include "stm32f1xx_hal.h"
  2. #include "vcnl36821s.h"

  3. // 全局I2C句柄(根据实际工程生成)
  4. I2C_HandleTypeDef hi2c1;

  5. int main(void)
  6. {
  7.     HAL_Init();
  8.     SystemClock_Config();
  9.     MX_I2C1_Init(); // 初始化I2C1(速率400kHz,开漏输出)

  10.     float als_lx;
  11.     uint16_t ps_raw;

  12.     // 初始化VCNL36821S
  13.     VCNL36821S_Init();

  14.     // 配置中断阈值(示例:ALS<100lx或>5000lx触发;PS<100或>3000触发)
  15.     VCNL36821S_SetIntThreshold(1000, 50000, 100, 3000);
  16.     // 启用ALS+PS中断
  17.     VCNL36821S_EnableInt(1, 1);

  18.     while(1)
  19.     {
  20.         // 读取环境光和近距离数据
  21.         als_lx = VCNL36821S_ReadALS();
  22.         ps_raw = VCNL36821S_ReadPS();

  23.         // 示例:根据PS值判断距离(可根据实际场景校准)
  24.         if(ps_raw > 3000)
  25.         {
  26.             // 物体接近(<5cm),执行熄屏/触发动作
  27.         }
  28.         else if(ps_raw < 100)
  29.         {
  30.             // 物体远离(>20cm),执行亮屏/复位动作
  31.         }

  32.         // 示例:根据ALS值调节屏幕亮度
  33.         if(als_lx < 50.0f)
  34.         {
  35.             // 低光环境,调亮屏幕
  36.         }
  37.         else if(als_lx > 2000.0f)
  38.         {
  39.             // 强光环境,调暗屏幕
  40.         }

  41.         HAL_Delay(200); // 200ms读取一次,可按需调整
  42.     }
  43. }</font>
复制代码
四、移植与使用注意事项
  • 硬件适配:

    • I2C 引脚需配置为开漏输出,SDA/SCL 串联 4.7kΩ 上拉电阻到 3.3V;
    • 传感器 INT 引脚可接 STM32 外部中断引脚(如 PA0),用于中断触发;
    • 保证传感器光学窗口无遮挡,避免油污 / 灰尘影响检测精度。

  • 代码移植:

    • 修改VCNL36821S_I2C_HANDLE为工程实际使用的 I2C 句柄;
    • 根据实际需求调整 PS 发射功率、ALS 测量速率(修改初始化寄存器值);
    • PS 原始值需根据实际场景校准(如:3000 对应 5cm,100 对应 20cm)。

  • 性能优化:

    • 低功耗场景:配置传感器自动休眠,仅在需要时唤醒读取数据;
    • 抗干扰优化:开启 ALS 工频抑制,PS 可增加平均滤波次数(修改 PS_CONF1 寄存器)。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Microfelt|微感论坛-传感器技术交流社区 © 2001-2025 Discuz! Team. Powered by Discuz! W1.5 粤ICP备18044996号-3|81f01e9418981fd496123c701618b320
在本版发帖
论坛管理
论坛管理 返回顶部
快速回复 返回顶部 返回列表