当前位置: 首页 > news >正文

STM32光强传感器实验详解

/*******************************************************************************
* @文件名        : main
* @描述          : 光强传感器实验
* @作者          : 物联网项目组
* @日期          : 2020/01/15
* @版本          : V2.0.0
--------------------------------------------------------------------------------
功能介绍:
1. 检测BH1750光强
1、显示屏实时显示光强:xxlx
2、串口输出光强Illumination:xxlx
*******************************************************************************/
#include "main.h"
#include "usart_api.h"
#include "stm32l4xx_hal.h"
#include "gpio_api.h" 
#include "handle.h"

/*****************************内部函数定义**************************************/    
void SystemClock_Config(void);

/********************************************************************************
* 名    称:main
* 功    能:主函数
* 参数说明:无
* 返 回 值:无
* 说    明:无
* 调用方法:内部调用
********************************************************************************/
int main(void)
{
HAL_Init();
SystemClock_Config();    
LCD_Display_Init(); //屏幕初始化显示
gpio_module_open(LEDS);        
uart_open(uart2, 115200); 

    printf("\r\n        光强检测实验        \r\n");
printf("------------------------------\r\n");
printf("开始本实验:\r\n\r\n");
/*****************************code start 1*************************************/
Init_BH1750();
/*****************************code  end  1*************************************/
printf("** 光强传感器初始化\r\n");   
while(1)
{      
Light_Intensity_Handle(); //检测光强值并显示
}
}

/********************************************************************************
* 名    称:SystemClock_Config
* 功    能:系统时钟初始化
* 参数说明:无
* 返 回 值:无
* 说    明:无
* 调用方法:内部函数
********************************************************************************/
void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;

    /**Initializes the CPU, AHB and APB busses clocks 
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 1;
RCC_OscInitStruct.PLL.PLLN = 20;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

    /**Initializes the CPU, AHB and APB busses clocks 
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART3;
PeriphClkInit.Usart3ClockSelection = RCC_USART3CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

    /**Configure the main internal regulator output voltage 
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

    /**Configure the Systick interrupt time 
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
* @brief  This function is executed in case of error occurrence.
* @param  file: The file name as string.
* @param  line: The line in file as a number.
* @retval None
*/
void _Error_Handler(char *file, int line)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */

  Gui_Printf_Display("An error message detected");

  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
* @brief  Reports the name of the source file and the source line number
*         where the assert_param error has occurred.
* @param  file: pointer to the source file name
* @param  line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)

/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/**
* @}
*/

/**
* @}
*/

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

/*------------------------------------------------------------------------------
* @文件名        : handle
* @描述          : 用户处理函数
* @作者          : 物联网项目组
* @日期          : 2023/04/01
* @版本          : V0.0.2
*******************************************************************************
功能介绍:
1、显示屏初始化显示;
2、检测光强值并显示

******************************************************************************/
#include "handle.h"
#include "gpio_api.h" 
#include "lcd.h" 
#include "stdio.h"
#include "string.h"
#include "guangxian.h"

/********************************************************************************
* 名    称:LCD_Display_Init
* 功    能:显示屏上电初始化显示
* 入口参数:无
* 返 回 值:无
* 说    明:无
* 调用方法:外部函数
********************************************************************************/
void LCD_Display_Init(void)

/*显示屏初始化界面*/
LCD_Init();       
LCD_Fill(0,lcddev.height-20,lcddev.width,lcddev.height,BLUE);
LCD_Fill(0,0,lcddev.width,20,BLUE);
Gui_StrCenter(0,2,BLUE,BLUE," ",16,0); 
Gui_StrCenter(0,40,BLUE,WHITE,"光强检测实验",24,1);  
Gui_StrCenter(0,lcddev.height-18,BLUE,BLUE," ",16,0); 
LCD_draw_bmp(96,120,48,gImage_guangxian);   //光强图标显示
}

