BH1750.h 头文件
#ifndef BH1750_H
#define BH1750_H
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
//IIC总线地址接口定义
#define IIC_SCL PBout(3)
#define IIC_SDA_OUT PAout(15)
#define IIC_SDA_IN PAin(15)
#define IIC_INPUT_MODE_SET() {GPIOA->CRH&=0x0FFFFFFF;GPIOA->CRH|=0x80000000;}
#define IIC_OUTPUT_MODE_SET() {GPIOA->CRH&=0x0FFFFFFF;GPIOA->CRH|=0x30000000;}
#define IIC_WRITE 0 // 写
#define IIC_READ 1 // 读
#define SlaveAddress 0x46 //BH1750地址
extern u8 BUF[3];
//函数声明
void IIC_Init(void);
void BH1750_Start();
void BH1750_Stop();
void BH1750_SendACK(char ack);
char BH1750_RecvACK();
void BH1750_SendByte(u8 data);
void Single_Write_BH1750(u8 REG_Address);
void Multiple_Read_BH1750();
void Get_Sunlight_Value();
u8 BH1750_RecvByte();
#endif
2.BH1750模块驱动,BH1750.C
#include "BH1750.h"
/*
函数功能: IIC总线初始化
硬件连接:
SCL-PB10
SDA-PB11
*/
u8 BUF[3];
void MyI2C_W_SCL(uint8_t BitValue) //定义SCL PB10
{
GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);
Delay(10);
}
void MyI2C_W_SDA(uint8_t BitValue) //定义SDA PB11
{
GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);
Delay(10);
}
uint8_t MyI2C_R_SDA()
{
uint8_t BitValue;
BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);
Delay(10);
return BitValue;
}
void MyI2C_Init(void) //初始化 IIC
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);
}
/**************************************
起始信号
**************************************/
void BH1750_Start()
{
IIC_OUTPUT_MODE_SET(); //配置输出模式
IIC_SDA_OUT = 1; //拉高数据线
IIC_SCL = 1; //拉高时钟线
DelayUs(5); //延时
IIC_SDA_OUT = 0; //产生下降沿
DelayUs(5); //延时
IIC_SCL = 0; //拉低时钟线
}
/*
函数功能: 停止信号
*/
void BH1750_Stop()
{
IIC_OUTPUT_MODE_SET(); //配置输出模式
IIC_SDA_OUT = 0; //拉低数据线
IIC_SCL = 1; //拉高时钟线
DelayUs(5); //延时
IIC_SDA_OUT = 1; //产生上升沿
DelayUs(5); //延时
}
/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void BH1750_SendACK(char ack)
{
IIC_OUTPUT_MODE_SET(); //配置输出模式
IIC_SCL = 0; //拉低时钟线
if(ack) IIC_SDA_OUT = 1;
else IIC_SDA_OUT = 0; //写应答信号
DelayUs(2); //延时
IIC_SCL = 1; //拉高时钟线
DelayUs(5); //延时
IIC_SCL = 0; //拉低时钟线
}
/**************************************
接收应答信号
**************************************/
char BH1750_RecvACK()
{
u8 cnt=0;
IIC_INPUT_MODE_SET();//输入模式
IIC_SDA_OUT=1;
DelayUs(1);
IIC_SCL=1;
DelayUs(1);
while(IIC_SDA_IN)//等待应答
{
cnt++;
DelayUs(1);
if(cnt>=250)//等待时间过长,产生停止信号,返回1,表示接收应答失败
{
BH1750_Stop();
//printf("N0 ACK\n");
return 1;
}
}
IIC_SCL=0;//应答成功,则SCL变低
return 0;
}
/**************************************
向IIC总线发送一个字节数据
**************************************/
void BH1750_SendByte(u8 data)
{
u8 i;
IIC_OUTPUT_MODE_SET();
IIC_SCL = 0;//拉低时钟线, 数据准备发送
DelayUs(2);//延时
for (i=0;i<8;i++)//从高位开始一位一位地传送
{
if(data&0x80) IIC_SDA_OUT=1;//送数据口
else IIC_SDA_OUT=0;
data <<= 1;//移出数据的最高位
IIC_SCL = 1; //拉高时钟线,发送数据
DelayUs(2);//延时
IIC_SCL = 0;//拉低时钟线,数据发送完毕
DelayUs(2);//延时
}
}
/**************************************
从IIC总线接收一个字节数据
**************************************/
u8 BH1750_RecvByte()
{
u8 i;
u8 data = 0;
IIC_INPUT_MODE_SET();//使能内部上拉,准备读取数据,
for (i=0;i<8;i++)//8位计数器
{
IIC_SCL=0;//置时钟线为低,准备接收数据位
DelayUs(2);//时钟低电平周期大于4.7μs
IIC_SCL=1;//置时钟线为高使数据线上数据有效,主机开始读数据,从机不能再改变数据了,即改变SDA的电平
data <<= 1;
IIC_SCL = 1;//拉高时钟线
if(IIC_SDA_IN) data|=0x01;//读数据
DelayUs(1);//延时
}
IIC_SCL=0;
return data;
}
void Single_Write_BH1750(u8 REG_Address)
{
BH1750_Start();//起始信号
BH1750_SendByte(SlaveAddress);//发送设备地址+写信号
BH1750_RecvACK();
BH1750_SendByte(REG_Address);//内部寄存器地址,请参考中文pdf22页
BH1750_RecvACK();
BH1750_Stop();//发送停止信号
}
/*********************************************************
连续读出BH1750内部数据
*********************************************************/
void Multiple_Read_BH1750()
{
BH1750_Start();//起始信号
BH1750_SendByte(SlaveAddress+1);//发送设备地址+读信号
BH1750_RecvACK();
BUF[0] = BH1750_RecvByte();//BUF[0]存储0x32地址中的数据
BH1750_SendACK(0);
BUF[1] = BH1750_RecvByte();//BUF[0]存储0x32地址中的数据
BH1750_SendACK(1);
BH1750_Stop();//停止信号
DelayMs(5);
}
/*********************************************************
读出数据并合成实际光强值
*********************************************************/
void Get_Sunlight_Value()
{
int dis_data=0;
float temp;
u8 i=0;
Single_Write_BH1750(0x01);// power on
Single_Write_BH1750(0x10);// H- resolution mode
DelayMs(180);//延时180ms
Multiple_Read_BH1750();//连续读出数据,存储在BUF中
for(i=0;i<3;i++)
//printf("0X%X ",BUF[i]);
dis_data=BUF[0];
dis_data=(dis_data<<8)+BUF[1];//合成数据
temp=(float)dis_data/1.2;
//printf("Sunlight=%0.2f lx\n",temp);
}
3.主函数 main.c
#include "stm32f10x.h"
#include "config.h"
#include "usart.h"
#include "delay.h"
#include "BH1750.h"
int main(void)
{
u8 i=0;
IIC_Init();//BH1750初始化
while(1)
{
Get_Sunlight_Value();//获取光照强度值
DelayMs(2000);
}
}