STM32通过IIC读取BH1750光照数据

STM32的IIC接口

STM32共有3个IIC接口,引脚对应如下:

不了解GPIO配置的请看这篇

STM32F4 GPIO详解(代码)_Ljh0408abc的博客-CSDN博客GPIO代码分析https://blog.csdn.net/Ljh0408abc/article/details/122972149

例程,我们采用PB6为SCL,PB7为SDA。


void BH1750_PortInit()
{	
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOG,ENABLE);
	//PB6-SCL 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	//PG15-ADDR
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);	
}

函数:设置PB7(SDA)为输出

void SDA_OUT()
{
	GPIO_InitTypeDef GPIO_InitStructure;

	// PB7-SDA
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);

}

函数:设置PB7(SDA)为输入

void SDA_IN()
{
	GPIO_InitTypeDef GPIO_InitStructure;

	// PB7-SDA
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
}

函数:发送开始信号(S)

void BH1750_Start()
{
    SDA_OUT();     //sda线输出
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}

函数:发送停止信号(P)

void BH1750_Stop()
{
	SDA_OUT();//sda线输出
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
	IIC_SCL=1;
 	delay_us(4);
	IIC_SDA=1;//发送I2C总线结束信号
	delay_us(4);
}

不清楚IIC发送信号、停止信号、应答信号规格的请看这篇

https://blog.csdn.net/Ljh0408abc/article/details/123010638https://blog.csdn.net/Ljh0408abc/article/details/123010638

函数:发送应答信号

void BH1750_SendACK(u8 ack)
{
    SDA_OUT();          //sda线输出
	if(ack)IIC_SDA=1;   //写应答信号
	else IIC_SDA=0;          
    IIC_SCL=1;          //拉高时钟线
    delay_us(2);        //延时
    IIC_SCL=0;          //拉低时钟线
    delay_us(2);        //延时
}

函数:接受数据

u8 BH1750_RecvACK()
{
    u8 data;
	  SDA_IN();         //SDA设置为输入
    IIC_SCL=1;        //拉高时钟线
    delay_us(2);      //延时
    data = READ_SDA;  //读应答信号
    IIC_SCL=0;        //拉低时钟线
    delay_us(2);      //延时
    return data;
}

函数:向总线发送1Byte数据

