STM32模拟IIC与IIC四种实现数字光强采集模块GY30(标准库与HAL库)

2023-10-14 02:30

本文主要是介绍STM32模拟IIC与IIC四种实现数字光强采集模块GY30(标准库与HAL库),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

代码实现是的IIC通信,数据采集后在串口显示,方便大家实现二次开发

原件选择

GY-30 数字光强度介绍

BH1750芯片参数

引脚说明

 BH1750指令集

接线表设计

通过四种方式实现GY-30数据采集

1.标准库模拟IIC实现GY-30采集并串口1显示

 2.标准库IIC实现GY-30采集并串口1显示

3.HAL库模拟IIC实现GY-30采集并串口1显示

4.HAL库IIC实现GY-30采集并串口1显示

源码下载链接


代码实现是的IIC通信,数据采集后在串口显示,方便大家实现二次开发

原件选择

1.STM32F103

2.GY-30 数字光强度 光照传感器 BH1750FVI 

GY-30 数字光强度介绍

GY30简介
GY-30是一款内置ROHM-BH1750FLV芯片的数字光照强度模块,用于光照强度采集。
BH1750FVl是一种用于RC总线接口的数字环境光传感器LC。该芯片最适合于获取移动电话液晶显示器和按键背光功率的环境光数据。在高分辨率(1~65535 l×)范围内检测是可行的。

特性
IIC总线接口
光强数字转换器
16位分辩率(1~65535)
直接数字输出,省略复杂的计算,省略标定
不区分环境光源,接近于视觉灵敏度的分光特性
应用
手机、数码相机、车载导航,PDA、LCD显示等。


GY-30模块是一款基于IIC通信的16bit的数字型传感器。模块主要是以BH1750数字型光强感应芯片为核心及一些外围驱动电路。模块整体电路如图:

其中C1、C2 为电源滤波电容,R1、R3 为 I2C 上拉电阻,ADDR 是 I2C 通讯时设备地址的选择,即接电源或接地时,读操作、写操作的指令有所区别,如下图。一般为接地,即写操作指令为0x46,读操作指令为0x47。

BH1750芯片参数

BH1750是一款内部集成了光电转换、ADC转换、IIC信号转换等电路的芯片,省去了复杂信号处理电路,即能保持良好的稳定型又节省空间。BH1750内部简要框图如图:

该芯片内部电路主要分为4部分:其中

  1. 光敏二极管,导通电流随着光强的变化而变化;
  2. I/V转换电路:主要是将电流信号转换为电压信号;
  3. ADC转换电路:将电压信号转换为数字信号,分辨率为16bit;
  4. IIC逻辑电路:主要是将光强数据打包成I标准的IIC通信信号;

引脚说明

 BH1750指令集

#define BHAddWrite     0x46      //写地址
#define BHAddRead      0x47      //读地址
#define BHPowDown      0x00      //关闭模块
#define BHPowOn        0x01      //打开模块等待指令 
#define BHReset        0x07      //重置数据寄存器仅在BHpowOn模式下有效
#define BHModeH1       0x10      //高分辨率 模式1 单位 11X 测量时间 120ms 
#define BHModeH2       0x11      //高分辨率 模式2 单位 11X 测量时间 120ms 
#define BHModeL        0x13      //低分辨率 单位4lx 测量时间16ms  
#define BHSigModeH     0x20      //一次测量高分辨率模式1,然后转到powerdown模式
#define BHSigModeH2    0x21      //同上类似
#define BHSigModeL     0x23      //同上类似  

接线表设计

序号GY-30单片机STM32
1VCC3.3V/5V
2SCLPB6
3SDAPB7
4GNDGND
5-PA9(USART1_ TX)
6-PA10(USART1_RX)

通过四种方式实现GY-30数据采集

1.标准库模拟IIC实现GY-30采集并串口1显示

核心代码gy30.c

