第二次发代码,希望能帮助到有需要的朋友,花了我好久才搞通,其中各种错误呜呜~~
/******************************************
描述;模拟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;
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>