打印
[STM32F1]

STM32F1光照度测量BH1750 串口输出

[复制链接]
632|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
STM32F1光照度测量BH1750 串口输出
  • 硬件连接:
    使用到的硬件有:STM32F103C8T6最小系统板,USB转TTL模块(串口通信),光照度小球(主芯片BH1750)
    连接图:


  • 使用到的引脚:

  • 除了RCC和下载方式SYS外只需要配置IIC和USART





使用特权

评论回复
沙发
梵蒂冈是神uy|  楼主 | 2024-2-27 20:04 | 只看该作者
STM32CubeMX配置:



具体配置都默认

使用特权

评论回复
板凳
梵蒂冈是神uy|  楼主 | 2024-2-27 20:05 | 只看该作者
时钟框图:

使用特权

评论回复
地板
梵蒂冈是神uy|  楼主 | 2024-2-27 20:05 | 只看该作者
生成工程后先搞一下printf函数重定义:
把以下代码粘贴在usart.c最后
/* USER CODE BEGIN 1 */
#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
1. @brief  Retargets the C library printf function to the USART.
2. @param  None
3. @retval None
  */
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

  return ch;
}
/* USER CODE END 1 */

使用特权

评论回复
5
梵蒂冈是神uy|  楼主 | 2024-2-27 20:05 | 只看该作者
在usart.c和main.c里添加头文件:stdio.h

使用特权

评论回复
6
梵蒂冈是神uy|  楼主 | 2024-2-27 20:05 | 只看该作者
添加BH1750.c和BH1750.h文件
BH1750.c

#inc
#include "BH1750.h"

uint8_t mcy=0;
uint8_t BUF[3];
/***开始信号**/
void BH1750_Start()
{
    HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_SET);                    //拉高数据线
    HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_SET);                   //拉高时钟线
    delay_us(5);                 
    HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_RESET);                    //产生下降沿
    delay_us(5);               
    HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_RESET);                    //拉低时钟线
}

/*****停止信号******/
void BH1750_Stop()
{
    HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_RESET);                   //拉低数据线
    HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_SET);                      //拉高时钟线
    delay_us(5);                 
    HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_SET);                    //产生上升沿
    delay_us(5);                 
}
/*****初始化BH1750******/
void Init_BH1750()
{
                BH1750_Start();                                                 //起始信号
                BH1750_SendByte(SlaveAddress);                                  //发送设备地址+写信号
                BH1750_SendByte(0x01);                                  //内部寄存器地址
                BH1750_Stop();                                                  //停止信号
       
}

//连续读出BH1750内部数据
uint16_t mread(void)
{   
          uint8_t i;       
    BH1750_Start();                          //起始信号
    BH1750_SendByte(SlaveAddress+1);         //发送设备地址·+读信号
       
         for (i=0; i<3; i++)                      //连续读取6个地址数据到BUF
    {
        BUF[i] = BH1750_RecvByte();         
        if (i == 3)
        {
           BH1750_SendACK(1);                //最后一个数据需要回NOACK
        }
        else
        {               
          BH1750_SendACK(0);                //回应ACK
        }
   }

    BH1750_Stop();                          //停止信号
    Delay_mms(5);

}

uint32_t Value_GY30(void)
{
                uint16_t dis_data;
          uint16_t Value_GY_30;
    Single_Write_BH1750(0x01);   // power on
    Single_Write_BH1750(0x10);   // H- resolution mode   
    HAL_Delay(180);            //延时180ms                    
    mread();       //连续读出数据,存储在BUF中
    dis_data=BUF[0];
    dis_data=(dis_data<<8)+BUF[1];//字节合成数据
    Value_GY_30=(float)dis_data/1.2;
    return Value_GY_30;
}
//系统主频72MHZ
void delay_us(uint16_t us)
{
        while(us--)
        {
                __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
                __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
                __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
                __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
                __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
                __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
                __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
                __nop();__nop();
        }
}
void Delay_mms(uint16_t tmp)
{
          uint16_t i=0;
          while(tmp--)
          {
                i=12000;
                while(i--);
    }
}

/**************************************
发送应答信号
入口参数:ack (0:ACK 1:NAK)
**************************************/
void BH1750_SendACK(int ack)
{
                        GPIO_InitTypeDef GPIO_InitStruct;
       
  GPIO_InitStruct.Pin = scl|sda;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    if(ack == 1)   //写应答信号
                        HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_SET);
                else if(ack == 0)
                        HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_RESET);
                else
                        return;
                       
    HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_SET);     
    delay_us(5);               
    HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_RESET);      
    delay_us(5);               
}

/**************************************
接收应答信号
**************************************/
int BH1750_RecvACK()
{               
               
          GPIO_InitTypeDef GPIO_InitStruct;
       
          GPIO_InitStruct.Mode = GPIO_MODE_INPUT;  /*输入上拉*/
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Pin = sda;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);        
       
    HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_SET);            //拉高时钟线
    delay_us(5);               
       
          if(HAL_GPIO_ReadPin( GPIOB, sda ) == 1 )//读应答信号
        mcy = 1 ;  
    else
        mcy = 0 ;                       
       
    HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_RESET);                    //拉低时钟线
    delay_us(5);               
  
   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
   HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
       
    return mcy;
}