//发送起始信号
void IIC_Start(void)
{IIC_Sdaout_Mode();//输出模式IIC_SCL=1;IIC_SDAout=1;delay_us(2);IIC_SDAout=0;IIC_SCL=0;//方便后续数据收发
}
//停止信号
void IIC_Stop(void)
{IIC_Sdaout_Mode();//输出模式IIC_SCL=0;IIC_SDAout=0;delay_us(2);IIC_SCL=1;delay_us(2);IIC_SDAout=1;
}
/***********发送应答信号**************************
**
**形参:u8 ack -- 0应答,1非应答
**
***************************************************/
void IIC_SendAck(u8 ack)
{IIC_Sdaout_Mode();//输出模式	IIC_SCL=0;//告诉从机,主机开始发送数据IIC_SDAout=ack&0x01;delay_us(2);IIC_SCL=1;//告诉从机,主机数据发送完成//方便下一次数据收发delay_us(2);IIC_SCL=0;
}
//获取应答信号
u8 IIC_Wait_Ack(void)
{u8 cnt=0;IIC_SdaIn_Mode();//配置为输入模式IIC_SDAout=1;	IIC_SCL=0;//告诉从机,主机需要获取数据delay_us(2);IIC_SCL=1;//从机数据发送完成,主机开始读取数据while(IIC_SDAin){cnt++;delay_us(1);if(cnt>=100)return 1;}delay_us(2);IIC_SCL=0;//方便下一次数据收发return 0;
}
//发送一个字节数据
void IIC_Send_Byte(u8 data)
{u8 i=0;IIC_Sdaout_Mode();//输出模式for(i=0;i<8;i++){IIC_SCL=0;//告诉从机,主机开始发送数据if(data&0x80)IIC_SDAout=1;else IIC_SDAout=0;delay_us(2);IIC_SCL=1;//主机数据发送完成data<<=1;delay_us(2);}IIC_SCL=0;//方便下一次数据收发
}
//读取一个字节数据
u8 IIC_Read_Byte(void)
{u8 i=0;u8 data=0;IIC_SdaIn_Mode();//配置为输入模式for(i=0;i<8;i++){IIC_SCL=0;//告诉从机,主机需要获取数据delay_us(2);IIC_SCL=1;//开始读取数据data<<=1;//默认收到0if(IIC_SDAin)data|=0x01;delay_us(2);}IIC_SCL=0;return data;
}void bh_data_send(u8 command)  
{  do{  IIC_Start();                      //iic开始IIC_Send_Byte(BHAddWrite);       //写地址  }while(IIC_Wait_Ack());           //等待响应 IIC_Send_Byte(command);          //发送命令  IIC_Wait_Ack();                   //等待响应 IIC_Stop();                       //iic停止  
}   u16 bh_data_read(void)  
{  u16 buf;  IIC_Start();                       //iic开始  IIC_Send_Byte(BHAddRead);         //发送读地址IIC_Wait_Ack();                     //等待响应  buf=IIC_Read_Byte();              //读取数据  IIC_SendAck(0);buf=buf<<8;                        //读取并保存高八位数据buf+=0x00ff&IIC_Read_Byte();      //读取并保存第八位数据IIC_SendAck(1);IIC_Stop();                        //发送停止信号return buf;   
}  void BH1750init(void)
{IIC_Init();//GPIO初始化bh_data_send(BHPowOn);    //发送启动信号bh_data_send(BHReset);    //清除寄存器  bh_data_send(BHModeH1);   //设置为模式1delay_ms(180);            //最高延时180ms 
}

实现

 2.标准库IIC实现GY-30采集并串口1显示

gy30.c核心代码

void I2C_GY30_Config(void)
{GPIO_InitTypeDef    GPIO_InitStuctrue;I2C_InitTypeDef     I2C_InitStuctrue;//开启GPIO外设时钟GY30_I2C_GPIO_APBxClkCmd(GY30_I2C_SCL_GPIO_CLK|GY30_I2C_SDA_GPIO_CLK,ENABLE);//开启IIC外设时钟GY30_I2C_APBxClkCmd(GY30_I2C_CLK,ENABLE);//SCL引脚-复用开漏输出GPIO_InitStuctrue.GPIO_Mode=GPIO_Mode_AF_OD;GPIO_InitStuctrue.GPIO_Pin=GY30_I2C_SCL_GPIO_PIN;GPIO_InitStuctrue.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GY30_I2C_SCL_GPIO_PORT,&GPIO_InitStuctrue);//SDA引脚-复用开漏输出GPIO_InitStuctrue.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_InitStuctrue.GPIO_Pin = GY30_I2C_SDA_GPIO_PIN;GPIO_InitStuctrue.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GY30_I2C_SDA_GPIO_PORT,&GPIO_InitStuctrue);//IIC结构体成员配置I2C_InitStuctrue.I2C_Ack=I2C_Ack_Enable;I2C_InitStuctrue.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;I2C_InitStuctrue.I2C_ClockSpeed=GY30_I2C_BAUDRATE;I2C_InitStuctrue.I2C_DutyCycle=I2C_DutyCycle_2;I2C_InitStuctrue.I2C_Mode=I2C_Mode_I2C;I2C_InitStuctrue.I2C_OwnAddress1=STM32_I2C_OWN_ADDR;I2C_Init(GY30_I2C,&I2C_InitStuctrue);I2C_Cmd(GY30_I2C,ENABLE);}//向EEPROM写入一个字节
void  GY30_Byte_Write(uint8_t addr)
{//发送起始信号I2C_GenerateSTART(GY30_I2C,ENABLE);//检测EV5事件while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_MODE_SELECT)==ERROR);//发送设备写地址I2C_Send7bitAddress(GY30_I2C,GY30_I2C_Address,I2C_Direction_Transmitter);//检测EV6事件while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR);//发送要操作设备内部的地址I2C_SendData(GY30_I2C,addr);while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED )==ERROR);
//  I2C_SendData(EEPROM_I2C,data);
//	//检测EV8_2事件
//	while( I2C_CheckEvent(EEPROM_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED )==ERROR);//发送停止信号I2C_GenerateSTOP(GY30_I2C,ENABLE);}//向EEPROM写入多个字节
uint32_t  GY30_Page_Write(uint8_t addr,uint8_t *data,uint16_t Num_ByteToWrite)
{I2CTimeout = I2CT_LONG_TIMEOUT;//判断IIC总线是否忙碌while(I2C_GetFlagStatus(GY30_I2C, I2C_FLAG_BUSY))   {if((I2CTimeout--) == 0) return 1;} //重新赋值I2CTimeout = I2CT_FLAG_TIMEOUT;//发送起始信号I2C_GenerateSTART(GY30_I2C,ENABLE);//检测EV5事件while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_MODE_SELECT)==ERROR){if((I2CTimeout--) == 0) return 2;} I2CTimeout = I2CT_FLAG_TIMEOUT;//发送设备写地址I2C_Send7bitAddress(GY30_I2C,GY30_I2C_Address,I2C_Direction_Transmitter);//检测EV6事件while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)==ERROR){if((I2CTimeout--) == 0) return 3;} I2CTimeout = I2CT_FLAG_TIMEOUT;//发送要操作设备内部的地址I2C_SendData(GY30_I2C,addr);//检测EV8事件while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTING )==ERROR){if((I2CTimeout--) == 0) return 4;} while(Num_ByteToWrite){I2C_SendData(GY30_I2C,*data);I2CTimeout = I2CT_FLAG_TIMEOUT;while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTING )==ERROR){if((I2CTimeout--) == 0) return  5;} Num_ByteToWrite--;data++;}I2CTimeout = I2CT_FLAG_TIMEOUT;//检测EV8_2事件while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTED )==ERROR){if((I2CTimeout--) == 0) return 6;} //发送停止信号I2C_GenerateSTOP(GY30_I2C,ENABLE);return 1;
}//向EEPROM读取多个字节
uint32_t GY30_Read(uint8_t *data,uint8_t addr,uint16_t Num_ByteToRead)
{I2CTimeout = I2CT_LONG_TIMEOUT;//判断IIC总线是否忙碌while(I2C_GetFlagStatus(GY30_I2C, I2C_FLAG_BUSY))   {if((I2CTimeout--) == 0) return 1;} I2CTimeout = I2CT_FLAG_TIMEOUT;//发送起始信号I2C_GenerateSTART(GY30_I2C,ENABLE);//检测EV5事件while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_MODE_SELECT )==ERROR){if((I2CTimeout--) == 0) return 7;} I2CTimeout = I2CT_FLAG_TIMEOUT;//发送设备写地址I2C_Send7bitAddress(GY30_I2C,GY30_I2C_Address,I2C_Direction_Transmitter);//检测EV6事件等待从机应答while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED )==ERROR){if((I2CTimeout--) == 0) return 8;}I2CTimeout = I2CT_FLAG_TIMEOUT;//发送要操作设备内部存储器的地址I2C_SendData(GY30_I2C,addr);//检测EV8事件while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_BYTE_TRANSMITTING )==ERROR){if((I2CTimeout--) == 0) return 9;}I2CTimeout = I2CT_FLAG_TIMEOUT;//发送起始信号I2C_GenerateSTART(GY30_I2C,ENABLE);//检测EV5事件while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_MODE_SELECT )==ERROR){if((I2CTimeout--) == 0) return 10;}I2CTimeout = I2CT_FLAG_TIMEOUT;	 //发送设备读地址I2C_Send7bitAddress(GY30_I2C,GY30_I2C_Address,I2C_Direction_Receiver);//检测EV6事件while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED )==ERROR){if((I2CTimeout--) == 0) return 10;}while(Num_ByteToRead--){//是否是最后一个字节,若是则发送非应答信号if( Num_ByteToRead==0){//发送非应答信号I2C_AcknowledgeConfig(GY30_I2C,DISABLE);//发送停止信号I2C_GenerateSTOP(GY30_I2C,ENABLE);}I2CTimeout = I2CT_FLAG_TIMEOUT;	 //检测EV7事件while( I2C_CheckEvent(GY30_I2C,I2C_EVENT_MASTER_BYTE_RECEIVED )==ERROR){if((I2CTimeout--) == 0) return 10;}*data=I2C_ReceiveData(GY30_I2C);data++; }//重新开启应答信号I2C_AcknowledgeConfig(GY30_I2C,ENABLE);return 1;
}
void I2C_GY30_BufferWrite(uint8_t* pBuffer,uint8_t WriteAddr, uint16_t NumByteToWrite)
{u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;//I2C_PageSize=8Addr = WriteAddr % I2C_PageSize;count = I2C_PageSize - Addr;NumOfPage =  NumByteToWrite / I2C_PageSize;NumOfSingle = NumByteToWrite % I2C_PageSize;/* 写入数据的地址对齐,对齐数为8 */if(Addr == 0) {/* 如果写入的数据个数小于8 */if(NumOfPage == 0) {GY30_Page_Write(WriteAddr, pBuffer, NumOfSingle);GY30_WaitForWriteEnd();}/* 如果写入的数据个数大于8 */else  {//按页写入while(NumOfPage--){GY30_Page_Write(WriteAddr, pBuffer, I2C_PageSize); GY30_WaitForWriteEnd();WriteAddr +=  I2C_PageSize;pBuffer += I2C_PageSize;}//不足一页(8个)单独写入if(NumOfSingle!=0){GY30_Page_Write(WriteAddr, pBuffer, NumOfSingle);GY30_WaitForWriteEnd();}}}/*写的数据的地址不对齐*/else {NumByteToWrite -= count;NumOfPage =  NumByteToWrite / I2C_PageSize;NumOfSingle = NumByteToWrite % I2C_PageSize;	if(count != 0){  GY30_Page_Write(WriteAddr, pBuffer, count);GY30_WaitForWriteEnd();WriteAddr += count;pBuffer += count;} while(NumOfPage--){GY30_Page_Write(WriteAddr, pBuffer, I2C_PageSize);GY30_WaitForWriteEnd();WriteAddr +=  I2C_PageSize;pBuffer += I2C_PageSize;  }if(NumOfSingle != 0){GY30_Page_Write(WriteAddr, pBuffer, NumOfSingle); GY30_WaitForWriteEnd();}} 
}

效果如下: 

3.HAL库模拟IIC实现GY-30采集并串口1显示

#include "gy30.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内部数据
void 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 onSingle_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=dis_data;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);elsereturn;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 ;  elsemcy = 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);elseHAL_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;elsebit = 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;
}

 

