目录
一、GY-30简介
1.1GY-30原理图
1.2模块引脚
二、GY-30驱动
2.1GPIO配置
2.2初始化BH1750
2.3设置精度
2.4读取光强数据
三、元操作
3.1延时
3.2IIC开始/结束信号
3.4发送应答信号
3.5接收应答信号
3.6IIC发送一个字节
3.7IIC读取一个字节
四、测试结果与光照强度参考
资源链接:请移步 我的资源
GY-30是一款内置ROHM-BH1750FLV芯片的数字光照强度模块。芯片内置16bitAD转换器,可直接数字输出,测量光照强度范围为0-65535lx(精度可选)。除此之外,模块内置电平转换,支持3-5V供电,可与5V单片机IO直接连接;对外提供IIC接口,方便使用。
ps:ADDR默认接地,此时IIC地址为0x46
使能时钟
由于本人使用的是hal库,使能时钟
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO配置
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_RESET);
/*Configure GPIO pins : PB0 PB1 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
PB0 -- 模拟SDA
PB1 -- 模拟SCL
IIC起始(SCL高电平时,SDA下降沿)
/***开始信号***/
void BH1750_Start()
{
HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_SET); //拉高数据线
HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_SET); //拉高时钟线
delay_us(5); //延时
HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_RESET); //产生下降沿
delay_us(5); //延时
HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_RESET); //拉低时钟线
}
发送设备地址,寄存器地址
IIC结束(SCL高电平,SDA上升沿)
/*****停止信号******/
void BH1750_Stop()
{
HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_RESET); //拉低数据线
HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_SET); //拉高时钟线
delay_us(5); //延时
HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_SET); //产生上升沿
delay_us(5); //延时
}
设置精度只需向BH1750发送指令,本人采用的是H- Resolution mode(0x10)
如需设置其他精度亲参考下表
读取BH1750内部数据
//连续读出BH1750内部数据
void mread(void)
{
uchar i;
BH1750_Start(); //起始信号
BH1750_SendByte(SlaveAddress+1); //发送设备地址+读信号
for (i=0; i<3; i++) //连续读取6个地址数据,存储中BUF
{
BUF[i] = BH1750_RecvByte(); //BUF[0]存储0x32地址中的数据
if (i == 3)
{
BH1750_SendACK(1); //最后一个数据需要回NOACK
}
else
{
BH1750_SendACK(0); //回应ACK
}
}
BH1750_Stop(); //停止信号
Delay_mms(5);
}
合成数据
dis_data=BUF[0];
dis_data=(dis_data<<8)+BUF[1]; //合成数据
Value_GY_30=(float)dis_data/1.2;
//系统主频72MHZ
void delay_us(uint16_t us)
{
while(us--)
{
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
__nop();__nop();
}
}
void Delay_mms(uint16_t tmp)
{
uint16_t i=0;
while(tmp--)
{
i=12000;
while(i--);
}
}
时序图如下代码见2.2初始化BH1750
/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void BH1750_SendACK(int ack)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
if(ack == 1) //写应答信号
HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_SET);
else if(ack == 0)
HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_RESET);
else
return;
HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_SET); //拉高时钟线
delay_us(5); //延时
HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_RESET); //拉低时钟线
delay_us(5); //延时
}
/**************************************
接收应答信号
**************************************/
int BH1750_RecvACK()
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; /*这里一定要设成输入上拉,否则不能读出数据*/
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Pin = sda;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_SET); //拉高时钟线
delay_us(5); //延时
if(HAL_GPIO_ReadPin( GPIOB, sda ) == 1 )//读应答信号
mcy = 1 ;
else
mcy = 0 ;
HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_RESET); //拉低时钟线
delay_us(5); //延时
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
return mcy;
}
/**************************************
向IIC总线发送一个字节数据
**************************************/
void BH1750_SendByte(uchar dat)
{
uchar i;
for (i=0; i<8; i++) //8位计数器
{
if( 0X80 & dat )
HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_SET);
else
HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_RESET);
dat <<= 1;
HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_SET); //拉高时钟线
delay_us(5); //延时
HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_RESET); //拉低时钟线
delay_us(5); //延时
}
BH1750_RecvACK();
}
/**************************************
从IIC总线读取一个字节数据
**************************************/
uchar BH1750_RecvByte()
{
uchar i;
uchar dat = 0;
uchar bit;
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; /*这里一定要设成输入上拉,否则不能读出数据*/
GPIO_InitStruct.Pin = sda;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_SET); //使能内部上拉,准备读取数据,
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1;
HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_SET); //拉高时钟线
delay_us(5); //延时
if( SET == HAL_GPIO_ReadPin( GPIOB, sda ) )
bit = 0X01;
else
bit = 0x00;
dat |= bit; //读数据
HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_RESET); //拉低时钟线
delay_us(5); //延时
}
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
return dat;
}
测试结果
光照强度参考值
环境 | 光照强度参考值 |
晚上 | 0.001-0.02 |
月夜 | 0.02-0.3 |
多云室内 | 5-50 |
多云室外 | 50-500 |
晴天室内 | 100-1000 |
夏天中午光照下 | 大约10*6能量 |
阅读书籍时的照明度 | 50-60 |
家庭录像标准照明度 | 1400 |