STM32--软件IIC与硬件IIC驱动BH1750芯片

一.光照传感器分析

STM32--软件IIC与硬件IIC驱动BH1750芯片_第1张图片

查看芯片手册,总结GY_30使用注意的几个点:考虑断电通电、单次连续、读取数据时间

1.设置芯片为通电模式、

2.重置数字寄存器值

3.设置连续 H分辨率模式

4.等待一次测量时间max 180ms

5完整过程

STM32--软件IIC与硬件IIC驱动BH1750芯片_第2张图片

  • 发送起始信号,发送器件地址与读方向,检测应答。发送高分辨率指令,检测应答,发送结束信号
  • 延时等待180ms
  • 发送起始信号,发送器件地址与写方向,检测应答。接收高八位,检测应答。接收第八位,检测非应答,发送结束信号
/************************ BH1750初始化函数 ***********************
根据需要参考pdf进行参数修改
*****************************************************************/
void BH1750_Init(void)
{
	BH1750_Write_COM(SlaveAddress,0x01);      //开电源
	BH1750_Write_COM(SlaveAddress,0x07);    //重置数字寄存器值
	BH1750_Write_COM(SlaveAddress,0x10);      //连续模式
	Delay_ms(180);                            //等到测量结束
}
/************************ BH1750写指令函数 ***********************
Dev_Adder:模块IIC通讯地址
Common:   需要发送的控制指令
******************************************************************/
void BH1750_Write_COM(unsigned char Dev_Adder,unsigned char Common)
{
	IIC_Start();                   //起始信号
	IIC_Send_Data(Dev_Adder);      //发送从设备地址(从设备地址+读写控制位)
	if( IIC_Get_ACK() )            //检测应答
	{
		goto WR_End;           
	} 
	IIC_Send_Data(Common);       	 //发送测试指令
	if( IIC_Get_ACK() )            //检测应答
	{
		goto WR_End;
	}
WR_End:	
	IIC_Stop();	                   //发送结束信号
}

/************************ BH1750读数据函数 ***********************
Dev_Adder:模块IIC通讯地址
******************************************************************/
u16 BH1750_Read_Data(unsigned char Dev_Adder)
{
	unsigned char Buff[2] = {0}; 
	u16 Data = 0;
	IIC_Start();                           //起始信号
	IIC_Send_Data(Dev_Adder | 0x01);       //发送从设备地址(从设备地址+读写控制位)
	if( IIC_Get_ACK() )                    //检测应答
	{
		goto WR_End;           
	} 
	/* 读取光照数据 */
	Buff[0]= IIC_Read_Data(1);             //读取高字节光照数据 并发送应答信号               
	Buff[1] = IIC_Read_Data(0);            //读取低字节光照数据 并发送非应答信号                
	
WR_End:	
	IIC_Stop();	                          //发送结束信号
	Delay_ms(5);
	
    /* 合并光强数据 */	
	Data = Buff[0]; 
	Data = (Data << 8) | Buff[1];         //合成数据,即光照数据
	
	return Data;													//光照强度数值
}

 

一.软件IIC

/*******************************************************************
函数功能:   SDA初始化
*******************************************************************/
void SDA_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	/*SDA-----PB11*/ //浮空输入
	GPIO_InitStruct.GPIO_Pin = IIC_SDA;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(IIC_GPIO,&GPIO_InitStruct);
}

/*******************************************************************
函数功能:   SDA初始化
*******************************************************************/
void SDA_OUT(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	/*SDA-----PB11*/ //推挽输出 50MHZ
	GPIO_InitStruct.GPIO_Pin = IIC_SDA;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;  
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(IIC_GPIO,&GPIO_InitStruct);
}

/*******************************************************************
函数功能:   电容按键接口初始化
*******************************************************************/
void IIC_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能B时钟
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟	
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	
	/*SDA-----PB11*/ //推挽输出 50MHZ
	GPIO_InitStruct.GPIO_Pin = IIC_SDA;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(IIC_GPIO,&GPIO_InitStruct);
	
	/*CLK-----PB10*/ //推挽输出 50MHZ
	GPIO_InitStruct.GPIO_Pin = IIC_CLK;
	GPIO_Init(IIC_GPIO,&GPIO_InitStruct);
		
	CLK_H;
	SDA_H;
}

/*******************************************************************
函数功能:   起始信号
*******************************************************************/
void IIC_Start(void)
{
	SDA_OUT();
	SDA_H;   							//串行数据线高电平(空闲信号)
	CLK_H;   							//串行时钟线高电平(空闲信号)
	Delay_us(5);
	SDA_L;   							//串行数据线拉出下降沿
	Delay_us(5);
	CLK_L;   							//串行时钟线拉出下降沿
}

/*******************************************************************
函数功能:   结束信号
*******************************************************************/
void IIC_Stop(void)
{
	SDA_OUT();					//输出模式
	CLK_L;							//串行时钟线低电平
	SDA_L;							//串行数据线低电平
	CLK_H;							//串行时钟线高电平
	Delay_us(5);
	SDA_H;							//串行数据线高电平  上升沿
	Delay_us(5);

}

/*******************************************************************
函数功能:   发送应答信号
*******************************************************************/
void IIC_Send_ACK(void)
{
	
	CLK_L;
	SDA_OUT();			   				//输出模式
	SDA_L;										//串行数据线低电平
	Delay_us(5);
	CLK_H;										//串行时钟线线高电平    上下
	Delay_us(5);
	CLK_L;										//串行时钟线线低电平
}

