这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» STM32» STM32G070RB探测18-模拟IIC采集光照强度

共5条 1/1 1 跳转至

STM32G070RB探测18-模拟IIC采集光照强度

高工
2021-01-10 00:44:27 打赏
今天来实现一下模拟IIC采集BH1750也就是GY-30传感器所使用的芯片。BH1750是两线式串行总线接口(IIC)的16位数字输出型环境光强度传感器.芯片内置16bitAD转换器,可直接数字输出,测量光照强度范围为0-65535lx(精度可选)。依然使用模拟IIC,同样我们这个传感器跟OLED和AHT10是同一个总线,上篇已经弄好了驱动,这次直接看手册即可

首先还是先找设备地址,因为BH1750的手册是英文的,所以有点懵,简单的英文咱还是认识的,地址的英语咱还是会的,直接搜索adderss

根据手册可知地址是跟ADDR引脚的状态有关的,看下我们的原理图

可知ADDR是'L',所以写地址为0X46,读地址为0x47

#define BH1750_ADDR_WRITE 0x46 #define BH1750_ADDR_READ 0x47

当然也可以看出来BH1750的工作流程 写入工作模式,然后读取数据即可

继续看看以后什么工作模式

咦,难懂,看翻译吧,直接弄个枚举

typedef enum { POWER_OFF_CMD = 0x00, //断电:无激活状态 POWER_ON_CMD = 0x01, //通电:等待测量指令 RESET_REGISTER = 0x07, //重置数字寄存器(在断电状态下不起作用) CONT_H_MODE = 0x10, //连续H分辨率模式:在11x分辨率下开始测量,测量时间120ms CONT_H_MODE2 = 0x11, //连续H分辨率模式2:在0.51x分辨率下开始测量,测量时间120ms CONT_L_MODE = 0x13, //连续L分辨率模式:在411分辨率下开始测量,测量时间16ms ONCE_H_MODE = 0x20, //一次高分辨率模式:在11x分辨率下开始测量,测量时间120ms,测量后自动设置为断电模式 ONCE_H_MODE2 = 0x21, //一次高分辨率模式2:在0.51x分辨率下开始测量,测量时间120ms,测量后自动设置为断电模式 ONCE_L_MODE = 0x23 //一次低分辨率模式:在411x分辨率下开始测量,测量时间16ms,测量后自动设置为断电模式 } BH1750_MODE;

我们就直接使用一次高分辨率模式:在11x分辨率下开始测量,测量时间120ms,测量后自动设置为断电模式

根据流程写驱动

发送指令

/** * @brief 向BH1750发送一条指令 * @param cmd —— BH1750工作模式指令(在BH1750_MODE中枚举定义) */ void BH1750_Send_Cmd(BH1750_MODE cmd) { IIC_Init(); IIC_Start(); IIC_Send_Byte(BH1750_ADDR_WRITE); IIC_Wait_Ack(); IIC_Send_Byte(cmd); IIC_Wait_Ack(); IIC_Stop(); }

读数据

/** * @brief 从BH1750接收一次光强数据 * @param dat —— 存储光照强度的地址(两个字节数组) * @retval 成功 —— 返回1 */ uint8_t BH1750_Read_Dat(uint8_t* dat) { IIC_Start(); IIC_Send_Byte(BH1750_ADDR_READ); IIC_Wait_Ack(); dat[0]=IIC_Read_Byte(1);//取高八位 dat[1]=IIC_Read_Byte(0);//取低八位 IIC_Stop(); return 1; }

数据转换

/** * @brief 将BH1750的两个字节数据转换为光照强度值(0-65535) * @param dat —— 存储光照强度的地址(两个字节数组) * @retval 成功 —— 返回光照强度值 */ uint16_t BH1750_Dat_To_Lux(uint8_t* dat) { uint16_t lux = 0; lux = dat[0]; lux <<= 8; lux += dat[1]; lux = (int)(lux / 1.2); return lux; }
读取

使用一次高分辨率模式

定义一个数组存放高八位和低八位 定义一个十六进制存储光照强度

uint8_t lux[2]; uint16_t lux_16; while (1) { if(AHT10ReadData(&tem,&hum)==0) { printf("tem:%.1f\r\nhum:%d%%\r\n",tem,hum); } else { printf("aht10 not read\r\n"); } BH1750_Send_Cmd(ONCE_H_MODE);//单次模式 OLED_ShowCHinese(0u,0u,0); OLED_ShowCHinese(16u,0u,1); OLED_ShowCHinese(32u,0u,2); OLED_ShowCHinese(48u,0u,3); OLED_ShowCHinese(64u,0u,4); OLED_ShowCHinese(80u,0u,5); sprintf(buf,"tem:%.1f",tem); OLED_P8x16Str(0u,2u,(uint8_t *)buf); sprintf(buf,"hum:%d%%",hum); OLED_P8x16Str(0u,4u,(uint8_t *)buf); sprintf(buf,"lux:%d",lux_16); OLED_P8x16Str(0u,6u,(uint8_t *)buf); HAL_Delay(500); BH1750_Read_Dat(lux);//读取数据 lux_16 = BH1750_Dat_To_Lux(lux);//转换数据 printf("lux:%d\r\n",lux_16); }
效果如下



高工
2021-01-10 17:13:31 打赏
2楼

代码写的还会非常不错的


工程师
2021-01-10 21:10:55 打赏
3楼

感谢分享


工程师
2021-01-12 22:15:42 打赏
4楼

强度还是蛮大的


工程师
2021-01-12 22:56:17 打赏
5楼

学习一下


共5条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]