STM32F103ZET6+IIC+BH1750光照强度传感

STM32F103ZET6+IIC+BH1750光照强度传感

为了加深对IIC协议的理解和应用,接下来,使用STM32驱动BH1750光照强度传感器

准备IIC协议

其实IIC协议还是之前的驱动温湿度传感的那个,只是把GPIO引脚口改了一下,同理,之后遇到使用IIC协议驱动的传感器,都可以用这个定义的IIC协议。

1、声明GPIO和IIC初始化

void BH1750_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(BH_SCL_GPIO_CLK | BH_SDA_GPIO_SDA, ENABLE);

  GPIO_InitStructure.GPIO_Pin = BH_SCL_GPIO_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(BH_SCL_GPIO_PORT, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = BH_SDA_GPIO_PIN;
  GPIO_Init(BH_SDA_GPIO_PORT, &GPIO_InitStructure);
	
  Single_Write_BH1750(0x01);  //初始化BH1750
  delay_ms(180);
	
}

2、IIC数据线的输出模式
因为在IIC数据线输出数据前,需要将数据线设置为输出模式才行

void SDA_OUT(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = BH_SDA_GPIO_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(BH_SDA_GPIO_PORT, &GPIO_InitStructure);
}

3、IIC数据线的输入模式
同样在IIC数据线输入数据前,需要将数据线设置为输入模式才行

void SDA_IN(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = BH_SDA_GPIO_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(BH_SDA_GPIO_PORT, &GPIO_InitStructure);
}

4、IIC起始信号

void BH_IIC_Start(void)
{
  SDA_OUT();
  BH_SDA = 1;
  BH_SCL = 1;
  delay_us(20);

  BH_SDA = 0;	
  delay_us(20);
  BH_SCL = 0; 
}

5、IIC停止信号

void BH_IIC_Stop(void)
{
  SDA_OUT();
  BH_SCL = 0;
  BH_SDA = 0;	
  delay_us(20);
  BH_SCL = 1;
  BH_SDA = 1;
  delay_us(20);
}

6、IIC等待应答信号
返回值:1,接收应答失败;0,接收应答成功。

u8 BH_IIC_Wait_Ack(void)
{
  u8 ucErrTime = 0;
  SDA_IN();
  BH_SDA = 1;
  delay_us(10);
  BH_SCL = 1;
  delay_us(10);
  while(BH_SDA_READ())
  {
    ucErrTime++;
    if(ucErrTime > 250)
    {
      BH_IIC_Stop();
      return 1;
    }
  }
  BH_SCL = 0;  
  return 0;
}

7、IIC产生应答信号

void BH_IIC_Ack(void)
{
  BH_SCL = 0;
  SDA_OUT();
  BH_SDA = 0;
  delay_us(20);
  BH_SCL = 1;
  delay_us(20);
  BH_SCL = 0;
}

8、IIC不产生应答信号

void BH_IIC_NAck(void)
{
  BH_SCL = 0;
  SDA_OUT();
  BH_SDA = 1;
  delay_us(20);
  BH_SCL = 1;
  delay_us(20);
  BH_SCL = 0;
}

9、IIC发送一个字节
返回从机有无应答,1,有应答;0,无应答。

void BH_IIC_Send_Byte(u8 txd)
{
  u8 t;
  SDA_OUT();
  BH_SCL = 0; 	 
  for(t = 0; t < 8; t++)
  {
    if((txd & 0x80) >> 7)
      BH_SDA = 1;
    else
      BH_SDA = 0;
    txd <<= 1;
    delay_us(20);
    BH_SCL = 1;
    delay_us(20);
    BH_SCL = 0;
    delay_us(20);
  }
  delay_us(20);

}

10、IIC读取一个字节
读取字节时,ask=1,产生应答;ask=0,不产生应答

u16 BH_IIC_Read_Byte(u8 ack)
{
  u8 i;
  u16 receive = 0;
  SDA_IN();
  for(i = 0; i < 8; i++ )
  {
    BH_SCL = 0;
    delay_us(20);
    BH_SCL = 1;
    receive <<= 1;
    if(BH_SDA_READ())
      receive++;
    delay_us(20);
  }
  if (!ack)
    BH_IIC_NAck();
  else
    BH_IIC_Ack(); 
  return receive;
}

