CC2530下ZigBee协议栈中添加BH1750数字光照传感器

项目里需要获得光照强度,之前用的是光敏电阻,但是光敏电阻实在不精确,换用BH1750数字光照传感器。网上购买后,送的资料都是单片机的,移植到ZigBee协议栈里面,时序有些问题,在网上找的一些资料,很杂乱。主要出现两个问题:一、读取不到数据;二、读取到的数据是乱的。

仔细研究之后,发现,第一个问题读不到数据,八成是延时函数有差别;第二个问题,一直以为是时序的问题,纠结了很久还是没弄好,后来突然想把数据处理的地方单独弄出来测试,结果正是这里,采集到数据,转为字符串的时候,数据类型跟所需要的数据类型有差,最大范围不同,可能每个人宏或者自定义的数据类型都不太一样,所以移植过来的时候,虽然名字一样,但是实际上定义的时候不一样,导致使用的时候不容易发现问题。

下面贴上代码。(之前在网上看到别人做的bh1750,想问他买代码,结果告诉我一个代码要我80,瞬间无语,还好自己弄出来了 ,共享给大家,也给自己提个醒,最是觉得没有问题的地方,往往就是问题所在,需时刻抱有怀疑的态度)

BH1750.h:

#ifndef __BH1750_H
#define __BH1750_H

#include <ioCC2530.h>

#define st(x)      do { x } while (__LINE__ == -1)
#define HAL_IO_SET(port, pin, val)        HAL_IO_SET_PREP(port, pin, val)
#define HAL_IO_SET_PREP(port, pin, val)   st( P##port##_##pin## = val; )
#define HAL_IO_GET(port, pin)   HAL_IO_GET_PREP( port,pin)
#define HAL_IO_GET_PREP(port, pin)   ( P##port##_##pin)


#define LIGHT_SCK_0()         HAL_IO_SET(1,3,0)
#define LIGHT_SCK_1()         HAL_IO_SET(1,3,1)
#define LIGHT_DTA_0()         HAL_IO_SET(1,1,0)
#define LIGHT_DTA_1()         HAL_IO_SET(1,1,1)

#define LIGHT_DTA()          HAL_IO_GET(1,1)
#define LIGHT_SCK()          HAL_IO_GET(1,3)

#define SDA_W() (P1DIR |=(1 << 1)  )
#define SDA_R() (P1DIR &=~(1 << 1) )

                       
#define LIGHT_INIT()                           \
do{                                            \
	P1SEL &= ~0x08;                        \
	P1DIR |=0x08;                           \
	P1_3 = 1;                                  \
	                                 \
	P1SEL &= ~0x02;                        \
	P1DIR |= 0x02;                         \
	P1_1 = 1; 	                             \
}while(0)
	
extern unsigned short get_light(void);

#endif // __BH1750_H


BH1750.c:

#include "BH1750.h"
#include "OnBoard.h"

void halMcuWaitUs(uint16 usec)
{
    while(usec--)
    {
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
        asm("nop");
    }
}
//以ms延时
void halMcuWaitMs(uint16 msec)
{
    while(msec--)
        halMcuWaitUs(1000);
}

void delay_us()
{
  halMcuWaitUs(1);
 // MicroWait(1);
}
void delay_5us()
{
  halMcuWaitUs(5);
  //MicroWait(5);
}
void delay_10us()
{
  halMcuWaitUs(10);
  //MicroWait(10);
}
void delay_nms(int n)
{
  halMcuWaitMs(n);
}
/****************************/
static void start_i2c(void)
{
  SDA_W() ;
  LIGHT_DTA_1();//
  LIGHT_SCK_1() ;//
  delay_us() ;
  LIGHT_DTA_0() ;
  delay_us()  ;
  LIGHT_SCK_0() ;
  delay_us()  ;
  //delay()  ;
}

