[AT32M412] 【AT-START-M412测评】+光照强度传感器及其检测

[复制链接]
1309|12
 楼主| jinglixixi 发表于 2025-6-2 12:19 | 显示全部楼层 |阅读模式
本帖最后由 jinglixixi 于 2025-6-2 12:22 编辑

#申请原创#

BH1750是一款基于 I2C 接口的数字式环境光传感器,它适于获得环境光照强度的检测,受光学窗口的影响其检测最小为 0.11 lx,最大为 100000 lx。
该传感器的引脚定义如图1所示,它与开发板的连接关系为:
SCL ---PB8
SDA---PB9
为便于直观观察检测结果,由OLED进行显示,它与开发板的连接关系为:
SCL ---PA5
SDA---PA6

798eb795e12fac946830606e8d9c5ecb
图1 引脚定义

19f3f82be9c23082296bf34cb2c677d5
图2 所用接口

为便于引脚的分配和使用,这里采用模拟I2C的方式来实现光照强度的检测。
配置所用引脚的函数为:
  1. void BH1750_Init(void)
  2. {
  3. gpio_init_type gpio_init_struct;
  4. crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
  5. gpio_default_para_init(&gpio_init_struct);
  6. gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  7. gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  8. gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  9. gpio_init_struct.gpio_pins = GPIO_PINS_8|GPIO_PINS_9;
  10. gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  11. gpio_init(GPIOB, &gpio_init_struct);
  12. }

有别于OLED屏的显示驱动,在进行光照检测时,数据引脚既要工作在输出模式,也要工作在输入模式。
为此,需要配置相应的工作模式函数,以便进行工作模式切换。
设置为输入模式的函数为:
  1. void IIC_INPUT_MODE_SET()
  2. {
  3. gpio_init_type gpio_init_struct;
  4. gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
  5. gpio_init_struct.gpio_pins = GPIO_PINS_9;
  6. gpio_init(GPIOB, &gpio_init_struct);
  7. }

设置为输出模式的函数为:
  1. void IIC_OUTPUT_MODE_SET()
  2. {
  3.   gpio_init_type gpio_init_struct;
  4.   gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  5.   gpio_init_struct.gpio_pins = GPIO_PINS_9;
  6.   gpio_init(GPIOB, &gpio_init_struct);
  7. }


设置引脚输出高低电平和检测引脚状态的语句定义为:
#define SCL_Set()       GPIOB->scr = GPIO_PINS_8
#define SCL_Clr()       GPIOB->clr = GPIO_PINS_8
#define SDA_Set()       GPIOB->scr = GPIO_PINS_9
#define SDA_Clr()       GPIOB->clr = GPIO_PINS_9
#define IIC_SDA_IN      gpio_input_data_bit_read(GPIOB, GPIO_PINS_9)

模拟I2C处理的辅助辅助函数如下:
  1. void BH1750_Start()
  2. {
  3. IIC_OUTPUT_MODE_SET();
  4. SDA_Set();
  5. SCL_Set();
  6. delay_us(5);
  7. SDA_Clr();
  8. delay_us(5);
  9. SCL_Clr();
  10. }

  11. void BH1750_Stop()
  12. {
  13. IIC_OUTPUT_MODE_SET();
  14. SDA_Clr();
  15. SCL_Set();
  16. delay_us(5);
  17. SDA_Set();
  18. delay_us(5);
  19. }

  20. void BH1750_SendACK(char ack)
  21. {
  22. IIC_OUTPUT_MODE_SET();
  23. SCL_Clr();
  24. if(ack)
  25. {
  26. SDA_Set();
  27. }
  28. else
  29. {
  30. SDA_Clr();
  31. }
  32. delay_us(2);
  33. SCL_Set();
  34. delay_us(5);
  35. SCL_Clr();
  36. }

  37. char BH1750_RecvACK()
  38. {
  39. int cnt=0;
  40. IIC_OUTPUT_MODE_SET();
  41. SDA_Set();
  42. delay_us(1);
  43. SCL_Set();
  44. IIC_INPUT_MODE_SET();
  45. delay_us(1);
  46. while(IIC_SDA_IN)
  47. {
  48. cnt++;
  49. delay_us(1);
  50. if(cnt>=250)
  51. {
  52. BH1750_Stop();
  53. return 1;
  54. }
  55. }
  56. SCL_Clr();
  57. return 0;
  58. }

模拟I2C发送字节数据的函数为:
  1. void BH1750_SendByte(char data)
  2. {
  3. char i;
  4. IIC_OUTPUT_MODE_SET();
  5. SCL_Clr();
  6. delay_us(2);
  7. for (i=0;i<8;i++)
  8. {
  9. if(data&0x80)
  10. {
  11. SDA_Set();
  12. }
  13. else
  14. {
  15. SDA_Clr();
  16. }
  17. data <<= 1;
  18. SCL_Set();
  19. delay_us(2);
  20. SCL_Clr();
  21. delay_us(2);
  22. }
  23. }

