STM32之BH1750光照强度模块(GY-302)C语言代码(代码稳定详细,简洁明了)

BH1750光强模块
BH1750光强模块图片

BH1750光强模块显示
BH1750光强模块数据显示

请别乱用printf!!!!!以下是printf函数重定向方法!!!!!!!!搞不懂的话,就别用,就只用光照模块部分代码

今日头条

第一部分:BH1750光强模块代码头文件(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

第二部分:BH1750光强模块代码文件(BH1750.c)

#include "BH1750.h"
/*
函数功能: IIC总线初始化
硬件连接:
        SCL-PB3
        SDA-PA15
*/
u8  BUF[3];

void IIC_Init(void)
{
  /*1. 开时钟*/
	RCC->APB2ENR|=1<<2; //PA
	RCC->APB2ENR|=1<<3; //PB
	RCC->APB2ENR|=1<<0; //开启AFIO时钟
	
	/*2. 配置模式*/
	AFIO->MAPR |= 0x2<<24;//关闭JTAG-DP,启用SW-DP
	GPIOA->CRH&=0x0FFFFFFF;
	GPIOA->CRH|=0x30000000;
	GPIOB->CRL&=0xFFFF0FFF;
	GPIOB->CRL|=0x00003000;
	
	/*3. 上拉*/
	GPIOA->ODR|=0x1<<15;
	GPIOB->ODR|=0x1<<3;
	
	//printf("BH1750 IIC_Init OK! \n");
}

/**************************************
起始信号
**************************************/
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);
}

第三部分:主函数(main.c)

#include "stm32f10x.h"
#include "config.h"
#include "usart.h"
#include "delay.h"
#include "string.h"
#include "stdio.h"
#include "BH1750.h"

int main(void)
{
	u8 i=0;
	USARTx_Init(USART1,72,115200); 
	TIMERx_Init(TIM1,72,20000);   //辅助串口1接收。20ms为一帧数据。	
	IIC_Init();//BH1750初始化
	while(1)
	{	
		Get_Sunlight_Value();//获取光照强度值
		DelayMs(2000);	
	}	
}
	

第四部分:USARTx_Init(USART1,72,115200);//printf串口打印


void USARTx_Init(USART_TypeDef *USARTx,int clock,int baud)
{
	if(USARTx==USART1)
	{
		/*1.开总线GPIOA的时钟*/
		RCC->APB2ENR |= 1<<2;
		/*2.设置GPIOA口模式 PA9--TX(1011)  PA10--RX(1000)*/
		GPIOA->CRH &= 0xFFFFF00F;
		GPIOA->CRH |= 0x000008B0;
		/*3.开USART1时钟*/	
		RCC->APB2ENR |= 1<<14;//使能USART1
		RCC->APB1RSTR |= 1<<14;//开启复位USART1
		RCC->APB1RSTR &= ~(1<<14);//关闭复位USART1 
		/*4.设置USARTx中断 */
#ifdef USART1_IRQ_RX	
  	USART1->CR1|=1<<5;  //开启串口接收中断
	  STM32_NVIC_SetPriority(USART1_IRQn,0,0); //优先级设置
#endif
	}
	else if(USARTx==USART2)
	{
		/*1.开总线GPIOA的时钟*/
		RCC->APB2ENR |= 1<<2;
		/*2.设置GPIOA口模式 PA2--TX(1011)  PA3--RX(1000)*/
		GPIOA->CRL &= 0xFFFF00FF;
		GPIOA->CRL |= 0x00008B00;
		/*3.开USART2时钟*/	
		RCC->APB1ENR |= 1<<17;//使能USART2
		RCC->APB1RSTR |= 1<<17;//开启复位USART2
		RCC->APB1RSTR &= ~(1<<17);//关闭复位USART2 
		/*4.设置USARTx中断 */
#ifdef USART2_IRQ_RX	
  	USART2->CR1|=1<<5;  //开启串口接收中断
	  STM32_NVIC_SetPriority(USART2_IRQn,1,0); //优先级设置
#endif		
	}
	else if(USARTx==USART3)
	{
		/*1.开总线GPIOB的时钟*/
		RCC->APB2ENR |= 1<<3;
		/*2.设置GPIOB口模式 PB10--TX(1011)  PB11--RX(1000)*/
		GPIOB->CRH &= 0xFFFF00FF;
		GPIOB->CRH |= 0x00008B00;
		/*3.开USART3时钟*/	
		RCC->APB1ENR |= 1<<18;//使能USART3
		RCC->APB1RSTR |= 1<<18;//开启复位USART3
		RCC->APB1RSTR &= ~(1<<18);//关闭复位USART3
		/*4.设置USARTx中断 */
#ifdef USART3_IRQ_RX	
  	USART3->CR1|=1<<5;  //开启串口接收中断
	  STM32_NVIC_SetPriority(USART3_IRQn,2,0); //优先级设置
#endif
	}
	else 
	{
		printf("%s串口参数错误!!!\n","USARTx");
		return ;
	}
	/*5.设置USARTx波特率*/
	USARTx->BRR = clock*1000000/baud; //brr=clock/baud
	/*6.设置USARTx控制寄存器 */
	USARTx->CR1 |= 1<<2;//使能接收
	USARTx->CR1 |= 1<<3;//使能发送
	USARTx->CR1 |= 1<<13;//USARTx模块使能
}

