这里将我写的STC12C5A60S2单片机控制数字光照强度模块GY-30(主芯片BH1750FVI)的程序共享一下,是为了让前辈给予斧正。
更新:
2014/04/29 14:05
(补充:以下代码只需要修改.h文件中含有 “选择” 字样的部分,就可以达到复用的效果)
对于串口调试部分,请参考《单片机程序协助调试方法(一)串口调试》点击进入
对于BH1750FVI有6种工作模式,文章中选用的模式为 Continuously H-Resolution Mode
测试程序:
#include
#include "BH1750FVI.h"
#include "uart.h"
void main()
{
UartInit() ;
BH1750FVIInit();
while(1)
{
UartSendValue("Ambient Light Value (lx): ", BH1750FVIReadResult() );
}
}
/*################BH1750FVI.h start ################*/
#ifndef __BH1750FVI_H__
#define __BH1750FVI_H__
#include
#include "common.h"
sbit BH1750FVI_sclk_bit=P2^0; /*根据硬件选择*/
sbit BH1750FVI_sda_bit=P2^1; /*根据硬件选择*/
#define BH1750FVI_ADDRESS_ON_ADD_LOW_LEVEL 0x46
#define BH1750FVI_ADDRESS_ON_ADD_HIGH_LEVEL 0Xb8
/*注意:这里当ADD引脚接VCC时选择BH1750FVI_ADDRESS_ON_ADD_HIGH_LEVEL,
当ADD引脚接GND时选择BH1750FVI_ADDRESS_ON_ADD_LOW_LEVEL。
在实验室,我接了GND,所以选择了BH1750FVI_ADDRESS_ON_ADD_LOW_LEVEL
根据硬件连接选择*/
#define BH1750FVI_ADDRESS BH1750FVI_ADDRESS_ON_ADD_LOW_LEVEL
#define BH1750FVI_READ 0x01
#define BH1750FVI_WRITE (0x01 & (~(0x01<<0)))
//命令 (参照datasheet)
#define BH1750FVI_POWER_DOWM 0x00
#define BH1750FVI_POWER_ON 0x01
#define BH1750FVI_RESET 0x07
#define BH1750FVI_CONTINUOUSLY_H_RESOLUTION_MODE 0x10
#define BH1750FVI_CONTINUOUSLY_H_RESOLUTION_MODE2 0x11
#define BH1750FVI_CONTINUOUSLY_L_RESOLUTION_MODE 0x13
#define BH1750FVI_ONE_TIME_H_RESOLUTION_MODE 0x20
#define BH1750FVI_ONE_TIME_H_RESOLUTION_MODE2 0X21
#define BH1750FVI_ONE_TIME_L_RESOLUTION_MODE 0x23
/*****************外部接口函数******************/
//初始化,上电,模式选择
extern void BH1750FVIInit() ;
//读取结果
extern UW16 BH1750FVIReadResult(void) ;
//写命令
extern void BH1750FVIWriteCommand(UB8 command) ;
/**********************************************/
#endif /*__BH1750FVI_H__*/
/*################BH1750FVI.h end ################*/
/*################BH1750FVI.c start ################*/
/***************************************************************************
Module :BH1750FVI.c
Purpose :Implementation of BH1750FVI module.(数字光照强度模块GY-30)
Version :0.01 2014/02/03 12:00(OK)
Complier:Keil 8051 C complier V9.01
MCU :STC12C5A60S2
Author :yangrui
QQ :279729201
Email :[email protected]
Modification:
=================
2014/04/29 14:35
Reason:
1.这里采用的工作方式为 Continuously H-Resolution Mode,即连续高分辨率模式。
除此之外,还有其他工作模式,关于6中工作模式总结如下:
Continuously H-Resolution Mode ;(at 1LX resolution,Measurement Time is typically 120ms)
Continuously H-Resolution Mode2 ;(at 0.5LX resolution,Measurement Time is typically 120ms)
Continuously L-Resolution Mode ;(at 4LX resolution,Measurement Time is typically 16ms)
One Time H-Resolution Mode ;(at 1LX resolution,Measurement Time is typically 120ms,
It is autionmatically set to power dowm mode after measurement,
so if want to read ,you shoule set "power on")
One Time H-Resolution Mode ;(at 0.5LX resolution,Measurement Time is typically 120ms,
It is autionmatically set to power dowm mode after measurement,
so if want to read ,you shoule set "power on")
One Time L-Resolution Mode ;(at 4LX resolution,Measurement Time is typically 16ms,
It is autionmatically set to power dowm mode after measurement,
so if want to read ,you shoule set "power on")
2.BH1750FVI在内部地址写数据和其他IIC器件稍有不同,其他IIC器件在传输器件地址后,还需要传输器件内部
地址,但是BH1750FVI写数据时,写的是命令,所以不需要内部器件地址,所以将函数直接命名成了
BH1750FVIWriteCommand(...),这里的代码由我的的at24c02.c演化而来,如果在工程中有很多IIC器件,
想把IIC通信协议封装起来,一定要注意这个细节。
=================
***************************************************************************/
#include
#include "BH1750FVI.h"
/*外部接口函数在BH1750FVI.h中声明*/
/*****************内部函数******************/
//static void delay5usForBH1750FVI(void) ;
static void delay180msForBH1750FVI(void) ;
static void BH1750FVIStartSignal(void) ;
static void BH1750FVIStopSignal(void) ;
static void BH1750FVIFreeBus(void) ;
static void BH1750FVIAcknowledge(void) ;
static void mcuAcknowledge(void) ;
static void BH1750FVIWriteByte(UB8 dat) ;
static UB8 BH1750FVIReadByte() ;
static void BH1750FVIPowerOn(void) ;
/**********************************************/
///******************************************************
//Function :delay5usForBH1750FVI
//Input :N/A
//Output :N/A
//Return :N/A
//Description :N/A
//Note :由STC-ISP V6.69软件针对相应MCU生成,若MCU不同
// 最好也要修改此函数。
//******************************************************/
//static void delay5usForBH1750FVI(void) //@11.0592MHz
//{
// unsigned char i;
//
// _nop_();
// _nop_();
// _nop_();
// i = 10;
// while (--i);
//}
/******************************************************
Function :delay180msForBH1750FVI
Input :N/A
Output :N/A
Return :N/A
Description :N/A
Note :由STC-ISP V6.69软件针对相应MCU生成,若MCU不同
最好也要修改此函数。
******************************************************/
static void delay180msForBH1750FVI(void) //@11.0592MHz
{
unsigned char i, j, k;
i = 8;
j = 145;
k = 99;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/******************************************************
Function :BH1750FVIStartSignal
Input :N/A
Output :N/A
Return :N/A
Description :BH1750FVI start signal
Note :N/A
******************************************************/
static void BH1750FVIStartSignal(void)
{
BH1750FVI_sda_bit = HIGH_LEVEL ;
//_nop_() ;
BH1750FVI_sclk_bit = HIGH_LEVEL ;
//_nop_() ;
BH1750FVI_sda_bit = LOW_LEVEL ;
//_nop_();
}
/******************************************************
Function :BH1750FVIStopSignal
Input :N/A
Output :N/A
Return :N/A
Description :BH1750FVI stop signal
Note :N/A
******************************************************/
static void BH1750FVIStopSignal(void)
{
BH1750FVI_sda_bit = LOW_LEVEL ;
//_nop_() ;
BH1750FVI_sclk_bit = HIGH_LEVEL ;
//_nop_() ;
BH1750FVI_sda_bit = HIGH_LEVEL ;
//_nop_();
}
/******************************************************
Function :BH1750FVIFreeBus
Input :N/A
Output :N/A
Return :N/A
Description :释放总线
Note :N/A
******************************************************/
static void BH1750FVIFreeBus(void)
{
//free bus
BH1750FVI_sclk_bit = HIGH_LEVEL ;
BH1750FVI_sda_bit = HIGH_LEVEL ;
}
/******************************************************
Function :BH1750FVIAcknowledge
Input :N/A
Output :N/A
Return :N/A
Description :主机等待BH1750FVI应答
Note :N/A
******************************************************/
static void BH1750FVIAcknowledge(void)
{
UB8 i=0 ;
BH1750FVI_sclk_bit = LOW_LEVEL ;
//_nop_() ;
BH1750FVI_sclk_bit = HIGH_LEVEL ;
//_nop_() ;
while((BH1750FVI_sda_bit) && (i<250))
{
i++;//暂时,具体见调试
//经过测试,这里的250足够大了
}
BH1750FVI_sclk_bit = LOW_LEVEL ;
}
/******************************************************
Function :mcuAcknowledge
Input :N/A
Output :N/A
Return :N/A
Description :主机作为接收机收到BH1750FVI数据后,发出应答信号
Note :N/A
******************************************************/
static void mcuAcknowledge(void)
{
BH1750FVI_sclk_bit = LOW_LEVEL ;
//_nop_();
BH1750FVI_sda_bit = LOW_LEVEL ;
//_nop_();
BH1750FVI_sclk_bit = HIGH_LEVEL;
}
/******************************************************
Function :BH1750FVIWriteByte
Input :dat
Output :N/A
Return :N/A
Description :write byte-data to BH1750FVI
Note :N/A
******************************************************/
static void BH1750FVIWriteByte(UB8 dat)
{
UB8 i;
for (i=0; i<8; i++)
{
BH1750FVI_sclk_bit = LOW_LEVEL ;
//_nop_();
//方法一
BH1750FVI_sda_bit = (bit)(dat & (0x80>>i)) ;
//方法二
//temp <<= 1 ;
//BH1750FVI_sda_bit = CY ;
//delay5usForBH1750FVI();/*经过测试可以屏蔽*/
//_nop_();
BH1750FVI_sclk_bit = HIGH_LEVEL ;
//_nop_();
}
}
/******************************************************
Function :BH1750FVIReadByte
Input :N/A
Output :N/A
Return :byte-data from BH1750FVI
Description :读取字节数据
Note :N/A
******************************************************/
static UB8 BH1750FVIReadByte()
{
UB8 i ;
UB8 dataCode = 0x00 ;
//Ready
/*Data on sda pin may change during scl low timer period*/
BH1750FVI_sclk_bit = LOW_LEVEL ;
//_nop_() ;
BH1750FVI_sda_bit = HIGH_LEVEL ;
//_nop_() ;
for(i=0; i<8 ; i++)
{
BH1750FVI_sclk_bit = HIGH_LEVEL ;
//_nop_() ;
dataCode<<= 1;
dataCode |= BH1750FVI_sda_bit ;
//_nop_() ;
BH1750FVI_sclk_bit = LOW_LEVEL ;
//_nop_() ;
}
return dataCode ;
}
/******************************************************
Function :BH1750FVIWriteCommand
Input :command Code
Output :N/A
Return :N/A
Description :写BH1750FVI内置命令
Note :N/A
******************************************************/
void BH1750FVIWriteCommand(UB8 command)
{
BH1750FVIStartSignal();
BH1750FVIWriteByte(BH1750FVI_ADDRESS | BH1750FVI_WRITE);
BH1750FVIAcknowledge();
BH1750FVIWriteByte(command);
BH1750FVIAcknowledge();
BH1750FVIFreeBus() ;
}
/******************************************************
Function :BH1750FVIReadResult
Input :N/A
Output :N/A
Return :Ambient Light Value
Description :读取亮度值
Note :N/A
******************************************************/
UW16 BH1750FVIReadResult(void)
{
UW16 temp ;
UB8 msb,lsb ;
BH1750FVIStartSignal();
BH1750FVIWriteByte(BH1750FVI_ADDRESS | BH1750FVI_READ ) ;
BH1750FVIAcknowledge();
msb= BH1750FVIReadByte() ;
mcuAcknowledge();
lsb= BH1750FVIReadByte();
/*后一个字节读取后,主机以结束信号代替应答信号*/
BH1750FVIStopSignal();
BH1750FVIFreeBus() ;
temp = ((UW16)(msb)) <<8 | lsb ;
temp = (float)temp/1.2 ;
/*这里有隐含的类型转换:float -- > unsigned int */
return temp ;
}
/******************************************************
Function :BH1750FVIPowerOn
Input :N/A
Output :N/A
Return :N/A
Description :"上电"命令
Note :对于"上电"命令,如果使用"One Time...."模式,
在转换结果后,硬件会自动切换到POWER DOWM模式,
因此还需要重新使用上电命令,在程序中,我使用了
的模式是"Continuously H-Resolution Mode",因此
不会自动切换到掉电模式,只需要在初始化时,调用
此函数。如果使用其他模式,可能还需要在其他地方调用。
并需要根据实际情况封装其他功能。
******************************************************/
static void BH1750FVIPowerOn(void)
{
BH1750FVIWriteCommand(BH1750FVI_POWER_ON); //power on
}
/******************************************************
Function :Init_BH1750
Input :N/A
Output :N/A
Return :N/A
Description :初始化
Note :N/A
******************************************************/
void BH1750FVIInit()
{
BH1750FVIPowerOn();
/*模式选择为 Continuously H-Resolution Mode*/
BH1750FVIWriteCommand(BH1750FVI_CONTINUOUSLY_H_RESOLUTION_MODE);
delay180msForBH1750FVI();
}
/*################BH1750FVI.c end################*/
补充:common.h
#ifndef __COMMON_H__
#define __COMMON_H__
typedef unsigned char UB8 ;
typedef unsigned short int UW16 ;
typedef unsigned long UL32 ;
typedef char SB8;
typedef short int SW16 ;
typedef long SL32 ;
#define HIGH_LEVEL 1
#define LOW_LEVEL 0
#endif /*__COMMON_H__*/