基于BH1750模塊實現的光強度檢測,使用的是STM32F103C8T6
單片機源程序如下:
- #include "bh1750.h"
- #include "delay.h"
- #include "timer.h"
- u8 BUF[8];
- u16 temp2=0;
- float lux=0;
- void bh1750_iic_init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB時鐘
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- GPIO_SetBits(GPIOB,GPIO_Pin_5|GPIO_Pin_6); //PB6,PB7 輸出高
- }
- /****向BH1750單次寫命令****/
- void Single_Write_bh1750(unsigned char Reg_Address)
- {
- bh1750_iic_start();
- bh1750_send_byte(0x46); //發送器件地址0100 0110 最后一位0,表示寫
- //IIC_Wait_Ack();
- bh1750_send_byte(Reg_Address);
- //IIC_Wait_Ack();
- bh1750_iic_stop();
- }
- /****BH1750初始化****/
- void bh1750_Init(void)
- {
- char dir=0;
- unsigned char value=0;
- TIM3_PWM_Init(899,0);
- bh1750_iic_init();
- TIM_SetCompare3(TIM3,0);
-
- while(1)
- {
- Single_Write_bh1750(0x01);
- Single_Write_bh1750(0x10);
- delay_ms(200);
- bh1750_ReadContinuous1();
- temp2=BUF[0];
- temp2=(temp2<<8)+BUF[1];
- lux=(float)temp2/1.2; //lux是float型
- if((lux>0)&&(lux<50))
- value=10;
- else if(lux<75)
- value=20;
- else if(lux<100)
- value=40;
- else if(lux<125)
- value=50;
- else if(lux<150)
- value=60;
- else if(lux<175)
- value=70;
- else if(lux<200)
- value=80;
- else if(lux<250)
- value=90;
- else if(lux<280)
- value=110;
- else if(lux<300)
- value=120;
- else if(lux<320)
- value=130;
- else if(lux<340)
- value=140;
- else if(lux<360)
- value=150;
- else if(lux<380)
- value=160;
- else if(lux<400)
- value=170;
- else if(lux<410)
- value=180;
- else if(lux<450)
- value=190;
- else if(lux<800)
- value=240;
- printf("光照強度:%f value:%d\r\n",lux,value);
- TIM_SetCompare3(TIM3,value);
-
- //delay_ms(1000);
- }
-
-
- }
- /****從BH1750單次讀Lux****/
- /****
- 模式選擇:H-Resolution Mode,分辨率1lux
- 單次讀Opecode:0010 0000 ,即0x20
- 器件地址:0100011,ADDR接GND
- ****/
- void bh1750_ReadOneTime(void)
- {
-
- bh1750_iic_start();
- bh1750_send_byte(0x46); //發送器件地址0100 0110 最后一位0,表示寫
- bh1750_recv_ack();
- bh1750_send_byte(0x20); //發送One time H-Resolution Mode的Opecode 0010 0000,分辨率為1lux
- bh1750_recv_ack();
- bh1750_iic_stop();
- delay_ms(200);
- bh1750_iic_start();
- bh1750_send_byte(0x47); //
- bh1750_recv_ack();
- BUF[0]=bh1750_recv_byte(1);
- //IIC_Ack(); //主機應答
- //temp1=temp<<8;
- BUF[1]=bh1750_recv_byte(0);
- //IIC_NAck(); //主機不應答
- bh1750_iic_stop();
-
-
- // temp2=BUF[0];
- // temp2=(temp2<<8)+BUF[1];
- // lux=(float)temp2/1.2; //lux是float型
-
- //return lux;
- //delay_ms(200);
- }
- /****從BH1750連續讀Lux****/
- /****
- 模式選擇:H-Resolution Mode,分辨率1lux
- 連續讀Opecode:0001 0000
- 器件地址:0100011,ADDR接GND
- ****/
- void bh1750_ReadContinuous1(void)
- {
- // u16 temp=0,temp1=0;
- bh1750_iic_start();
- bh1750_send_byte(0x46); //發送器件地址0100 0110 最后一位0,表示寫
- bh1750_recv_ack();
- bh1750_send_byte(0x10); //發送Continuous H-Resolution Mode的Opecode 0001 0000,分辨率為1lux
- bh1750_recv_ack();
- bh1750_iic_stop();
- delay_ms(200);
- bh1750_iic_start();
- bh1750_send_byte(0x47);
- bh1750_recv_ack();
-
-
- BUF[0]=bh1750_recv_byte(1);
- BUF[1]=bh1750_recv_byte(0);
-
-
- //temp=bh1750_recv_byte(1);
- //temp1=bh1750_recv_byte(0);
- bh1750_iic_stop();
-
- //temp2=temp1+(temp<<8);
- //lux=(float)temp2/1.2; //lux是float型
- }
- void Conversion(void)
- {
- temp2=BUF[0];
- temp2=(temp2<<8)+BUF[1];
- lux=(float)temp2/1.2; //lux是float型
-
- }
- /**************************************
- 起始信號
- **************************************/
- void bh1750_iic_start(void)
- {
- BH1750_SDA_OUT() //設置SDA線為輸出
- //在開始數據傳輸前,先讓SDA和SCL都拉高
- BH1750_IIC_SDA=1; //發送起始條件的數據信號,釋放總線
- delay_us(2);
- BH1750_IIC_SCL=1;
- delay_us(5); //Tsu;STA:起始條件的建立時間大于4.7us。
-
- BH1750_IIC_SDA=0; //SDA由高變為低表示開始信號
- delay_us(4); //起始條件的保持時間大于4us
- BH1750_IIC_SCL=0; //鉗住IIC總線,準備發送或者接收數據
- delay_us(2);
- }
- /**************************************
- 停止信號
- **************************************/
- void bh1750_iic_stop(void)
- {
- BH1750_SDA_OUT() //設置SDA線為輸出
-
- //IIC_SCL=0; //此句是調試BH1750時加,2018.03.03
-
- BH1750_IIC_SDA=0; //發送停止信號的數據信號
- delay_us(2);
- BH1750_IIC_SCL=1; //發送停止信號的時鐘信號
- delay_us(5); //停止信號的建立時間大于4us
- BH1750_IIC_SDA=1; //發送停止信號
- delay_us(4); //;
- }
- /**************************************
- 發送應答信號
- 入口參數:ack (0:ACK 1:NAK)
- **************************************/
- void bh1750_send_ack(char ack)
- {
- BH1750_IIC_SCL=0;
- BH1750_SDA_OUT();
- BH1750_IIC_SDA=ack; //主器件應答
- delay_us(2);
- BH1750_IIC_SCL=1;
- delay_us(4); //SCL高電平周期大于4us
- BH1750_IIC_SCL=0; //清時鐘線,鉗住IIC總線以便繼續接收
- delay_us(2);
- }
- /**************************************
- 接收應答信號
- **************************************/
- char bh1750_recv_ack(void)
- {
- u8 ucErrorTime=0;
- BH1750_SDA_IN(); //SDA設置成輸入
- BH1750_IIC_SDA=1;
- delay_us(2);
- BH1750_IIC_SCL=1;
- delay_us(2);
- while(BH1750_READ_SDA)
- {
- ucErrorTime++;
- if(ucErrorTime>=250)
- {
- bh1750_iic_stop();
- return 1;
- }
- }
- BH1750_IIC_SCL=0;
- return 0;
- }
- /**************************************
- 向IIC總線發送一個字節數據
- **************************************/
- void bh1750_send_byte(char dat)
- {
- u8 i;
- BH1750_SDA_OUT();
- for(i=0;i<8;i++)
- {
- if((dat<<i)&0x80) BH1750_IIC_SDA=1; //判斷發送位
- else BH1750_IIC_SDA=0;
- delay_us(2);
- BH1750_IIC_SCL=1; //拉高SCL,通知被控器開始接收數據位
- delay_us(4); //保證SCL高電平周期大于4us
- BH1750_IIC_SCL=0; //拉低SCL,允許SDA傳輸下一位數據。因為只有在SCL=0時才允許SDA的狀態發生變化
- delay_us(2);
- }
- //以下四句是調試BH1750時添加的,2018.03.03
- //特別注意;用方法三時,以下四句不可去掉,去掉后得到的數有問題
- //用方法二時,以下四句需注釋掉,否則也會有問題,至于原因暫時還不清楚。
- // IIC_SDA=0;
- // delay_us(2);
- // IIC_SCL=1;
- // delay_us(2);
-
- BH1750_IIC_SCL=0; //拉低SCL,為下次數據傳輸做好準備
- delay_us(2);
- }
- /**************************************
- 從IIC總線接收一個字節數據
- 用來接收從器件傳來的數據,ack為1時,發送Ack(產生應答);ack為0時,發送NAck(不產生應答)
- **************************************/
- char bh1750_recv_byte(unsigned char ack)
- {
- unsigned char i,receive=0;
- BH1750_SDA_IN();
- for(i=0;i<8;i++)
- {
- BH1750_IIC_SCL=0; //置SCL為低,準備接收數據位
- delay_us(5); //時鐘低電平周期大于4.7us
- BH1750_IIC_SCL=1; //置SCL為高,使SDA上數據有效
- delay_us(2);
- receive=receive<<1;
- if(BH1750_READ_SDA) receive=receive+1; //讀取SDA,把接收的數據位放入receve中,若此處寫成IIC_SDA==1,會失敗,思考原因?
- delay_us(2);
- }
- if(!ack)
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
Keil代碼下載:
bh1750.rar
(275.76 KB, 下載次數: 435)
2018-6-6 02:37 上傳
點擊文件名下載附件
|