文章目录[隐藏]
1.BH1750基本原理讲解
BH1750作为一款数字化的光照传感器,采用的是IIC接口,本篇文章主要是侧重BH1750的应用,关于IIC总线的时序原理,请大家自行学习。
数字化的传感器,简单点理解即只要通信接口配置正确,即可读出数据,内部集成的有AD转换,但是得到的数据只是为数字量,还需要进行转换
本篇文章使用的指令只有两个:
等待测量–0X01
连续高分辨率模式–0x10
引脚的连接方式按照上图即可,初学者可能对ADDR引脚有疑问,其实简单点理解就是有两个地址:
ADDR连接GND时,地址为:0x46
ADDR连接VCC时,地址为:0xB8
本篇文章后续代码使用的地址是:0x46;
2.代码篇
函数部分:
#include "bh1750.h"
#include "delay.h"
void bh1750_Config(uint8_t mode)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
if(mode==1)
{
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
Single_Write_BH1750(0x01);
delay_ms(200);
}
void bh1750_Start(void)
{
SCK_STA(1);
SDA_OUT(1);
delay_us(5);
SDA_OUT(0);
delay_us(5);
SCK_STA(0);
}
void bh1750_Stop(void)
{
SDA_OUT(0);
SCK_STA(0);
delay_us(5);
SCK_STA(1);
delay_us(5);
SDA_OUT(1);
delay_us(5);
/*
这样写也可以
SDA_OUT(0);
SCK_STA(1);
delay_us(5);
SDA_OUT(1);
delay_us(5);
*/
}
//发送应答信号
//ack--0 应答
void bh1750_SendAck(u8 ack)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
SCK_STA(0);//时钟线拉低
delay_us(5);
if(ack==1)
{
SDA_OUT(1);
}
else if(ack==0)
{
SDA_OUT(0);
}
else return;
SCK_STA(1);
delay_us(5);
SCK_STA(0);
delay_us(5);
}
uint8_t bh1750_RevAck(void)
{
uint8_t revack=0xff;
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
SCK_STA(1);
delay_us(5);
if(SDA_IN==1)
{
revack=1;
}
else if(SDA_IN==0)
{
revack=0;
}
SCK_STA(0);
delay_us(5);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
return revack;
}
void bh1750_SendData(uint8_t data)
{
uint8_t i=0;
SCK_STA(0);
for(i=0;i<8;i++)
{
if((data& 0x80))
{
SDA_OUT(1);
}
else SDA_OUT(0);
data<<=1;
SCK_STA(1);
delay_us(5);
SCK_STA(0);
delay_us(5);
}
bh1750_RevAck();
}
uint8_t bh1750_RevData(void)
{
u8 i=0;
u8 revdata=0;
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//SDA_OUT(1);
for(i=0;i<8;i++)
{
revdata<<=1;
SCK_STA(1);
delay_us(5);
if(SDA_IN)
{
revdata |=0X01;
}
SCK_STA(0);
delay_us(5);
}
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
return revdata;
}
//数据接收函数
void Single_Write_BH1750(u8 REG_Address)//REG_Address是要写入的指令
{
bh1750_Start(); //起始信号
bh1750_SendData(SLAVEADDR); //发送设备地址+写信号
bh1750_SendData(REG_Address); //写入指令
bh1750_Stop(); //发送停止信号
}
uint8_t rev_buf[2]={0};
void read_BH1750(void)
{
uint8_t i;
bh1750_Start();
bh1750_SendData(SLAVEADDR+1);
for(i=0;i<2;i++)
{
rev_buf[i]=bh1750_RevData();
if(i==2)
{
bh1750_SendAck(1);//非应答
}
else bh1750_SendAck(0);//应答
}
bh1750_Stop();
delay_ms(5);
}
//整理数据
float get_BH1750Data(void)
{
int data=0;
float tmp1=0;
float tmp2=0;
Single_Write_BH1750(REG_CMD);//上电
Single_Write_BH1750(HIGH_MEASUCMD);//高分辨率测量
delay_ms(200);
read_BH1750();//读取数据
data=rev_buf[0];
data=(data<<8)|rev_buf[1];
tmp1=data/1.
return tmp1;
}
声明部分:
#ifndef __BH1750_H__
#define __BH1750_H__
#define SLAVEADDR 0x46
#define REG_CMD 0x01 //通电 开始写入
#define HIGH_MEASUCMD 0x10 //高分辨率模式,此模式下通电后需要等待180ms左右设备才可以工作
#define INPUT_MODE 0
#define OUTPUT_MODE 1
#define SCK_STA(x) x?(GPIO_SetBits(GPIOA,GPIO_Pin_2)):(GPIO_ResetBits(GPIOA,GPIO_Pin_2))
#define SDA_OUT(x) x?(GPIO_SetBits(GPIOA,GPIO_Pin_3)):(GPIO_ResetBits(GPIOA,GPIO_Pin_3))
#define SDA_IN GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)
void bh1750_Config(uint8_t mode);
void bh1750_Start(void);
void bh1750_Stop(void);
void bh1750_SendAck(u8 ack);
uint8_t bh1750_RevAck(void);
void bh1750_SendData(uint8_t data);
uint8_t bh1750_RevData(void);
void Single_Write_BH1750(u8 REG_Address);
void read_BH1750(void);
float get_BH1750Data(void);
#endif
/*
BH1750代码中的重点,当然了也是IIC通信中的重点(是我个人感觉这个是重点)
响应部分的时序分析:
1.先说发送应答部分,意味着是主机发送应答,重点在于是否还要接受数据,因此我们需要整理,应答信号,也就是想好此时
我们是需要发送0还是1,这个时候一定要注意,时钟线是需要设置为低电平的,因为只有时钟为低电平的时候,我们才可以改变SDA线路上的电平状态,设置好应答信号之后,紧接着拉高时钟电平,这个时候就是发送数据到从机。
2.再说接收应答部分,意味着我们的MCU只要接收应答即可,说明应答信号在模块内部已经整好了,那么我们只需要将时钟线拉高,等待接收即可,接收完毕之后,再把时钟线拉低,进行延时,等待模块处理数据
以上两点,是我在看了好多IIC时序中得到的一点经验,大佬们也许会感觉这个东西没什么,但是我把这个点着重说出来了,希望初学者可以少走弯路。大家可以自习的想一下IIC的时序,这个时序其实不难,但是为什么在写的过程中总是出现问题,模拟IIC对
延时和状态的切换要求是比较严格的。
最后想说的就是,在IIC的接收和发送函数中是和应答这一块是一个道理,大家可以自习比较下,先按照标准的IIC时序就行配置理解关于IIC其实好多模块在应用的过程中都会有些不一样,这个就需要大家区查看相应的模块手册。
关于IIC的使用,我会在后续再找两个模块进行讲解比较,关于这些基础类的之后还是需要大家多去使用,多去思考,才能灵活运用
*/
关于结果我只是在串口上面进行打印了,时间紧迫,就先记录了下关于此模块的运用,后续时间充足我会把IIC的时序讲解,写出来和大家一起探讨。
关于以上代码的格式,有些没有对齐,我现在实在是修改不了,电脑这会卡的不能行,就跟便秘一样,凑合着看吧,兄弟们。
版权声明:本文为CSDN博主「浅夏漫行」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/aaaaannnnnn_/article/details/122257391
1.BH1750基本原理讲解
BH1750作为一款数字化的光照传感器,采用的是IIC接口,本篇文章主要是侧重BH1750的应用,关于IIC总线的时序原理,请大家自行学习。
数字化的传感器,简单点理解即只要通信接口配置正确,即可读出数据,内部集成的有AD转换,但是得到的数据只是为数字量,还需要进行转换
本篇文章使用的指令只有两个:
等待测量–0X01
连续高分辨率模式–0x10
引脚的连接方式按照上图即可,初学者可能对ADDR引脚有疑问,其实简单点理解就是有两个地址:
ADDR连接GND时,地址为:0x46
ADDR连接VCC时,地址为:0xB8
本篇文章后续代码使用的地址是:0x46;
2.代码篇
函数部分:
#include "bh1750.h"
#include "delay.h"
void bh1750_Config(uint8_t mode)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
if(mode==1)
{
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
Single_Write_BH1750(0x01);
delay_ms(200);
}
void bh1750_Start(void)
{
SCK_STA(1);
SDA_OUT(1);
delay_us(5);
SDA_OUT(0);
delay_us(5);
SCK_STA(0);
}
void bh1750_Stop(void)
{
SDA_OUT(0);
SCK_STA(0);
delay_us(5);
SCK_STA(1);
delay_us(5);
SDA_OUT(1);
delay_us(5);
/*
这样写也可以
SDA_OUT(0);
SCK_STA(1);
delay_us(5);
SDA_OUT(1);
delay_us(5);
*/
}
//发送应答信号
//ack--0 应答
void bh1750_SendAck(u8 ack)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
SCK_STA(0);//时钟线拉低
delay_us(5);
if(ack==1)
{
SDA_OUT(1);
}
else if(ack==0)
{
SDA_OUT(0);
}
else return;
SCK_STA(1);
delay_us(5);
SCK_STA(0);
delay_us(5);
}
uint8_t bh1750_RevAck(void)
{
uint8_t revack=0xff;
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
SCK_STA(1);
delay_us(5);
if(SDA_IN==1)
{
revack=1;
}
else if(SDA_IN==0)
{
revack=0;
}
SCK_STA(0);
delay_us(5);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
return revack;
}
void bh1750_SendData(uint8_t data)
{
uint8_t i=0;
SCK_STA(0);
for(i=0;i<8;i++)
{
if((data& 0x80))
{
SDA_OUT(1);
}
else SDA_OUT(0);
data<<=1;
SCK_STA(1);
delay_us(5);
SCK_STA(0);
delay_us(5);
}
bh1750_RevAck();
}
uint8_t bh1750_RevData(void)
{
u8 i=0;
u8 revdata=0;
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//SDA_OUT(1);
for(i=0;i<8;i++)
{
revdata<<=1;
SCK_STA(1);
delay_us(5);
if(SDA_IN)
{
revdata |=0X01;
}
SCK_STA(0);
delay_us(5);
}
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
return revdata;
}
//数据接收函数
void Single_Write_BH1750(u8 REG_Address)//REG_Address是要写入的指令
{
bh1750_Start(); //起始信号
bh1750_SendData(SLAVEADDR); //发送设备地址+写信号
bh1750_SendData(REG_Address); //写入指令
bh1750_Stop(); //发送停止信号
}
uint8_t rev_buf[2]={0};
void read_BH1750(void)
{
uint8_t i;
bh1750_Start();
bh1750_SendData(SLAVEADDR+1);
for(i=0;i<2;i++)
{
rev_buf[i]=bh1750_RevData();
if(i==2)
{
bh1750_SendAck(1);//非应答
}
else bh1750_SendAck(0);//应答
}
bh1750_Stop();
delay_ms(5);
}
//整理数据
float get_BH1750Data(void)
{
int data=0;
float tmp1=0;
float tmp2=0;
Single_Write_BH1750(REG_CMD);//上电
Single_Write_BH1750(HIGH_MEASUCMD);//高分辨率测量
delay_ms(200);
read_BH1750();//读取数据
data=rev_buf[0];
data=(data<<8)|rev_buf[1];
tmp1=data/1.
return tmp1;
}
声明部分:
#ifndef __BH1750_H__
#define __BH1750_H__
#define SLAVEADDR 0x46
#define REG_CMD 0x01 //通电 开始写入
#define HIGH_MEASUCMD 0x10 //高分辨率模式,此模式下通电后需要等待180ms左右设备才可以工作
#define INPUT_MODE 0
#define OUTPUT_MODE 1
#define SCK_STA(x) x?(GPIO_SetBits(GPIOA,GPIO_Pin_2)):(GPIO_ResetBits(GPIOA,GPIO_Pin_2))
#define SDA_OUT(x) x?(GPIO_SetBits(GPIOA,GPIO_Pin_3)):(GPIO_ResetBits(GPIOA,GPIO_Pin_3))
#define SDA_IN GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_3)
void bh1750_Config(uint8_t mode);
void bh1750_Start(void);
void bh1750_Stop(void);
void bh1750_SendAck(u8 ack);
uint8_t bh1750_RevAck(void);
void bh1750_SendData(uint8_t data);
uint8_t bh1750_RevData(void);
void Single_Write_BH1750(u8 REG_Address);
void read_BH1750(void);
float get_BH1750Data(void);
#endif
/*
BH1750代码中的重点,当然了也是IIC通信中的重点(是我个人感觉这个是重点)
响应部分的时序分析:
1.先说发送应答部分,意味着是主机发送应答,重点在于是否还要接受数据,因此我们需要整理,应答信号,也就是想好此时
我们是需要发送0还是1,这个时候一定要注意,时钟线是需要设置为低电平的,因为只有时钟为低电平的时候,我们才可以改变SDA线路上的电平状态,设置好应答信号之后,紧接着拉高时钟电平,这个时候就是发送数据到从机。
2.再说接收应答部分,意味着我们的MCU只要接收应答即可,说明应答信号在模块内部已经整好了,那么我们只需要将时钟线拉高,等待接收即可,接收完毕之后,再把时钟线拉低,进行延时,等待模块处理数据
以上两点,是我在看了好多IIC时序中得到的一点经验,大佬们也许会感觉这个东西没什么,但是我把这个点着重说出来了,希望初学者可以少走弯路。大家可以自习的想一下IIC的时序,这个时序其实不难,但是为什么在写的过程中总是出现问题,模拟IIC对
延时和状态的切换要求是比较严格的。
最后想说的就是,在IIC的接收和发送函数中是和应答这一块是一个道理,大家可以自习比较下,先按照标准的IIC时序就行配置理解关于IIC其实好多模块在应用的过程中都会有些不一样,这个就需要大家区查看相应的模块手册。
关于IIC的使用,我会在后续再找两个模块进行讲解比较,关于这些基础类的之后还是需要大家多去使用,多去思考,才能灵活运用
*/
关于结果我只是在串口上面进行打印了,时间紧迫,就先记录了下关于此模块的运用,后续时间充足我会把IIC的时序讲解,写出来和大家一起探讨。
关于以上代码的格式,有些没有对齐,我现在实在是修改不了,电脑这会卡的不能行,就跟便秘一样,凑合着看吧,兄弟们。
版权声明:本文为CSDN博主「浅夏漫行」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/aaaaannnnnn_/article/details/122257391
暂无评论