4.HAL库IIC实现GY-30采集并串口1显示

//写命令
void GY30_WR_CMD(uint8_t cmd)
{HAL_I2C_Master_Transmit(&hi2c1, 0x46, &cmd,1, 0x100);//HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);//HAL_I2C_Mem_Write(&hi2c1 ,0x46,0x00,I2C_MEMADD_SIZE_8BIT,&cmd,1,0x100);
}/**@brief BH1750初始化函数@param 无@return 无
*/
void BH1750_Init(void)
{GY30_WR_CMD(0x01);GY30_WR_CMD(0x10);GY30_WR_CMD(0x47);}//读数据
void GY30_READ_DATA(uint8_t data[])
{
//	uint8_t temp = 0X47;
//	
//	HAL_I2C_Mem_Write(&hi2c1 ,0x47,0x00,I2C_MEMADD_SIZE_8BIT,&temp,1,0x100);BH1750_Init();HAL_I2C_Master_Receive(&hi2c1, 0x46, data, 2, 0x100);//HAL_I2C_Mem_Read_IT(&hi2c1, 0x46, 0X00,I2C_MEMADD_SIZE_8BIT, data, 2);//HAL_I2C_Mem_Read(&hi2c1 ,0x46,0x47,I2C_MEMADD_SIZE_8BIT,data,2,0x100);
}/**@brief BH1750获取光强度@param 无@return 光强度
*/
uint32_t BH1750_ReadLightIntensity(void)
{uint32_t lux = 0;uint8_t sensorData[2] = {0};GY30_READ_DATA(sensorData);lux = (sensorData[0] << 8 | sensorData[1]);return lux;
}

