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);
}
}
运行效果
打开串口调试助手文章来源:https://www.toymoban.com/news/detail-410149.html
完整工程下载!!!文章来源地址https://www.toymoban.com/news/detail-410149.html
到了这里,关于STM32F103ZET6+IIC+BH1750光照强度传感的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!