今天来实现一下模拟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);
}效果如下
我要赚赏金
