查看芯片手册,总结GY_30使用注意的几个点:考虑断电通电、单次连续、读取数据时间
/************************ 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; //光照强度数值
}
/*******************************************************************
函数功能: 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;
}
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);
}
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;
}