OpenVINOTM,给你看得见的未来!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 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 跳转至

回复

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