void BH1750_SendByte(u8 dat)
{
    u8 i,bit;
	SDA_OUT();               //sda线输出
    for (i=0; i<8; i++)      //8位计数器
    {
	    bit=dat&0x80;
		if(bit) IIC_SDA=1;
		else IIC_SDA=0;
        dat <<= 1;           //移出数据的最高位
        IIC_SCL=1;           //拉高时钟线
        delay_us(2);         //延时
        IIC_SCL=0;           //拉低时钟线
        delay_us(2);         //延时
    }
    BH1750_RecvACK();

函数:向BH1750写入数据

void Single_Write_BH1750(u8 REG_Address)
{
    BH1750_Start();                  //起始信号
    BH1750_SendByte(SlaveAddress);   //发送设备地址+写信号
    BH1750_SendByte(REG_Address);    //内部寄存器地址,
    BH1750_Stop();                   //发送停止信号
}

函数:连续读取BH1750数据

void Multiple_Read_BH1750(void)
{   u8 i;	
    BH1750_Start();                          //起始信号
    BH1750_SendByte(SlaveAddress+1);         //发送设备地址+读信号
	
	for (i=0; i<3; i++)                      //连续读取2个地址数据,存储中BUF
    {
        BUF[i] = BH1750_RecvByte();          //BUF[0]存储0x32地址中的数据
        if (i == 3)
        {
           BH1750_SendACK(1);                //最后一个数据需要回NOACK
        }
        else
        {		
          BH1750_SendACK(0);                //回应ACK
       }
   }
    BH1750_Stop();                          //停止信号
 //   delay_ms(150);
}

函数:生成光亮数据

uint16_t Get_Bh_Value(void)
{  
	static float temp;
	unsigned int data;
	int dis_data ;
    Single_Write_BH1750(0x01);   // power on
    Single_Write_BH1750(0x10);   // H- resolution mode
//    delay_ms(200);              //延时200ms
    Multiple_Read_BH1750();       //连续读出数据,存储在BUF中
    dis_data=BUF[0];
    dis_data=(dis_data<<8)+BUF[1];//合成数据,即光照数据
    temp=(float)dis_data/1.2;
	data=(int)temp;
    return data;        
}

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用HAL库模拟I2C读取BH1750传感器的示例代码: ```c #include "main.h" #include "stdio.h" #include "stdlib.h" #include "string.h" #define BH1750_ADDR 0x23 // BH1750地址 #define BH1750_ON 0x01 // BH1750开启命令 #define BH1750_OFF 0x00 // BH1750关闭命令 #define BH1750_CONT_H_RES_MODE 0x10 // BH1750连续高分辨率模式命令 #define BH1750_MTREG_DEFAULT 69 // BH1750默认测量时间寄存器值 I2C_HandleTypeDef hi2c1; // I2C句柄 void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_I2C1_Init(void); void BH1750_ON_CMD(void); void BH1750_OFF_CMD(void); void BH1750_CONT_H_RES_MODE_CMD(void); void BH1750_Set_MTREG(uint8_t MTREG); uint16_t BH1750_Read_Lux(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_I2C1_Init(); BH1750_Set_MTREG(BH1750_MTREG_DEFAULT); BH1750_ON_CMD(); BH1750_CONT_H_RES_MODE_CMD(); while (1) { uint16_t lux = BH1750_Read_Lux(); printf("Lux: %d\n", lux); HAL_Delay(1000); } } void BH1750_ON_CMD(void) { uint8_t cmd = BH1750_ON; HAL_I2C_Master_Transmit(&hi2c1, BH1750_ADDR << 1, &cmd, 1, 100); } void BH1750_OFF_CMD(void) { uint8_t cmd = BH1750_OFF; HAL_I2C_Master_Transmit(&hi2c1, BH1750_ADDR << 1, &cmd, 1, 100); } void BH1750_CONT_H_RES_MODE_CMD(void) { uint8_t cmd = BH1750_CONT_H_RES_MODE; HAL_I2C_Master_Transmit(&hi2c1, BH1750_ADDR << 1, &cmd, 1, 100); } void BH1750_Set_MTREG(uint8_t MTREG) { uint8_t cmd[2]; cmd[0] = 0x40; cmd[1] = MTREG; HAL_I2C_Master_Transmit(&hi2c1, BH1750_ADDR << 1, cmd, 2, 100); } uint16_t BH1750_Read_Lux(void) { uint8_t data[2]; HAL_I2C_Master_Receive(&hi2c1, BH1750_ADDR << 1, data, 2, 100); uint16_t lux = (data[0] << 8) | data[1]; lux /= 1.2; return lux; } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; 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_0) != HAL_OK) { Error_Handler(); } } static void MX_I2C1_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.Timing = 0x00303D5B; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) { Error_Handler(); } if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9 | GPIO_PIN_10, GPIO_PIN_RESET); GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void Error_Handler(void) { __disable_irq(); while (1) { } } ``` 在上面的代码中,我们使用了STM32的I2C1接口来模拟I2C通讯,通过HAL库提供的函数来实现对BH1750传感器的控制和读取。具体来说: - `BH1750_ON_CMD()`函数用于发送BH1750开启命令。 - `BH1750_OFF_CMD()`函数用于发送BH1750关闭命令。 - `BH1750_CONT_H_RES_MODE_CMD()`函数用于发送BH1750连续高分辨率模式命令。 - `BH1750_Set_MTREG()`函数用于设置BH1750测量时间寄存器的值。 - `BH1750_Read_Lux()`函数用于读取BH1750传感器的光强数据。 需要注意的是,在使用I2C通讯时,需要先通过`HAL_I2C_Master_Transmit()`函数发送命令给从设备,再通过`HAL_I2C_Master_Receive()`函数读取从设备的响应数据。此外,在读取BH1750传感器的数据时,需要将读取到的数据除以1.2,得到光强值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值