光照强度传感器的驱动过程

BH1750数据手册下载

在这里插入图片描述
在这里插入图片描述
驱动代码如下:

void Single_Write_BH1750(unsigned char REG_Address)
{
  BH_IIC_Start();                  
  BH_IIC_Send_Byte(BHAddWrite);   
  BH_IIC_Send_Byte(REG_Address);    
  BH_IIC_Stop();                   
}

//BH1750发送数据
void BH_Data_Send(u8 command)
{
    do{
			BH_IIC_Start();                      
			BH_IIC_Send_Byte(BHAddWrite);       
    }while(BH_IIC_Wait_Ack());          
			BH_IIC_Send_Byte(command);         
			BH_IIC_Wait_Ack();                  
			BH_IIC_Stop();                     
}

//BH1750读取数据
u16 BH_Data_Read(void)
{
	u16 buf;
	u8 a;
	u8 b;
	BH_IIC_Start();                       
	BH_IIC_Send_Byte(BHAddRead);         
	BH_IIC_Wait_Ack();                  
	b=BH_IIC_Read_Byte(1);
	a=BH_IIC_Read_Byte(0);
	buf=b*256+a;   
	BH_IIC_Stop();                      
	return buf; 
}

在之前的USART工程上,新建两个文件,一个是BH1750.h文件,另一个是BH1750.c文件

BH1750.h文件的代码如下:

#ifndef __bh1750_H
#define __bh1750_H	 

#include "sys.h"
#include "delay.h"

#define  BH_SCL   PBout(0)
#define  BH_SDA   PBout(1)

// GPIO 引脚定义
#define  BH_SCL_GPIO_CLK        RCC_APB2Periph_GPIOB
#define  BH_SCL_GPIO_PORT       GPIOB
#define  BH_SCL_GPIO_PIN        GPIO_Pin_0

#define  BH_SDA_GPIO_SDA        RCC_APB2Periph_GPIOB
#define  BH_SDA_GPIO_PORT       GPIOB
#define  BH_SDA_GPIO_PIN        GPIO_Pin_1

#define  BH_SDA_READ()           GPIO_ReadInputDataBit(BH_SDA_GPIO_PORT, BH_SDA_GPIO_PIN)


#define ADDR 0x23                //0100011
#define BHAddWrite     0x46      //从机地址+最后写方向位
#define BHAddRead      0x47      //从机地址+最后读方向位
#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_GPIO_Init(void);
void SDA_OUT(void);
void SDA_IN(void);
void BH_IIC_Start(void);
void BH_IIC_Stop(void);
u8 BH_IIC_Wait_Ack(void);
void BH_IIC_Ack(void);
void BH_IIC_NAck(void);
void BH_IIC_Send_Byte(u8 txd);
u16 BH_IIC_Read_Byte(u8 ack);


void Single_Write_BH1750(unsigned char REG_Address);
void BH_Data_Send(u8 command);
u16 BH_Data_Read(void);

#endif

BH1750.c文件的代码如下:

#include "BH1750.h"


void BH1750_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(BH_SCL_GPIO_CLK | BH_SDA_GPIO_SDA, ENABLE);

  GPIO_InitStructure.GPIO_Pin = BH_SCL_GPIO_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(BH_SCL_GPIO_PORT, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = BH_SDA_GPIO_PIN;
  GPIO_Init(BH_SDA_GPIO_PORT, &GPIO_InitStructure);
	
  Single_Write_BH1750(0x01);
  delay_ms(180);
	
}

void SDA_OUT(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = BH_SDA_GPIO_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(BH_SDA_GPIO_PORT, &GPIO_InitStructure);
}

void SDA_IN(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = BH_SDA_GPIO_PIN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(BH_SDA_GPIO_PORT, &GPIO_InitStructure);
}


void BH_IIC_Start(void)
{
  SDA_OUT();
  BH_SDA = 1;
  BH_SCL = 1;
  delay_us(20);

  BH_SDA = 0;
  delay_us(20);
  BH_SCL = 0;
}