第五部分:printf重定向函数


/********************************
将标准输入输出重定向到USART1
********************************/

int fputc(int c ,FILE *stream)
{
	USART1->DR = c;
	while(!(USART1->SR&1<<7));//等待数据发送完成
	return c;
}

int fgetc(FILE *stream)
{
	while(!(USART1->SR&1<<5));//等待数据	
	return USART1->DR;
}

第六部分:初始化定时器 TIMERx_Init(TIM1,720,10000); 


/*函数功能: 初始化定时器
函数形参:
		u32 psc :预分频系数
		u32 arr :重装载计数器*/
		
void TIMERx_Init(TIM_TypeDef *TIMx,u32 psc,u32 arr)
{
	if(TIMx==TIM1)
	{
		RCC->APB2ENR|=1<<11;
		RCC->APB2RSTR|=1<<11;
		RCC->APB2RSTR&=~(1<<11);
#ifdef	 TIME1_UP_IRQ
		TIMx->DIER|=1<<0;//配置更新中断
		STM32_NVIC_SetPriority(TIM1_UP_IRQn,1,0); //设置中断优先级
		printf("TIM1_Init OK!\n");
#endif	
		
	}
	else if(TIMx==TIM2)
	{
		RCC->APB1ENR|=1<<0;
		RCC->APB1RSTR|=1<<0;
		RCC->APB1RSTR&=~(1<<0);
#ifdef	 TIME2_UP_IRQ
		TIMx->DIER|=1<<0;//配置更新中断
		STM32_NVIC_SetPriority(TIM2_IRQn,1,0); //设置中断优先级
		printf("TIM2_Init OK!\n");
#endif	
		
	}
	else if(TIMx==TIM3)
	{
		RCC->APB1ENR|=1<<1;
		RCC->APB1RSTR|=1<<1;
		RCC->APB1RSTR&=~(1<<1);
#ifdef	 TIME3_UP_IRQ
		TIMx->DIER|=1<<0;//配置更新中断
		STM32_NVIC_SetPriority(TIM3_IRQn,1,0); //设置中断优先级
		printf("TIM3_Init OK!\n");
#endif	
	}
	else if(TIMx==TIM4)
	{
		RCC->APB1ENR|=1<<2;
		RCC->APB1RSTR|=1<<2;
		RCC->APB1RSTR&=~(1<<2);
#ifdef	 TIME4_UP_IRQ
	TIMx->DIER|=1<<0;//配置更新中断
	STM32_NVIC_SetPriority(TIM4_IRQn,1,0); //设置中断优先级
	printf("TIM4_Init OK!\n");
#endif
	}
	else 
	{
		printf("TIMx_Init ERROR!\n");
		return;
	}

	/*配置定时器核心寄存器*/
	TIMx->PSC=psc-1; //预分频器
	TIMx->ARR=arr;   //重装载寄存器
	TIMx->CR1|=1<<7; //开启缓存功能
	//TIMx->CR1|=1<<0; //开启定时器
	TIMx->CR1&=~(1<<0); //关闭定时器
}

实物工程源码下载:

农业大棚环境监测(温湿度+二氧化碳浓度+光照强度+时间+OLED显示+ESP8266连网+EEPROM)-C文档类资源-CSDN下载

  • 39
    点赞
  • 295
    收藏
    觉得还不错? 一键收藏
  • 44
    评论
评论 44
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值