模拟I2C读取字节数据的函数为:
  1. char BH1750_RecvByte()
  2. {
  3. char i;
  4. char data = 0;
  5. IIC_INPUT_MODE_SET();
  6. for (i=0;i<8;i++)
  7. {
  8. SCL_Clr();
  9. delay_us(2);
  10. SCL_Set();
  11. data <<= 1;
  12. SCL_Set();
  13. if(IIC_SDA_IN) data|=0x01;
  14. delay_us(2);
  15. }
  16. SCL_Clr();
  17. return data;
  18. }

写入寄存器地址的函数为:
  1. void Single_Write_BH1750(char REG_Address)
  2. {
  3. BH1750_Start();
  4. BH1750_SendByte(SlaveAddress);
  5. BH1750_RecvACK();
  6. BH1750_SendByte(REG_Address);
  7. BH1750_RecvACK();
  8. BH1750_Stop();
  9. }

读取BH1750多字节数据的函数为:
  1. void Multiple_Read_BH1750()
  2. {
  3. BH1750_Start();
  4. BH1750_SendByte(SlaveAddress+1);
  5. BH1750_RecvACK();
  6. BUF[0] = BH1750_RecvByte();
  7. BH1750_SendACK(0);
  8. BUF[1] = BH1750_RecvByte();
  9. BH1750_SendACK(1);
  10. BH1750_Stop();
  11. delay_ms(5);
  12. }

实现光强检测与显示的函数为:
  1. void Get_Sunlight_Value()
  2. {
  3. int dis_data=0;
  4. float temp;
  5. char i=0;
  6. unsigned int sd;
  7. Single_Write_BH1750(0x01);
  8. Single_Write_BH1750(0x10);
  9. delay_ms(180);
  10. Multiple_Read_BH1750();
  11. for(i=0;i<3;i++)dis_data=BUF[0];
  12. dis_data=(dis_data<<8)+BUF[1];
  13. temp=(float)dis_data/1.2;
  14. sd=temp;
  15. OLED_ShowNum(20,2,sd,5,16);
  16. }

实现光强检测与显示的主程序为:
  1. int main(void)
  2. {
  3. system_clock_config();
  4. at32_board_init();
  5. oled_config();
  6. OLED_Init();
  7. OLED_Clear();
  8. OLED_ShowString(0,0,"AT32M412",16);
  9. OLED_ShowString(0,2,"L=",16);
  10. BH1750_Init();
  11. while(1)
  12. {
  13. at32_led_toggle(LED2);
  14. delay_ms(200);
  15. at32_led_toggle(LED3);
  16. delay_ms(200);
  17. at32_led_toggle(LED4);
  18. delay_ms(200);
  19. Get_Sunlight_Value();
  20. }
  21. }

经程序的编译和下载,其检测结果如图4所示。
defce0d85a1436035ead1664be14c520
图3 连接形式

22c9519cbced5266e79bd67a494ef5b6
图4 检测结果



kmzuaz 发表于 2025-6-4 10:05 | 显示全部楼层
非常适合用于嵌入式系统的学习和开发。
mikewalpole 发表于 2025-6-4 13:28 | 显示全部楼层
BH1750              
mmbs 发表于 2025-6-5 11:05 | 显示全部楼层
若采用的是光敏二极管传感器,其灵敏度高、线性度好的特性得以充分展现
51xlf 发表于 2025-6-5 14:34 | 显示全部楼层
高精度的光照强度传感器              
plsbackup 发表于 2025-6-5 16:16 | 显示全部楼层
适合中阶物联网项目              
updownq 发表于 2025-6-5 18:50 | 显示全部楼层
能够准确地测量环境光强度,适用于各种需要光控的应用场景
benjaminka 发表于 2025-6-5 20:52 | 显示全部楼层
低功耗是非常重要的考量因素之一。
loutin 发表于 2025-6-6 14:36 | 显示全部楼层
无需复杂的硬件配置即可开始采集数据。这极大地提高了开发效率。
 楼主| jinglixixi 发表于 2025-6-6 14:42 | 显示全部楼层
loutin 发表于 2025-6-6 14:36
无需复杂的硬件配置即可开始采集数据。这极大地提高了开发效率。

没错,的确如此!
modesty3jonah 发表于 2025-6-8 22:05 | 显示全部楼层
传感器的信号传输稳定              
usysm 发表于 2025-6-9 01:26 | 显示全部楼层
常见的BH1750              
幽谷深处 发表于 2025-6-11 11:17 | 显示全部楼层
常见的BH1750 ,主要应该是展示雅特力 I2C的性能,很好的案例。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

521

主题

2949

帖子

39

粉丝
快速回复 在线客服 返回列表 返回顶部