/*******************************************************************
函数功能:   发送非应答信号
*******************************************************************/
void IIC_Send_NoACK(void)
{
	
	CLK_L;
	SDA_OUT(); 
	SDA_H;											//串行数据线为高电平
	Delay_us(5);
	CLK_H;
	Delay_us(5);
	CLK_L;
}
/*******************************************************************
函数功能:   发送8位数据
*******************************************************************/
void IIC_Send_Data(u8 dat)
{
	u8 i;
	SDA_OUT();
	CLK_L;
	for(i = 0; i < 8; i++)					//分8次传输数据  一位一位传递  串行
	{
	//	Delay_us(5);//SCL拉低后S,SDA要立马改变,(等待时间不能超过0.9us)?????
		if(dat & 0x80)								//先发最高位  1000 0000
		{
			SDA_H;     //写1
		}
		else
		{
			SDA_L;     //写0
		}
		dat <<= 1;									//左移操作  次高位-->最高位
		Delay_us(5);
		CLK_H;
		Delay_us(5);
		CLK_L;
		Delay_us(5);	
	}
}
/*******************************************************************
函数功能:   等待应答
*******************************************************************/
u8 IIC_Get_ACK(void)
{
	u8 ERRTIME = 0;    //超时变量
	SDA_IN();
	//SDA_L;// 没有影响
	Delay_us(5);
	CLK_H;
	Delay_us(5);
	while( READ_SDA() )
	{
		ERRTIME++;
		if(ERRTIME >=250)
		{
			IIC_Stop();
			return 1;
		}
	}
	CLK_L;
	return 0;
}

/*******************************************************************
函数功能:   读取8位数据
*******************************************************************/
u8 IIC_Read_Data(u8 ack)
{
	unsigned char i,date = 0;
	SDA_IN();
	for(i = 0; i < 8; i++)
	{
		
		CLK_L;
		Delay_us(5);
		CLK_H;
		date <<= 1;
		Delay_us(5);
		if( READ_SDA() )
		{
			date ++;
		}
		//Delay_us(2);
	}
	if(ack)
	{
		IIC_Send_ACK();																	//发送应答
	}
	else
	{
		IIC_Send_NoACK();																	//发送非应答
	}
	return date;

}


二.硬件IIC

1.初始化

void IIC_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	I2C_InitTypeDef  I2C_InitStructure;
	//初始化时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);
	//配置IO口功能
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 |GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;//IIC模式
	I2C_InitStructure.I2C_OwnAddress1 = 0x0A;//作为从机地址
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//地址的位数
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;//选择有应答信号
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_16_9;//配置高低电平比例
	I2C_InitStructure.I2C_ClockSpeed = 200000;//配置时钟
	I2C_Init(I2C2,&I2C_InitStructure);
	
	I2C_Cmd(I2C2,ENABLE);
//	I2C_AcknowledgeConfig(I2C2,ENABLE);	
}

2.驱动器件

typedef   unsigned char BYTE;
typedef   unsigned short WORD;

void Single_Write_BH1750(u8 REG_Address)
{
    while(I2C_GetFlagStatus(I2C2,I2C_FLAG_BUSY));
	//起始信号
	I2C_GenerateSTART(I2C2,ENABLE);
    while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);
	
	//发送设备地址+写信号
	I2C_Send7bitAddress(I2C2,SlaveAddress,I2C_Direction_Transmitter);
	while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);
	
	//内部寄存器地址
	I2C_SendData(I2C2,REG_Address);
	while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
	//发送停止信号
	I2C_GenerateSTOP(I2C2,ENABLE);               
}

//*********************************************************
//
//连续读出BH1750内部数据
//
//*********************************************************
BYTE    BUF[8];                         //接收数据缓存区   
int     dis_data;                       //变量   	
void Multiple_read_BH1750(void)
{   
	u8 i;
	while(I2C_GetFlagStatus(I2C2,I2C_FLAG_BUSY));
	//起始信号
	I2C_GenerateSTART(I2C2,ENABLE);
    while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);  
	//发送设备地址+读信号
	I2C_Send7bitAddress(I2C2,SlaveAddress,I2C_Direction_Receiver);
	while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS);
   
	for (i=0; i<3-1; i++)                      //连续读取2个地址数据,存储中BUF
    {
		while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
		BUF[i] = I2C_ReceiveData(I2C2);
    }
    I2C_AcknowledgeConfig(I2C2,DISABLE);
    while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
	BUF[i] = I2C_ReceiveData(I2C2);
	
	 //停止信号
	I2C_GenerateSTOP(I2C2,ENABLE);
	
	I2C_AcknowledgeConfig(I2C2,ENABLE);                        
    delay_ms(5);
}

//初始化BH1750,根据需要请参考pdf进行修改****
void Init_BH1750(void)
{
	IIC_Init();
	Single_Write_BH1750(0x01);
	Single_Write_BH1750(0x10);   // H- resolution mode
	delay_ms(180);
}

float BH1750_Value;
void BH1750_Read(void)
{
	
	Multiple_read_BH1750();		 //连续读出数据,存储在BUF中
	
	dis_data=BUF[0];
	dis_data=(dis_data<<8)+BUF[1];//合成数据,即光照数据
	
	BH1750_Value=(float)dis_data/1.2;
	
}

 

你可能感兴趣的:(stm32,stm32,嵌入式,单片机)