资讯详情

STM32 模拟I2C 读取BH1750光照传感器数据

BH1750是光强传感器,可以测量当前环境下的光强。VCC支持3.3V供电,通过I2C协议与STM32通信。

BH1750可直接通过开发板连接。

测量后,稳定可用的代码。

i2c.c文件内容如下: /* 配置模拟I2C使用的GPIO*/ /* PC6配置为SDA,PC7配置为SCL */ void I2C_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStr; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); GPIO_InitStr.GPIO_Mode = GPIO_Mode_Out_OD;///泄漏输出 GPIO_InitStr.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStr.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC,&GPIO_InitStr); /* 给出停止信号,复位I2C总线上所有设备到待机模式*/ GPIO_ResetBits(GPIOC,GPIO_Pin_6); GPIO_ResetBits(GPIOC,GPIO_Pin_7); }

/* 主机产生一个起始信号 */ /* SCL高电平时,SDA从高电平跳到低电平,产生起始信号 */ void I2C_Start(void) {

/* 主机产生起始信号 */ GPIO_SetBits(GPIOC,GPIO_Pin_6); GPIO_SetBits(GPIOC,GPIO_Pin_7); delay_us(5); GPIO_ResetBits(GPIOC,GPIO_Pin_6); /* 主机准备发送数据 */ delay_us(5); GPIO_ResetBits(GPIOC,GPIO_Pin_7); delay_us(5); } /* 主机产生一个停止信号 */ /* SCL高电平时,SDA从低电平跳到高电平,产生停止信号 */ void I2C_Stop(void) { GPIO_ResetBits(GPIOC,GPIO_Pin_6); GPIO_SetBits(GPIOC,GPIO_Pin_7); delay_us(5); GPIO_SetBits(GPIOC,GPIO_Pin_6); }

/* 发送一个主机ACK给从机 */ void I2C_SendACK(void) {

/* 生成一个主机ACK信号 */ GPIO_ResetBits(GPIOC,GPIO_Pin_6); delay_us(5); GPIO_SetBits(GPIOC,GPIO_Pin_7); delay_us(5); /* 准备下一次发送 */ GPIO_ResetBits(GPIOC,GPIO_Pin_7); delay_us(5); GPIO_SetBits(GPIOC,GPIO_Pin_6); }

/* 主机发送NCAK信号给从机 */ void I2C_SendNAK(void) {

/* 生成一个主机NACK信号 */ GPIO_SetBits(GPIOC,GPIO_Pin_6); delay_us(5); GPIO_SetBits(GPIOC,GPIO_Pin_7); delay_us(5); /* 为下一次发送作准你*/ GPIO_ResetBits(GPIOC,GPIO_Pin_7); delay_us(5); }

/* 主机从机发送ACK信号 */ /* 返回1意味着获得了ACK信号 */ int I2C_WaitACK(void) { int ack; GPIO_SetBits(GPIOC,GPIO_Pin_6);//主机将SDA置高 delay_us(5); GPIO_SetBits(GPIOC,GPIO_Pin_7);//之前SCL现在将是低电平SCL放高后,主机读取SDA的数据 delay_us(5); ack = GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6);//若SDA为了低电平,机发送了一个ACK给主机 GPIO_ResetBits(GPIOC,GPIO_Pin_7)///获取信号后记得SCL低,否则容易出错 if (ack == 0) { return 1; } else { return 0; } }

/* STM32(主机)向BH1750(从机)发送字节数据,等待BH1750返回一个ACK */ /* 若函数返回值为1,则表示数据发送成功,BH1750返回了一个ACK给主机;相反,数据发送失败;*/ /* 从最高位发送*/ int I2C_SendByte(unsigned char byte) { int i; for (i = 0; i < 8; i ) { if (byte & 0x80) { GPIO_SetBits(GPIOC,GPIO_Pin_6); } else { GPIO_ResetBits(GPIOC,GPIO_Pin_6); } delay_us(5); GPIO_SetBits(GPIOC,GPIO_Pin_7); delay_us(5); GPIO_ResetBits(GPIOC,GPIO_Pin_7); if (i == 7) { GPIO_SetBits(GPIOC,GPIO_Pin_6); } delay_u(5);         byte <<= 1;     }          return I2C_WaitACK(); }

/* STM32(主机)从BH1750读取一个字节的数据 */ /* 读取的第一个bit是最高位 */ unsigned char I2C_ReadByte(void) {     unsigned char result = 0;     unsigned char data;     int i;     for (i = 0; i < 8; i++)     {         data = 0;         GPIO_SetBits(GPIOC,GPIO_Pin_7);         delay_us(5);         data = GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6);         GPIO_ResetBits(GPIOC,GPIO_Pin_7);         delay_us(5);         data <<= (7 - i);         result |= data;     }     return result; }