void BH_IIC_Stop(void)
{
  SDA_OUT();
  BH_SCL = 0;
  BH_SDA = 0;
  delay_us(20);
  BH_SCL = 1;
  BH_SDA = 1;
  delay_us(20);
}

u8 BH_IIC_Wait_Ack(void)
{
  u8 ucErrTime = 0;
  SDA_IN();
  BH_SDA = 1;
  delay_us(10);
  BH_SCL = 1;
  delay_us(10);
  while(BH_SDA_READ())
  {
    ucErrTime++;
    if(ucErrTime > 250)
    {
      BH_IIC_Stop();
      return 1;
    }
  }
  BH_SCL = 0;  
  return 0;
}

void BH_IIC_Ack(void)
{
  BH_SCL = 0;
  SDA_OUT();
  BH_SDA = 0;
  delay_us(20);
  BH_SCL = 1;
  delay_us(20);
  BH_SCL = 0;
}

void BH_IIC_NAck(void)
{
  BH_SCL = 0;
  SDA_OUT();
  BH_SDA = 1;
  delay_us(20);
  BH_SCL = 1;
  delay_us(20);
  BH_SCL = 0;
}

void BH_IIC_Send_Byte(u8 txd)
{
  u8 t;
  SDA_OUT();
  BH_SCL = 0; 	 
  for(t = 0; t < 8; t++)
  {
    if((txd & 0x80) >> 7)
      BH_SDA = 1;
    else
      BH_SDA = 0;
    txd <<= 1;
    delay_us(20);
    BH_SCL = 1;
    delay_us(20);
    BH_SCL = 0;
    delay_us(20);
  }
  delay_us(20);

}

u16 BH_IIC_Read_Byte(u8 ack)
{
  u8 i;
  u16 receive = 0;
  SDA_IN();
  for(i = 0; i < 8; i++ )
  {
    BH_SCL = 0;
    delay_us(20);
    BH_SCL = 1;
    receive <<= 1;
    if(BH_SDA_READ())
      receive++;
    delay_us(20);
  }
  if (!ack)
    BH_IIC_NAck();
  else
    BH_IIC_Ack();
  return receive;
}

void Single_Write_BH1750(unsigned char REG_Address)
{
  BH_IIC_Start();                  
  BH_IIC_Send_Byte(BHAddWrite);   
  BH_IIC_Send_Byte(REG_Address);    
  BH_IIC_Stop();                   
}

void BH_Data_Send(u8 command)
{
    do{
			BH_IIC_Start();                      
			BH_IIC_Send_Byte(BHAddWrite);       
    }while(BH_IIC_Wait_Ack());          
			BH_IIC_Send_Byte(command);         
			BH_IIC_Wait_Ack();                  
			BH_IIC_Stop();                     
}

u16 BH_Data_Read(void)
{
	u16 buf;
	u8 a;
	u8 b;
	BH_IIC_Start();                       
	BH_IIC_Send_Byte(BHAddRead);         
	BH_IIC_Wait_Ack();                  
	b=BH_IIC_Read_Byte(1);
	a=BH_IIC_Read_Byte(0);
	buf=b*256+a;   
	BH_IIC_Stop();                      
	return buf; 
}

main.c文件的代码如下:

#include "stm32f10x.h"
#include <stdio.h>
#include "led.h"
#include "USART_Init_Config.h"
#include "BH1750.h"


int main(void)
{
	int x=0;
	float c;
    delay_init();	     //延时函数初始化	  
	LED_Init();          //LED灯初始化
    USART_Init_Config(); //串口初始化
	BH1750_GPIO_Init();  //初始化BH1750
	
	BH_Data_Send(BHPowOn); 
	delay_ms(2000); 
    
	while(1)
	{
		BH_Data_Send(BHReset);
		BH_Data_Send(BHModeH1); 	
		delay_ms(180);
		x=BH_Data_Read();
		c=x/1.2;
		printf("光照强度为:%0.2f",c);
		delay_ms(1000); 
	}
		
}


运行效果

打开串口调试助手

在这里插入图片描述
完整工程下载!!!

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值