四种实现效果一样,硬件IIC比模拟IIC的确要简单一些,看各人的喜好,花了一天时间特意研究整理,实现效果一定没有问题的。

创作不易

源码下载链接

(2条消息) STM32模拟IIC与IIC四种实现实现数字光强采集模块GY30(标准库与HAL库)-C文档类资源-CSDN文库

吾芯电子工作室

这篇关于STM32模拟IIC与IIC四种实现数字光强采集模块GY30(标准库与HAL库)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/207501

相关文章

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

从去中心化到智能化:Web3如何与AI共同塑造数字生态

在数字时代的演进中,Web3和人工智能(AI)正成为塑造未来互联网的两大核心力量。Web3的去中心化理念与AI的智能化技术,正相互交织,共同推动数字生态的变革。本文将探讨Web3与AI的融合如何改变数字世界,并展望这一新兴组合如何重塑我们的在线体验。 Web3的去中心化愿景 Web3代表了互联网的第三代发展,它基于去中心化的区块链技术,旨在创建一个开放、透明且用户主导的数字生态。不同于传统

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

usaco 1.2 Name That Number(数字字母转化)

巧妙的利用code[b[0]-'A'] 将字符ABC...Z转换为数字 需要注意的是重新开一个数组 c [ ] 存储字符串 应人为的在末尾附上 ‘ \ 0 ’ 详见代码: /*ID: who jayLANG: C++TASK: namenum*/#include<stdio.h>#include<string.h>int main(){FILE *fin = fopen (

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<