BH1750传感器驱动实现(基于STM32F103标准库)

BH1750.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "BH1750.h"

/* SDA引脚状态控制函数 */
void BH1750_W_SDA(uint8_t BitVal)
{
    GPIO_WriteBit(GPIOB, GPIO_Pin_12, (BitAction)BitVal);    
    Delay_us(10);
}

/* SCL引脚状态控制函数 */
void BH1750_W_SCL(uint8_t BitVal)
{
    GPIO_WriteBit(GPIOB, GPIO_Pin_13, (BitAction)BitVal);
    Delay_us(10);    
}

/* SDA引脚状态读取函数 */
uint8_t BH1750_R_SDA(void)
{
    Delay_us(10);
    return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12);    
}

/* 初始化BH1750相关引脚 */
void BH1750_Init(void)
{
    /*开启时钟*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);        //开启GPIOA的时钟
    
    /*GPIO初始化*/
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);                        //将PB12(SDA)和PB13(SCL)引脚初始化为开漏输出
    
    /*设置SDA与SCL初始化后的默认电平,均为释放状态*/
    BH1750_W_SDA(1);
    BH1750_W_SCL(1);
    
    BH1750_SendCommand(BHPowOn);    //BH1750上电
    BH1750_SendCommand(BHReset);    //BH1750复位
    BH1750_SendCommand(BHModeH1);   //连续高分辨率模式1
}


/*****************  通信协议层  *******************/
/* 起始条件 */
void BH1750_Start(void)
{
    BH1750_W_SDA(1);
    BH1750_W_SCL(1);
    BH1750_W_SDA(0);
    BH1750_W_SCL(0);    
}

/* 终止条件 */
void BH1750_Stop(void)
{
    //BH1750_W_SCL(0);  //每个时序基本单元最后会拉低SCL因此此处可以不用拉低SCL
    BH1750_W_SDA(0);
    BH1750_W_SCL(1);
    BH1750_W_SDA(1);    
}

/* 主机发送一个字节 */
void BH1750_SendByte(uint8_t Data)
{
    for(uint8_t i = 0; i < 8; i++)
    {
        BH1750_W_SDA(Data & (0x80 >> i));
        BH1750_W_SCL(1);   //从机读取数据
        BH1750_W_SCL(0);   //主机改变SDA引脚状态        
    }    
}

/* 主机接收一个字节 */
uint8_t BH1750_ReceiveByte(void)
{
    uint8_t Data = 0x00;
    BH1750_W_SDA(1);  //接收前主机需要先释放SDA线
    for(uint8_t i = 0; i < 8; i++)
    {
        BH1750_W_SCL(1);
        if(BH1750_R_SDA())
            Data |= (0x80 >> i);
        BH1750_W_SCL(0);  //从机改变SDA引脚状态    
    }    
    return Data;
}

/* 接收应答 */
uint8_t BH1750_ReceiveAck(void)
{
    uint8_t Ack = 0;
    BH1750_W_SDA(1);   //主机释放SDA线,此时从机会改变SDA引脚状态
    BH1750_W_SCL(1);
    Ack = BH1750_R_SDA();
    BH1750_W_SCL(0);
    return Ack;
}

/* 发送应答 */
void BH1750_SendAck(uint8_t SendAck)
{
    BH1750_W_SDA(SendAck);
    BH1750_W_SCL(1);   //从机会读取SDA引脚状态,判断主机是否应答
    BH1750_W_SCL(0);    
}

/*****************  主机与从机通信层  *******************/
/* 主机给从机发送指令 */
void BH1750_SendCommand(uint8_t Command)
{
    uint32_t TimeOut = 0;
    BH1750_Start();
    BH1750_SendByte(BHAddWrite);  //发送从机地址与读写位,写命令
    
    while(BH1750_ReceiveAck())   //等待从机应答
    {
        TimeOut ++;
        if(TimeOut > 100000)
            break;  //从此处退出表示从机超时未应答
    }
    BH1750_SendByte(Command);
    
    while(BH1750_ReceiveAck())   //等待从机应答
    {
        TimeOut ++;
        if(TimeOut > 100000)
            break;  //从此处退出表示从机超时未应答
    }
    BH1750_Stop();
}

/* 主机接收从机传来的信息 */
uint16_t BH1750_ReceiveData(void)
{
    Delay_ms(120);
    uint32_t TimeOut = 0;    
    uint16_t Data = 0x0000;
    BH1750_Start();
    BH1750_SendByte(BHAddRead);  //发送从机地址与读写位,读命令
    while(BH1750_ReceiveAck())   //等待从机应答
    {
        TimeOut ++;
        if(TimeOut > 100000)
            break;  //从此处退出表示从机超时未应答
    }
    Data = BH1750_ReceiveByte();
    BH1750_SendAck(0);  //主机接收到信息应答,还需要从机发送的信息
    Data <<= 8;
    Data |= BH1750_ReceiveByte();
    BH1750_SendAck(1);  //主机接收到信息非应答,不需要从机发送的信息
    BH1750_Stop();
    return Data;
}

/* 将从 从机接收到的原始数据转化为光照强度 */
float BH1750_Light(void)
{
    uint16_t Light = 0;
    uint16_t result = 1, Data = BH1750_ReceiveData();
    for(uint8_t i = 0; i < 16; i++)
    {
        if(Data & (0x8000 >> i))
        {
            for(uint8_t j = 0; j < (15 - i); j ++)
            {
                result *= 2;                
            }
            Light += result;
            result = 1;
        }
    }
    return (float)Light / 1.2;
}

BH1750.h

#ifndef __BH1750_H
#define __BH1750_H


void BH1750_Init(void);


/********************* 指令集 **********************/
#define BHAddWrite     0x46      //从机地址“0100011”+最后写方向位
#define BHAddRead      0x47      //从机地址“0100011”+最后读方向位
#define BHPowDown      0x00      //关闭模块
#define BHPowOn        0x01      //打开模块等待测量指令
#define BHReset        0x07      //重置数据寄存器值在PowerOn模式下有效
#define BHModeH1       0x10      //高分辨率 单位1lx 测量时间120ms
#define BHModeH2       0x11      //高分辨率模式2 单位0.5lx 测量时间120ms
#define BHModeL        0x13      //低分辨率 单位4lx 测量时间16ms
#define BHSigModeH     0x20      //一次高分辨率 测量 测量后模块转到 PowerDown模式
#define BHSigModeH2    0x21      //同上类似
#define BHSigModeL     0x23      // 上类似

/*****************  通信协议层  *******************/
void BH1750_Start(void);
void BH1750_Stop(void);
void BH1750_SendByte(uint8_t Data);
uint8_t BH1750_ReceiveByte(void);
uint8_t BH1750_ReceiveAck(void);
void BH1750_SendAck(uint8_t SendAck);

/*****************  通信层  *******************/
void BH1750_SendCommand(uint8_t Command);
uint16_t BH1750_ReceiveData(void);
float BH1750_Light(void);
	
	
#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "BH1750.h"
#include <stdio.h>

float Light;
char buff[7];


int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	BH1750_Init();
	
	while (1)
	{
		Light = BH1750_Light();
		sprintf(buff, "%7.2f", Light);
		OLED_ShowString(1, 1, buff);
		Delay_ms(500);
	}
}

大致实现如上,可自主加入超时退出提醒机制,OLED显示优化等......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值