stm32f103C8T6使用硬件IIC读取BH1750光强传感器数值

硬件IIC主发送器传送序列图:

 硬件IIC主接收器传送序列图:

 BH1750官方文档"写指示"、"读结果"时序实例图:

 BH1750指令集:

指令

功能代码

注释

断电0000_0000无激活状态
通电0000_0001等待测量指令
重置0000_0111重置寄存器
连续高分辨率模式0001_00001LX分辨率,测量时间120ms
连续高分辨率模式20001-00010.5LX分辨率,测量时间120ms
连续低分辨率模式0001_00114LX分辨率,测量时间16ms
一次高分辨率模式0010_00001LX分辨率,测量时间120ms
一次高分辨率模式20010_00010.5LX分辨率,测量时间120ms
一次低分辨率模式0010_00114LX分辨率,测量时间120ms

接线:

VCC3.3V
GNG接地
SCLPB6
SDLPB7
ADDR

接地

代码:

lightgrad.c

#include "stm32f10x.h"
#include "OLED.h"

#define	  SlaveAddress   0x46 //定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
                              //ALT  ADDRESS引脚接地时地址为0x46,接电源时地址为0xB8

uint8_t Lightgrad[2]={0};//光照强度数值



//带超时退出的事件等待函数
void WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
	uint32_t timecount=40000;
	while( I2C_CheckEvent(I2Cx,I2C_EVENT) ==  ERROR )
	{
		timecount--;
		if(timecount == 0)//超时等待退出
		{
			break;
		}
	}
}

//写一个字节命令
void BH1750_WriteCommand(uint8_t command)
{
	I2C_GenerateSTART(I2C1, ENABLE);//生成起始条件
	WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT);//等待EV5事件的到来
	I2C_Send7bitAddress(I2C1, SlaveAddress, I2C_Direction_Transmitter);
	//硬件I2C会自动获取应答标志位,根据标志位,若未应答申请中断
	WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);//等待EV6事件的到来
	I2C_SendData(I2C1,command);//发送命令
	WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);//等待EV8_2事件的到来   停止事件
	I2C_GenerateSTOP(I2C1, ENABLE);
}


//连续读出光照强度传感器寄存器中的数据
void BH1750_Read(void)
{
	uint8_t i;
	uint16_t t=40000;
	while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY))//等待I2C总线空闲,加循环减减防止一直等待卡死在这
	{
		t--;
		if(t == 0)//超时等待退出
		{
			return;
		}
	}
	I2C_GenerateSTART(I2C1, ENABLE);//生成起始条件
	WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT);//等待EV5事件的到来
	
	I2C_Send7bitAddress(I2C1, SlaveAddress, I2C_Direction_Receiver);//发送设备地址+读信号
	WaitEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);//等待EV6事件的到来
	for(i=0;i<2;i++)
	{
		if(i == 1)//最后一个数据读到之前,发送非应答和停止信号
		{
			I2C_AcknowledgeConfig(I2C1,DISABLE);//取消应答
			I2C_GenerateSTOP(I2C1, ENABLE);//停止信号
		}
		WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED);//等待EV7事件的到来   每次读数据都要先等EV7事件到来 ,容易出错点
		Lightgrad[i]=I2C_ReceiveData(I2C1);//读数据
	}
	I2C_AcknowledgeConfig(I2C1,ENABLE);//恢复应答
}


void LightGard_Init(void)
{
	//RCC开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
	
	//配置GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//开漏输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//I2C配置
	I2C_InitTypeDef I2C_InitStructure;
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//接收数据后是否应答
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//7位地址位
	I2C_InitStructure.I2C_ClockSpeed = 50000;//速度
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//占空比2:1
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//I2C模式
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;//作为从机时自身地址
	I2C_Init(I2C1,&I2C_InitStructure);//
	
	//开启I2C
	I2C_Cmd(I2C1, ENABLE);
	
	//光照强度传感器控制信号
	//因为此处初始化为”连续“模式,所以只需要在初始化时发送一次通电指令,和一次分辨率模式指令,
	//在主函数的while循环中不要需要在写这两个命令
	BH1750_WriteCommand(0x01);   // 通电指令
    BH1750_WriteCommand(0x10);   // 连续高分辨率模式
}

lightgrad.h

#ifndef __LIGHTGARD_H
#define __LIGHTGARD_H


extern uint8_t Lightgrad[2];//光照强度数值

void BH1750_WriteCommand(uint8_t command);//写入BH1750命令
void BH1750_Read(void);//读取BH1750数值
void LightGard_Init(void);//初始化BH750

#endif

main.c

#include "stm32f10x.h"
#include "Delay.h"
#include "lightgard.h" 
#include "OLED.h"

uint16_t data=0;


int main(void)
{
	OLED_Init();
	LightGard_Init();
	while(1)
	{
		BH1750_Read();//读取数值
		data=Lightgrad[0];
		data=(data<<8) | Lightgrad[1];
		OLED_ShowBinNum(1,1,Lightgrad[0],8);
		OLED_ShowBinNum(2,1,Lightgrad[1],8);
		OLED_ShowNum(3,1,data,8);
	}
}

易错点:

1、BH1750读数读出刚刚写入的器件地址:

原因:在读函数数据中,读数据时没有等待EV7事件的到来;或者把等待EV7事件的函数放在了读数据后面;或者忘记循环等待Ev7事件

2:BH1750上电后只能读取一次数值

原因:当初始化设置为连续读模式后,在主函数中只需要初始化一次写命令,while中不在需要重复写命令;

当初始化设置为一次读模式后,需要在主函数的while循环中每次读数据之前发送一次命令设置(上电、模式选择命令)

BH1750中文手册

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值