static void stop_i2c(void)
{
  SDA_W() ;
  LIGHT_DTA_0() ;
  delay_us();
  LIGHT_SCK_1() ;
  delay_us();
  LIGHT_DTA_1() ;
  delay_us();
  LIGHT_SCK_0() ;
  delay_us();  
}
static char i2c_send(unsigned char val)                 
{
        int i;
        char error=0;
        SDA_W();
        for(i=0x80;i>0;i/=2)
		{
			if(val&i)
				LIGHT_DTA_1();
			else
				LIGHT_DTA_0();
			delay_us();
			LIGHT_SCK_1() ; 
			delay_us();
			LIGHT_SCK_0() ;
			delay_us();					
		}
        LIGHT_DTA_1();
        SDA_R();
        delay_us();
        //delay_us();
        LIGHT_SCK_1() ; 
        delay_us();
        if(LIGHT_DTA())
            error=1;
        delay_us();
        LIGHT_SCK_0() ;
        return error;
        
}
static char i2c_read(char ack)
{
        int i;
        char val=0;
        LIGHT_DTA_1();
        //SDA_R();
        for(i=0x80;i>0;i/=2)
                {
                        
                        LIGHT_SCK_1() ;
                        delay_us();
                        SDA_R();
                        //SDA_W();
                        //LIGHT_DTA_0();
                        //LIGHT_DTA_0() ;
                        
                        //delay_us();
                        if(LIGHT_DTA())
                                val=(val|i);
                        delay_us();
                        //SDA_R();
                        LIGHT_SCK_0() ;
                        delay_us();
                        
                        
                }
        SDA_W();
        if(ack)
                LIGHT_DTA_0();
        else
                LIGHT_DTA_1();
        delay_us();
        LIGHT_SCK_1() ;
        delay_us();
        LIGHT_SCK_0() ;
        LIGHT_DTA_1();
        return val;
        
}
unsigned short get_light(void)
{        
        unsigned char ack1=1;
        unsigned char ack2=1;
        unsigned char ack3=1;
        unsigned char ack4=1;
        unsigned char ack5=1;
        unsigned char ack6=1;
        unsigned char ack7=1;
        
        unsigned char t0;
        unsigned char t1;
        unsigned short t;

        P1DIR |= (1 << 1);
        delay_nms(200);

		start_i2c();
		ack1=i2c_send(0x46);
		if(ack1)
				return 255;
		ack2=i2c_send(0x01);
		if(ack2)
				return 254;
		stop_i2c();           //init
		start_i2c();
		ack3=i2c_send(0x46);
		if(ack3)
				return 253;
		ack4=i2c_send(0x01);
		if(ack4)
				return 252;
		stop_i2c();//power
		start_i2c();
		ack5=i2c_send(0x46);
		if(ack5)
				return 251;
		ack6=i2c_send(0x10);
		if(ack6)
				return 250;
		stop_i2c();                     
        delay_nms(1500);
        start_i2c();
        
		ack7=i2c_send(0x47);
		if(ack7)
				return 249;
                        
        t0 = i2c_read(1);
        t1 = i2c_read(0);
        stop_i2c();
        t =  ((short)t0)<<8;
        t |= t1;
        return t;
}


在主函数中加入以下函数(注意,此处就是最容易忽视的地方,uint应该是unsigned int,不能是范围太小的类型):

char wan,qian,bai,shi,ge;

void conversion(unsigned int temp_data)    
{
    wan=(uint)temp_data/10000 ;
    temp_data=temp_data%10000; 
    qian=(uint)temp_data/1000 ;
    temp_data=temp_data%1000;  
    bai=(uint)temp_data/100;
    temp_data=temp_data%100;    
    shi=(uint)temp_data/10;
    temp_data=temp_data%10;      
    ge=(uint)temp_data;
}
调用光照获取函数,讲数据转为字符串:

uint32 w;
    
    w = get_light()/1.2;
    conversion(w);
    char buf[5];
    buf[0] = wan + 48;
    buf[1] = qian + 48;
    buf[2] = bai + 48;
    buf[3] = shi + 48;
    buf[4] = ge + 48;
得到字符数组后,就很随意了。



评论 66
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值