/********************************************************************************
* 名    称:Light_Intensity_Handle
* 功    能:光强检测处理函数
* 入口参数:无
* 返 回 值:无
* 说    明:无
* 调用方法:外部函数
********************************************************************************/
void Light_Intensity_Handle(void)
{
uint16_t light_value = 0; //光强值
char  str[20]; //显示屏显示缓冲数组
static  uint32_t tickstart;
if((HAL_GetTick() - tickstart) >= 1000) //1000ms检测一次
{
tickstart = HAL_GetTick();  
memset(str,0,sizeof(str));
/*****************************code start 2*************************************/
light_value=BH1750_Handle();
/*****************************code  end  2*************************************/
if(light_value > 0 && (light_value < 54612))
{
sprintf(str,"光强: %d lx",light_value);
printf("** 读取光强传感器数据\r\n");
printf("** Illumination:%d lx\r\n\r\n", light_value);
}
else
{
sprintf(str,"光强:---");
}
LCD_Fill(90,182,230,198,WHITE);              //刷新显示
Show_Str(90,182,BLUE,WHITE,(uint8_t *)str,16,1);     //显示光强值
led_toggle(LED1_PORT);        
}    

/*-----------------------------------------------------------------------------
* @文件名        : bh1750
* @描述          : 光照强度检测驱动文件
* @作者          : 物联网项目组
* @日期          : 2023/04/01
* @版本          : V0.0.2
*******************************************************************************
本驱动函数使用指导流程:
1、添加本驱动的.c和.h文件
2、在main.c中调用Init_BH1750函数进行GPIO初始化
3、通过调用BH1750_Handle的返回值读取光照强度
4、用户要根据程序系统时钟修改SYSCLOCK的值,要不会影响延时精度
******************************************************************************/

#include "bh1750.h"

/********************************内部引脚定义***********************************/       
#define BH1750_SCL_Pin              GPIO_PIN_13        
#define BH1750_SCL_GPIO_Port        GPIOB

#define BH1750_SDA_Pin              GPIO_PIN_14        
#define BH1750_SDA_GPIO_Port        GPIOB

/********************************IO模式设置*************************************/    
#define BH1750_SDA_IN()             {GPIOB->MODER&=~(3<<(14*2));GPIOB->MODER|=0<<14*2;}          // PB14输入模式
#define BH1750_SDA_OUT()            {GPIOB->MODER&=~(3<<(14*2));GPIOB->MODER|=1<<14*2;}       // PB14输出模式

/********************************IO口函数操作***********************************/                   
#define BH1750_SCLK_Clr()     HAL_GPIO_WritePin(BH1750_SCL_GPIO_Port, BH1750_SCL_Pin, GPIO_PIN_RESET) 
#define BH1750_SCLK_Set()     HAL_GPIO_WritePin(BH1750_SCL_GPIO_Port, BH1750_SCL_Pin, GPIO_PIN_SET) 

#define BH1750_SDA_Clr()    HAL_GPIO_WritePin(BH1750_SDA_GPIO_Port, BH1750_SDA_Pin, GPIO_PIN_RESET)   
#define BH1750_SDA_Set()    HAL_GPIO_WritePin(BH1750_SDA_GPIO_Port, BH1750_SDA_Pin, GPIO_PIN_SET)

#define BH1750_READ_SDA()   HAL_GPIO_ReadPin(BH1750_SDA_GPIO_Port, BH1750_SDA_Pin)

/********************************BH1750宏定义***********************************/
#define BH1750_ADD_WRITE                 0x46   // 写数据
#define BH1750_ADD_READ                  0x47   // 读数据
#define BH1750_RSET                      0x07   // 复位
#define BH1750_POWER_ON                  0x01   // 打开模块
#define BH1750_POWER_DOWN                0x00   // 关闭模块
#define BH1750_MODE_H1                   0x10   // 高分辨率1 单位1lx
#define BH1750_MODE_H2                   0x11   // 高分辨率2 单位0.51lx
#define BH1750_MODE_L                    0x13   // 低分辨率 单位4lx

/********************************内部宏定义*************************************/
#define SYSCLOCK   80         // 系统时钟,用于延时,需要用户根据系统时钟进行修改,要不会影响精确延时,单位Mhz
#define ACK        1
#define NOACK      0
#define TURE       0  
#define ERROR      1

//******************************内部函数定义************************************/
static void delay_us(uint16_t Nus);
static void delay_ms(uint16_t Nms);
static void BH1750_GPIO_Init(void);
static void BH1750_IIC_Start(void);
static void BH1750_IIC_Stop(void);
static uint8_t BH1750_IIC_Wait_Ack(void);
static void BH1750_IIC_Ack(void);
static void BH1750_IIC_No_Ack(void);
static void BH1750_Write_Byte(uint8_t date);
static uint8_t BH1750_Read_Byte(uint8_t ack);
static void BH1750_Write_Command(uint8_t cmd);
static void Start_BH1750(void);
static uint16_t Read_BH1750(void);

/********************************************************************************
* 名    称:delay_us
* 功    能:微秒级延时
* 参数说明:Nus:延时的时间,单位us
* 返 回 值:无
* 说    明:根据系统时钟,进行延时
* 调用方法:内部函数
********************************************************************************/
static void delay_us(uint16_t Nus)
{
uint32_t i;
i = Nus * (SYSCLOCK/3);        
while(i--);
}

/********************************************************************************
* 名    称:delay_ms
* 功    能:微秒级延时
* 参数说明:nus:延时的时间,单位us
* 返 回 值:无
* 说    明:根据系统时钟,进行延时
********************************************************************************/
static void delay_ms(uint16_t Nms)
{
uint32_t i;
i = Nms * (SYSCLOCK/3) * 1000;        
while(i--);
}

/********************************************************************************
* 名    称:BH1750_GPIO_Init
* 功    能:初始化BH1750引脚
* 参数说明:无
* 返 回 值:无
* 说    明:用于配置BH1750引脚工作模式
********************************************************************************/
static void BH1750_GPIO_Init(void)
{                         
GPIO_InitTypeDef GPIO_InitStruct;

    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitStruct.Pin = BH1750_SCL_Pin | BH1750_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(BH1750_SCL_GPIO_Port, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    HAL_GPIO_WritePin(GPIOD,GPIO_PIN_12,GPIO_PIN_SET);

}

/********************************************************************************
* 名    称:BH1750_IIC_Start
* 功    能:产生IIC开始信号
* 参数说明:无
* 返 回 值:无
* 说    明:SDA高电平要延时 > 4.7us,SDA变为低电平之后
还要延时 > 4us
* 调用方法:内部函数
********************************************************************************/
static void BH1750_IIC_Start(void)
{
BH1750_SDA_OUT();     
BH1750_SDA_Set();
BH1750_SCLK_Set();
delay_us(5);
BH1750_SDA_Clr();
delay_us(5);
BH1750_SCLK_Clr();
}      

/********************************************************************************
* 名    称:BH1750_IIC_Start
* 功    能:产生IIC停止信号
* 参数说明:无
* 返 回 值:无
* 说    明:内部函数,SDA高电平要延时 > 4.7us,SDA变为低电平之后
还要延时 > 4us
* 调用方法:内部函数
********************************************************************************/
static void BH1750_IIC_Stop(void)
{
BH1750_SDA_OUT();
BH1750_SCLK_Clr();
BH1750_SDA_Clr();
delay_us(5);
BH1750_SCLK_Set();  
BH1750_SDA_Set();
delay_us(5);    
}
/********************************************************************************
* 名    称:BH1750_IIC_Wait_Ack
* 功    能:等待IIC应答信号
* 参数说明:无
* 返 回 值:TURE:接收成功
ERROR:接受失败
* 说    明:无
* 调用方法:内部函数
********************************************************************************/
static uint8_t BH1750_IIC_Wait_Ack(void)
{
uint8_t ack_time=0;

BH1750_SDA_IN();       
BH1750_SDA_Set();
delay_us(2);       
BH1750_SCLK_Set();
delay_us(2);     

while(BH1750_READ_SDA())
{
ack_time++;
delay_us(10);
if(ack_time>250)
{
BH1750_IIC_Stop();
return ERROR;
}
}
BH1750_SDA_Clr();//时钟输出0        
return TURE;  

/********************************************************************************
* 名    称:BH1750_IIC_Ack
* 功    能:产生ACK应答
* 参数说明:无
* 返 回 值:无
* 说    明:无
* 调用方法:内部函数
********************************************************************************/
static void BH1750_IIC_Ack(void)
{
BH1750_SCLK_Clr();
BH1750_SDA_OUT();
BH1750_SDA_Clr();
delay_us(2);
BH1750_SCLK_Set() ;
delay_us(2);
BH1750_SCLK_Clr();

}    
/********************************************************************************
* 名    称:BH1750_IIC_No_Ack
* 功    能:不产生ACK应答    
* 参数说明:无
* 返 回 值:无
* 说    明:无
* 调用方法:内部函数
********************************************************************************/
static void BH1750_IIC_No_Ack(void)
{
BH1750_SCLK_Clr();
BH1750_SDA_OUT();
BH1750_SDA_Set();
delay_us(2);
BH1750_SCLK_Set();
delay_us(2);
BH1750_SCLK_Clr();
}                                          

/********************************************************************************
* 名    称:BH1750_Write_Byte
* 功    能:IIC发送一个数据    
* 参数说明:date: 要发送的数据
* 返 回 值:无
* 说    明:无
* 调用方法:内部函数
********************************************************************************/
static void BH1750_Write_Byte(uint8_t date)
{                        
uint8_t i;

BH1750_SDA_OUT(); 
BH1750_SCLK_Clr();
for(i=0; i<8; i++)        
{
if((date&0x80) == 0x80)
{
BH1750_SDA_Set();
}
else
{
BH1750_SDA_Clr();
}
date = date << 1;
delay_us(2);
BH1750_SCLK_Set();
delay_us(2);
BH1750_SCLK_Clr();
delay_us(2);
}
}         

/********************************************************************************
* 名    称:BH1750_Read_Byte
* 功    能:IIC发送一个数据    
* 参数说明:ack: 1 发送ACK
0 发送nACK 
* 返 回 值:无
* 说    明:无
* 调用方法:内部函数
********************************************************************************/
static uint8_t BH1750_Read_Byte(uint8_t ack)
{
uint8_t i,receive = 0;

BH1750_SDA_IN();
for(i=0;i<8;i++ )
{
BH1750_SCLK_Clr(); 
delay_us(2);
BH1750_SCLK_Set();
receive <<= 1;
if(BH1750_READ_SDA())
receive++;   
delay_us(2); 
}                     
if (!ack)
BH1750_IIC_No_Ack();
else
BH1750_IIC_Ack();  
return receive;
}

/********************************************************************************
* 名    称:BH1750_Write_Command
* 功    能:写指令到BH1750中    
* 参数说明:cmd: 指令
* 返 回 值:无
* 说    明:功能函数
* 调用方法:内部函数
********************************************************************************/
static void BH1750_Write_Command(uint8_t cmd)
{
BH1750_IIC_Start();    
BH1750_Write_Byte(BH1750_ADD_WRITE); 
BH1750_IIC_Wait_Ack();    
BH1750_Write_Byte(cmd);    
BH1750_IIC_Wait_Ack();
BH1750_IIC_Stop();                   
}

/********************************************************************************
* 名    称:Init_BH1750
* 功    能:初始化BH1750    
* 参数说明:无
* 返 回 值:无
* 说    明:用于初始化BH1750
* 调用方法:外部函数
********************************************************************************/
void Init_BH1750(void)
{
BH1750_GPIO_Init();    
}

/********************************************************************************
* 名    称:Start_BH1750
* 功    能:开始测量光的强度    
* 参数说明:无
* 返 回 值:无
* 说    明:无
* 调用方法:内部函数
********************************************************************************/
static void Start_BH1750(void)
{
BH1750_Write_Command(BH1750_POWER_ON);     
BH1750_Write_Command(BH1750_MODE_H1);
}

/********************************************************************************
* 名    称:Read_BH1750
* 功    能:读取光强度    
* 参数说明:无
* 返 回 值:light_buf:读取到的光强值
* 说    明:得到的数据不是最终值需要处理
* 调用方法:内部函数
********************************************************************************/
static uint16_t Read_BH1750(void)
{   
uint16_t light_buf = 0;    

BH1750_IIC_Start();                         
BH1750_Write_Byte(BH1750_ADD_READ);         // 发送读数据信号
BH1750_IIC_Wait_Ack();

light_buf = BH1750_Read_Byte(ACK);          // 读数据的高八位
light_buf <<= 8;
light_buf |= BH1750_Read_Byte(NOACK);       // 读数据的低八位

BH1750_IIC_Stop();       
return  light_buf;
}

/********************************************************************************
* 名    称:BH1750_Handle
* 功    能:读取光强度    
* 参数说明:无
* 返 回 值:result_lx:得到单位为lx光值
* 说    明:功能函数
* 调用方法:外部函数
********************************************************************************/
uint16_t BH1750_Handle(void)
{   
uint16_t result_lx = 0;

    Start_BH1750();
delay_ms(180);
result_lx = Read_BH1750();
result_lx = (float)(result_lx / 1.2);

    return result_lx;
}

http://www.dtcms.com/a/394232.html

相关文章:

  • 基于单片机的数字电压表设计
  • 搜索百科(3):Elasticsearch — 搜索界的“流量明星”
  • 【嵌入式】CAN协议学习笔记
  • NeurIPS 2025 spotlight |FSDrive 自动驾驶迈向视觉推理
  • Linux系统编程--进程信号
  • 数据结构代码整理
  • 软件开发测试的W模型:构建高质量产品的坚实蓝图
  • 【OpenGL】LearnOpenGL学习笔记26 - 视差贴图 Parallax Map
  • 对1D poisson采用二阶中心差分格式离散,离散 Laplace 矩阵 A 的特征向量就是 Fourier 模式的离散化
  • [Windows] PDF解密程序 PDF Decrypter Pro 4.5.0 汉化版
  • 【OpenGL】openGL 法线贴图
  • 科普:通配符表达式(Wildcard)与正则表达式(Regular Expression)
  • 【ROS2】Beginner: Client libraries - 使用 colcon 构建功能包
  • 记一次投影连接网络存储
  • 计算机视觉(opencv)实战二十九——图像风格迁移
  • Python数据挖掘之基础分类模型_K最近邻分类器(KNN)_决策树
  • 23种设计模式之【外观模式】-核心原理与 Java实践
  • 第4章:构建自己的物料解决方案
  • 华为昇腾 950 系列芯片深度解析
  • 2025华为杯 C题围岩裂隙精准识别与三维模型重构保姆级教程思路分析【国奖版】
  • 搭建Electron桌面项目
  • Linux 线程之pthread库
  • 内存泄漏、内存溢出与内存访问越界
  • C++初阶(11)string类的模拟实现
  • Python快速入门专业版(三十九):Python集合:去重与集合运算(交集、并集、差集)
  • pytorch 中meshgrid()函数详解
  • 深度探秘GAIA:一个为下一代AI量身打造的挑战性基准
  • 今日分享C++ ---继承
  • TableGPT:浙江大学发布的表格大模型
  • Linux 概述