bh1750.h文件内容如下:

#define ADDR 0x23   //0100011  ADDR = 'L' #define BH_WRITEADDR   0x46    //01000110  BH1750写地址 #define BH_READADDR    0x47    //01000111  BH1750读地址 #define BH_POWEROFF    0x00    //0000_0000断电 #define BH_POWERON     0x01    //0000_0001 BH1750上电,等待测量指令 #define BH_RESET       0x07    //0000_0111 重置 #define BH_MODE_H      0x10    //连续H分辨率模式,精度为1x,测量时间为120ms,一般不超过180ms。

#define INTENSITY_WEAK    0   #define INTENSITY_STRONG  1 

typedef struct _BH1750_STRUCT {     volatile int open;     volatile int light_intensity;  } BH1750_STRUCTURE;

extern BH1750_STRUCTURE BH1750_Str; void BH1750_Init(void); void vTask_BH1750( void * pvParameters );

bh1750.c文件中的内容如下:

BH1750_STRUCTURE BH1750_Str = {0};

/*BH1750的ADDR引脚接到STM32的PC12上 */ /* 根据参考手册,ADDR为低电平时,BH1750的7位地址为0100011b */ static void BH1750_ADDR_Set(void) {     GPIO_InitTypeDef GPIO_InitStr;     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);     GPIO_InitStr.GPIO_Mode = GPIO_Mode_Out_PP;     GPIO_InitStr.GPIO_Pin = GPIO_Pin_12;     GPIO_InitStr.GPIO_Speed = GPIO_Speed_50MHz;     GPIO_Init(GPIOC,&GPIO_InitStr);     GPIO_ResetBits(GPIOC,GPIO_Pin_12); } static void BH1750_PowerOn(void) {     I2C_Start();     I2C_SendByte(BH_WRITEADDR);     I2C_SendByte(BH_POWERON);     I2C_Stop(); }

static void BH1750_PowerOff(void) {     I2C_Start();     I2C_SendByte(BH_WRITEADDR);     I2C_SendByte(BH_POWEROFF);     I2C_Stop(); }

static void BH1750_Reset(void) {     I2C_Start();     I2C_SendByte(BH_WRITEADDR);     I2C_SendByte(BH_RESET);     I2C_Stop(); }

/* 设置BH1750的模式 为: 连续H分辨率模式 */ /* 返回0表示设置成功,否则失败  */ static int BH1750_Set_Mode(void) {     I2C_Start();     if (I2C_SendByte(BH_WRITEADDR) == 0)     {         return 1;     }          if (I2C_SendByte(BH_MODE_H) == 0)     {         return 1;     }          I2C_Stop();     return 0; }

void BH1750_Init(void) {     I2C_GPIO_Init();     BH1750_ADDR_Set();     BH1750_PowerOn();     BH1750_Reset();     BH1750_Set_Mode(); }

/* 读取测量结果 */ static unsigned short BH1750_Read_Result(void) {     unsigned short result = 0;     unsigned char data;

    I2C_Start();     if (I2C_SendByte(BH_READADDR) == 0)     {         return 1;     }     data = I2C_ReadByte();     result = data;     result <<= 8;          I2C_SendACK();     data = I2C_ReadByte();     result += data;          I2C_SendNAK();     I2C_Stop();     result /= 1.2;              return result; }

/* 业务处理*/ void vTask_BH1750( void * pvParameters ) {     unsigned int result;     #if LOG_OPEN     char s[20];     #endif

    while (1)     {         if ( BH1750_Str.open != OPEN )          {             taskYIELD();             continue;         }         result = 0;         result = BH1750_Read_Result();                  if (result < 100) //         {             if ( BH1750_Str.light_intensity != INTENSITY_WEAK )             {                 BH1750_Str.light_intensity = INTENSITY_WEAK;             }         }         else //         {             if ( BH1750_Str.light_intensity != INTENSITY_STRONG )             {                 BH1750_Str.light_intensity = INTENSITY_STRONG;             }         } #if LOG_OPEN         my_itoa(result,s);         Usart_SendString(USART1,"BH1750 Result is ");                 Usart_SendString(USART1,s);                 vTaskDelay(500/portTICK_RATE_MS);//防止频繁打印,冲死串口 #endif         vTaskDelay(100/portTICK_RATE_MS);//加一个延时,没必要太勤劳 //    taskYIELD();     } }

void BH1750_Close(void) {     BH1750_Str.open = CLOSE;     BH1750_Str.light_intensity = INTENSITY_STRONG;     BH1750_PowerOff(); }

 

 

标签: 光强度传感器bh1750fvi

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台