/**************************************
向iic总线发送一个字节数据
**************************************/
void BH1750_SendByte(uint8_t dat)
{
    uint8_t i;

    for (i=0; i<8; i++)         //8位计数器
      {
                                if( 0X80 & dat )
          HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_SET);
        else
          HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_RESET);
                         
                                dat <<= 1;
        HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_SET);               //拉高时钟线
        delay_us(5);            
        HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_RESET);                //拉低时钟线
        delay_us(5);            
      }
    BH1750_RecvACK();
}

//我们对BH1750发送命令时,要先发送器件地址+写入位,然后发送指令
//读取数据的时候,需要先发送器件地址+读入位,然后读取两字节数据

//写入指令
void Single_Write_BH1750(uint8_t REG_Address)//REG_Address是要写入的指令
{
        BH1750_Start();                  //起始信号
        BH1750_SendByte(SlaveAddress);  //发送器件地址+写信号
        BH1750_SendByte(REG_Address);   //写入指令,内部寄存器地址
        BH1750_Stop();                   //结束信号
}
/**************************************
从iic总线读取一个字节地址
**************************************/
uint8_t BH1750_RecvByte()
{
    uint8_t i;
    uint8_t dat = 0;
          uint8_t bit;
          
         GPIO_InitTypeDef GPIO_InitStruct;
       
         GPIO_InitStruct.Mode = GPIO_MODE_INPUT;   /*上拉输入*/
   GPIO_InitStruct.Pin = sda;
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
   HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
       
    HAL_GPIO_WritePin(GPIOB, sda,GPIO_PIN_SET);          //准备读取数据
    for (i=0; i<8; i++)         //8位计数器
    {
        dat <<= 1;
        HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_SET);               //拉高时钟线
        delay_us(5);            
                       
                          if( SET == HAL_GPIO_ReadPin( GPIOB, sda ) )
             bit = 0X01;
       else
             bit = 0x00;  
                       
        dat |= bit;             //读数据
                       
        HAL_GPIO_WritePin(GPIOB, scl,GPIO_PIN_RESET);                //拉低时钟线
        delay_us(5);           
    }
               
                GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
    return dat;
}


使用特权

评论回复
7
梵蒂冈是神uy|  楼主 | 2024-2-27 20:05 | 只看该作者
BH1750.h

#ifndef __BH1750_H
#define __BH1750_H
#include "main.h"
#define scl GPIO_PIN_6
#define sda GPIO_PIN_7

#define SlaveAddress 0x46  //ADDR接GND时的器件地址
#define BH1750_PWR_DOWN     0x00 //关闭模块
#define BH1750_PWR_ON       0x01 //打开模块等待测量命令
#define BH1750_RST          0x07 //重置数据寄存器值在PowerOn模式下有效
#define BH1750_CON_H        0x10 // 连续高分辨率模式,1lx,120ms
#define BH1750_CON_H2       0x11 // 连续高分辨率模式.5lx,120ms
#define BH1750_CON_L        0x13 // 连续低分辨率模式,4lx,16ms
#define BH1750_ONE_H        0x20 // 一次高分辨率模式,1lx,120ms,测量后模块转到PowerDown模式
#define BH1750_ONE_H2       0x21 // 一次高分辨率模式,0.5lx,120ms,测量后模块转到PowerDown模式
#define BH1750_ONE_L        0x23 // 一次低分辨率模式,4lx,16ms,测量后模块转到PowerDown模式


void BH1750_Start();
void BH1750_Stop();
void Init_BH1750();
uint16_t mread(void);
uint32_t Value_GY30(void);
void delay_us(uint16_t us);
void Delay_mms(uint16_t tmp);
void BH1750_SendACK(int ack);
int BH1750_RecvACK();
void BH1750_SendByte(uint8_t dat);
uint8_t BH1750_RecvByte();
int I2C_ReadData(uint8_t slaveAddr, uint8_t regAddr, uint8_t *pData, uint16_t dataLen);
void Single_Write_BH1750(uint8_t REG_Address);

#endif

使用特权

评论回复
8
梵蒂冈是神uy|  楼主 | 2024-2-27 20:06 | 只看该作者
main.c
添加如下代码:
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "BH1750.h"
/* USER CODE END Includes */

  /* USER CODE BEGIN 2 */
        Init_BH1750();
        printf("\n\r UART already\n\r");
  /* USER CODE END 2 */


  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
                printf("\n\r 光照强度:%d lx\n\r",Value_GY30());
                HAL_Delay(1000);
  }

使用特权

评论回复
9
梵蒂冈是神uy|  楼主 | 2024-2-27 20:06 | 只看该作者
效果展示:
晚上开着灯的室内:


使用特权

评论回复
10
梵蒂冈是神uy|  楼主 | 2024-2-27 20:07 | 只看该作者
用手在小球前方6厘米左右挡着光:

使用特权

评论回复
11
Henryko| | 2024-2-29 23:02 | 只看该作者
光照强度测试出来准确吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

47

主题

680

帖子

1

粉丝