一、环境介绍
MCU: CC2530(Zigbee)
光敏传感器: BH1750数字传感器(IIC接口)
开发软件: IAR
代码说明:使用IIC模拟时序驱动,IIC时序代码与BH1750代码都采用模块化编程,代码清晰,注释完整,方便移植到其他平台,采集的光照度比较灵敏. 合成的光照度返回值范围是 0~255。 0表示全黑 255表示很亮。
实测: 手机闪光灯照着的状态返回值是245左右,手捂着的状态返回值是10左右.
完整工程源码下载地址: https://download.csdn.net/download/xiaolong1126626497/18502155
二、BH1750介绍
ADDR引脚接地地址就是0X46。
四、核心代码
#include "iic.h" /* 函数功能:IIC接口初始化 硬件连接: SDA:P1.2 SCL:P1.3 */ void IIC_Init(void) { P1SEL&=~(0x3<<2); //配置通用GPIO口模式 P1DIR|=0x3<<2; //配置为输出模式 } /* 函数功能:IIC总线起始信号 */ void IIC_Start(void) { IIC_SDA_OUTMODE(); //初始化SDA为输出模式 IIC_SDA_OUT=1; //数据线拉高 IIC_SCL=1; //时钟线 拉高 DelayUs(4); //电平保持时间 IIC_SDA_OUT=0; //数据线拉低 DelayUs(4); //电平保持时间 IIC_SCL=0; //时钟线拉低 } /* 函数功能:IIC总线停止信号 */ void IIC_Stop(void) { IIC_SDA_OUTMODE(); //初始化SDA为输出模式 IIC_SDA_OUT=0; //数据线拉低 IIC_SCL=0; //时钟线拉低 DelayUs(4); //电平保持时间 IIC_SCL=1; //时钟线拉高 DelayUs(4); //电平保持时间 IIC_SDA_OUT=1; //数据线拉高 } /* 函数功能:获取应答信号 返 回 值:1表示失败,0表示成功 */ u8 IIC_GetACK(void) { u8 cnt=0; IIC_SDA_INPUTMODE();//初始化SDA为输入模式 IIC_SDA_OUT=1; //数据线上拉 DelayUs(2); //电平保持时间 IIC_SCL=0; //时钟线拉低,告诉从机,主机需要数据 DelayUs(2); //电平保持时间,等待从机发送数据 IIC_SCL=1; //时钟线拉高,告诉从机,主机现在开始读取数据 while(IIC_SDA_IN) //等待从机应答信号 { cnt++; if(cnt>250)return 1; } IIC_SCL=0; //时钟线拉低,告诉从机,主机需要数据 return 0; } /* 函数功能:主机向从机发送应答信号 函数形参:0表示应答,1表示非应答 */ void IIC_SendACK(u8 stat) { IIC_SDA_OUTMODE(); //初始化SDA为输出模式 IIC_SCL=0; //时钟线拉低,告诉从机,主机需要发送数据 if(stat)IIC_SDA_OUT=1; //数据线拉高,发送非应答信号 else IIC_SDA_OUT=0; //数据线拉低,发送应答信号 DelayUs(2); //电平保持时间,等待时钟线稳定 IIC_SCL=1; //时钟线拉高,告诉从机,主机数据发送完毕 DelayUs(2); //电平保持时间,等待从机接收数据 IIC_SCL=0; //时钟线拉低,告诉从机,主机需要数据 } /* 函数功能:IIC发送1个字节数据 函数形参:将要发送的数据 */ void IIC_WriteOneByteData(u8 data) { u8 i; IIC_SDA_OUTMODE(); //初始化SDA为输出模式 IIC_SCL=0; //时钟线拉低,告诉从机,主机需要发送数据 for(i=0;i<8;i++) { if(data&0x80)IIC_SDA_OUT=1; //数据线拉高,发送1 else IIC_SDA_OUT=0; //数据线拉低,发送0 IIC_SCL=1; //时钟线拉高,告诉从机,主机数据发送完毕 DelayUs(2); //电平保持时间,等待从机接收数据 IIC_SCL=0; //时钟线拉低,告诉从机,主机需要发送数据 DelayUs(2); //电平保持时间,等待时钟线稳定 data<<=1; //先发高位 } } /* 函数功能:IIC接收1个字节数据 返 回 值:收到的数据 */ u8 IIC_ReadOneByteData(void) { u8 i,data; IIC_SDA_INPUTMODE();//初始化SDA为输入模式 for(i=0;i<8;i++) { IIC_SCL=0; //时钟线拉低,告诉从机,主机需要数据 DelayUs(2); //电平保持时间,等待从机发送数据 IIC_SCL=1; //时钟线拉高,告诉从机,主机现在正在读取数据 data<<=1; if(IIC_SDA_IN)data|=0x01; DelayUs(2); //电平保持时间,等待时钟线稳定 } IIC_SCL=0; //时钟线拉低,告诉从机,主机需要数据 (必须拉低,否则将会识别为停止信号) return data; }
4.2 iic.h
#ifndef _IIC_H #define _IIC_H #include "sys.h" #include "delay.h" /* 硬件连接: SDA:P1.2 SCL:P1.3 */ #define IIC_SDA_OUTMODE() {P1DIR|=0x1<<2;} #define IIC_SDA_INPUTMODE() {P1DIR&=~(0x1<<2);} #define IIC_SDA_OUT P1_2 //数据线输出 #define IIC_SDA_IN P1_2 //数据线输入 #define IIC_SCL P1_3 //时钟线 void IIC_Init(void); void IIC_Start(void); void IIC_Stop(void); u8 IIC_GetACK(void); void IIC_SendACK(u8 stat); void IIC_WriteOneByteData(u8 data); u8 IIC_ReadOneByteData(void); #endif
4.3 bh1750.c
#include "bh1750.h" u8 Read_BH1750_Data() { unsigned char t0; unsigned char t1; unsigned char t; u8 r_s=0; IIC_Start(); //发送起始信号 IIC_WriteOneByteData(0x46); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:1\r\n"); IIC_WriteOneByteData(0x01); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:2\r\n"); IIC_Stop(); //停止信号 IIC_Start(); //发送起始信号 IIC_WriteOneByteData(0x46); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:3\r\n"); IIC_WriteOneByteData(0x01); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:4\r\n"); IIC_Stop(); //停止信号 IIC_Start(); //发送起始信号 IIC_WriteOneByteData(0x46); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:5\r\n"); IIC_WriteOneByteData(0x10); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:6\r\n"); IIC_Stop(); //停止信号 DelayMs(300); //等待 IIC_Start(); //发送起始信号 IIC_WriteOneByteData(0x47); r_s=IIC_GetACK();//获取应答 if(r_s)USART0_Printf("error:7\r\n"); t0=IIC_ReadOneByteData(); //接收数据 IIC_SendACK(0); //发送应答信号 t1=IIC_ReadOneByteData(); //接收数据 IIC_SendACK(1); //发送非应答信号 IIC_Stop(); //停止信号 t=(((t0<<8)|t1)/1.2); return t; }
4.4 bh1750.h
#ifndef _BH1750_H #define _BH1750_H #include "delay.h" #include "iic.h" #include "uart.h" u8 Read_BH1750_Data(void); #endif