CC2530 模拟I2C的BH1750FVI光照传感器的驱动程序

2020-01-14 18:52发布

第二次发代码,希望能帮助到有需要的朋友,花了我好久才搞通,其中各种错误呜呜~~
/******************************************
描述;模拟I2C,光照传感器驱动代码
作者;leon_wf
时间;2011.7.21

********************************************/

#include <stdio.h>
#include <io.h>
#include "cc2530_sfr.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,4,0)
#define LIGHT_SCK_1()         HAL_IO_SET(1,4,1)
#define LIGHT_DTA_0()         HAL_IO_SET(1,3,0)
#define LIGHT_DTA_1()         HAL_IO_SET(1,3,1)

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

#define SDA_W() (P1DIR |=BV(3)  )
#define SDA_R() (P1DIR &=~BV(3) )
#define delay() {asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");}



                        /****command********/
#define DPOWR  0X00         //断电
#define POWER  0X01         //SHANG DIAN
#define RESET    0X07         //CHONG ZHI
#define CHMODE  0X10        //连续H分辨率
#define CHMODE2 0X11         //连续H分辨率2
#define CLMODE   0X13           //连续低分辨
#define H1MODE   0X20           //一次H分辨率
#define H1MODE2 0X21          //一次H分辨率2
#define L1MODE    0X23           //一次L分辨率模式

void delay_nus(void)
{       
        int i;
        int n=100;
        for(i=0;i<n;i++)//延迟32NOP为1US
                {
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
}
}

void delay_nms(int n)
{
        while(n--)
                {
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
        asm("nop");asm("nop");asm("nop");asm("nop");
                }
}





/****************************
启动I2C
数据在时钟高电平的时候从高往低跃变

*****************************/

void start_i2c(void)
{
        SDA_W() ;
        //LIGHT_SCK_0() ;
        //delay_nus(20);
        LIGHT_DTA_1();
        //delay_nus()  ;
        LIGHT_SCK_1() ;
        delay_nus() ;
        LIGHT_DTA_0() ;
        delay_nus()  ;
        LIGHT_SCK_0() ;
        delay_nus()  ;

        //delay()  ;
}


/********************************

结束I2C

数据在时钟高电平的时候从低往高跃变
********************************/

void stop_i2c(void)
{
        SDA_W() ;
        LIGHT_DTA_0() ;
        delay_nus();
        LIGHT_SCK_1() ;
        delay_nus();
        LIGHT_DTA_1() ;
        delay_nus();
        LIGHT_SCK_0() ;
        delay_nus();
       
}



/******************************
发送字节并且判断是否收到ACK
当收到ACK返回为0,否则返回为1

******************************/


char i2c_send(unsigned char val)                 
{
        int i;
        int ack;
        char error=0;
        SDA_W();
        for(i=0x80;i>0;i/=2)
                {
                        if(val&i)
                                LIGHT_DTA_1();
                        else
                                LIGHT_DTA_0();
                        delay_nus();
                        LIGHT_SCK_1() ;
                        delay_nus();
                        LIGHT_SCK_0() ;
                        delay_nus();
                               
                }
       
        LIGHT_DTA_1();
        SDA_R();
        //delay_nus();
        LIGHT_SCK_1() ;
        delay_nus();
        if(LIGHT_DTA())
                error=1;
        delay_nus();
        LIGHT_SCK_0() ;
        return error;
       
}

/***************************

读取I2C的字节,并且发送ACK
当参数为1的时候发送一个ACK(低电平)


***************************/

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_nus();
                        SDA_R();
                        if(LIGHT_DTA())
                                val=(val|i);
                        delay_nus();
                        LIGHT_SCK_0() ;
                        delay_nus();
                       
                       
                }
        SDA_W();
        if(ack)
                LIGHT_DTA_0();
        else
                LIGHT_DTA_1();
        delay_nus();
        LIGHT_SCK_1() ;
        delay_nus();
        LIGHT_SCK_0() ;
        LIGHT_DTA_1();
        return val;
       
}






/**************************
测量光张强度

***************************/


unsigned char
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 ack8=1;
       
        unsigned char t0;
        unsigned char t1;
        unsigned char t;
        int i;
        P1DIR|=BV(4);
        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=(((t0<<8)|t1)/1.2);
        return t;
       
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。