admin管理员组

文章数量:1794759

STM32之BH1750光照强度模块(GY

STM32之BH1750光照强度模块(GY

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下载

本文标签: 模块光照强度GY