//** IIC驅動程序 **
//** 單片機: STC12C5410AD 主頻: 24MHz **
//** Jumping <2008.04.20> **
//**********************************************************
//#include <REGX051.H> // AT89C4051頭文件
#include "../inc/STC12C5410AD.H" // AT89C4051頭文件
#include <INTRINS.H> // 系統調令頭文件
#include "def.h" // 類型定義文件
#include "config.h" // 配置頭文件
#include "IIC.h" // 配置頭文件
#include "uart.h" // 配置頭文件
#define SomeNOP(); {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
//*****變量聲明****
INT CH0,CH1;
// *** 函數聲明 ***
void I2C_Start (void);
void I2C_Stop (void);
BOOL Send_Byte_I2C(BYTE tmData);
BYTE Read_Byte_I2C_ACK();
BYTE Read_Byte_I2C_NoACK();
uchar TSL2561_read_byte( uchar addr);
void InitTsl256x(void);
INT GetLux(void);
//BOOL Read_Data_I2C(BYTE iNum, unsigned int wAddr, BYTE tmData[64]);
//BOOL Write_Data_I2C(BYTE iNum, unsigned int wAddr, BYTE tmData[64]);
//***************************************************************************************
unsigned int CalculateLux(unsigned int iGain, unsigned int tInt, unsigned int ch0, unsigned int ch1, int iType);
//#pragma OPTIMIZE(5)
/*******************************************************************************
* 名 稱: I2C_Start()
* 功 能: 啟動I2C操作
* 入口參數: 無
* 出口參數: 無
*******************************************************************************/
void I2C_Start (void)
{
SDA=0;
SCL=0;
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SDA=1;
SCL=1;
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SDA=0;
SCL=0;
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SDA=1;
SCL=1;
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SDA=0;
SCL=0;
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SDA=1;
SCL=1;
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SDA=0;
SCL=0;
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SDA=1;
SCL=1;
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SDA=1;
SCL=0;
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SDA=1;
SCL=1;
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SDA=0;
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
SomeNOP();//數據線保持高,時鐘線從高到低壹次跳變,I2C通信開始
}
/*******************************************************************************
* 名 稱: I2C_Stop()
* 功 能: 結束I2C操作
* 入口參數: 無
* 出口參數: 無
*******************************************************************************/
void I2C_Stop (void)
{
SDA=0;
SomeNOP(); //數據線保持低,時鐘線從低到高壹次跳變,I2C通信停止
SCL=1;
SomeNOP();
SDA=1;
SomeNOP();
}
/*******************************************************************************
* 名 稱: I2C_Start()
* 功 能: 啟動I2C操作
* 入口參數: 無
* 出口參數: 無
*******************************************************************************/
void SendAck(void)
{
SDA=1;
SCL=0;
SomeNOP(); //數據線保持低,時鐘線發生壹次從高低的跳變 發送壹個應答信號
SCL=1;
SomeNOP();
// SCL=0;
}
/*******************************************************************************
* 名 稱: I2C_Start()
* 功 能: 啟動I2C操作
* 入口參數: 無
* 出口參數: 無
*******************************************************************************/
void SendNotAck(void)
{
SDA=1;
SCL=0;
SomeNOP(); //數據線保持高,時鐘線發生壹次從高低的跳變 沒有應答
SCL=1;
SomeNOP();
// SCL=0;
}
/*******************************************************************************
* 名 稱: I2C_Start()
* 功 能: 啟動I2C操作
* 入口參數: 無
* 出口參數: 無
*******************************************************************************/
BOOL Send_Byte_I2C(BYTE ch)
{
unsigned char i=8;
while (i--)
{
SCL=0;
_nop_();
SDA=(bit)(ch&0x80);
ch<<=1;
SomeNOP(); //時鐘保持低可以發送數據
SCL=1;
SomeNOP();
}
SCL=0;
SendNotAck();
return 0;
}
/*******************************************************************************
* 名 稱: I2C_Start()
* 功 能: 啟動I2C操作
* 入口參數: 無
* 出口參數: 無
*******************************************************************************/
BYTE Read_Byte_I2C_ACK(void)
{
BYTE i,tdata;
i=8;tdata=0;
SDA=1;
_nop_();_nop_();_nop_();
while (i--)
{
tdata<<=1;
SCL=0;
SomeNOP();
SCL=1;
SomeNOP(); //時鐘做壹次從低到高的跳變 可以接收數據
tdata|=SDA;
}
SCL=0;
SendAck();
return tdata;
}
/*******************************************************************************
* 名 稱: I2C_Start()
* 功 能: 啟動I2C操作
* 入口參數: 無
* 出口參數: 無
*******************************************************************************/
BYTE Read_Byte_I2C_NoACK()
{
BYTE i;
BYTE tmData = 0;
SDA=1;
for(i=0; i<8; i++)
{
tmData *= 2;
SCL = 1;
if(SDA)
tmData |= 0x01;
SCL = 0;
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
_nop_ ();
}
/* SCL = 0;*/
return tmData;
}
/*******************************************************************************
* 名 稱: TSL2561_write_byte()
* 功 能: 啟動I2C操作
* 入口參數: 無
* 出口參數: 無
*******************************************************************************/
uchar TSL2561_write_byte( unsigned char addr, unsigned char dat)
{
uchar status=0;
I2C_Start(); //開始
status=Send_Byte_I2C(TSL2561_ADDR|TSL2561_WR);//寫TSL2561地址
status=Send_Byte_I2C(0x80|addr); //寫命令
status=Send_Byte_I2C(dat); //寫數據
I2C_Stop( ); //停止
delay_1ms(2); //延時2 ms
return 0;
}
/*******************************************************************************
* 名 稱: TSL2561_read_byte()
* 功 能: 啟動I2C操作
* 入口參數: 無
* 出口參數: 無
*******************************************************************************/
uchar TSL2561_read_byte( uchar addr)
{
uchar status=0;
I2C_Start(); //開始
status=Send_Byte_I2C(TSL2561_ADDR|TSL2561_WR);//寫TSL2561地址
status=Send_Byte_I2C(0x80|addr); //寫命令
I2C_Start(); //Re開始
status=Send_Byte_I2C(TSL2561_ADDR|TSL2561_RD); //寫TSL2561地址
status=Read_Byte_I2C_ACK(); //讀數據
I2C_Stop( ); //停止
delay_1ms(10);
return status;
}
/*******************************************************************************
* 名 稱: InitTsl256x()
* 功 能: 啟動I2C操作
* 入口參數: 無
* 出口參數: 無
*******************************************************************************/
void InitTsl256x(void)
{
uchar status;
status=TSL2561_write_byte(0x00,PWUP); //寄存器00H
//status=TSL2561_write_byte(0x01,0x12); //寄存器00H
status=TSL2561_write_byte(0x01,0x02); //寄存器00H //jumping080522 change the gain To 1x
status=TSL2561_write_byte(0x02,0x00); //寄存器00H
status=TSL2561_write_byte(0x03,0x00); //寄存器00H
status=TSL2561_write_byte(0x04,0x00); //寄存器00H
status=TSL2561_write_byte(0x05,0x00); //寄存器00H
status=TSL2561_write_byte(0x06,0x00); //寄存器00H
/*
I2C_Start(); //開始
status=Send_Byte_I2C(TSL2561_ADDR|TSL2561_WR); //寫TSL2561地址
//jumpingtest
while(!status)//test the Tsl2561 ack
LED=0;
LED=1;
status=Send_Byte_I2C(0x90|REG_CTR); //寫命令
// I2C_Start(); //開始
// status=Send_Byte_I2C(TSL2561_ADDR|TSL2561_RD);//寫TSL2561地址
status=Send_Byte_I2C(0x07);//寫n ge
status=Send_Byte_I2C(PWUP); //寄存器00H
status=Send_Byte_I2C(0x12); //寄存器01H -the gain=1 16x -the timer=10 401ms
status=Send_Byte_I2C(0x00); //寄存器02H
status=Send_Byte_I2C(0x00); //寄存器03H
status=Send_Byte_I2C(0x00); //寄存器04H
status=Send_Byte_I2C(0x00); //寄存器05H
status=Send_Byte_I2C(0x00); //寄存器06H no interrupt
I2C_Stop( ); //停止 */
delay_1ms(10); //延時10 ms
}
//****************************************************************************
//
// Copyright -Handson Jumping, Inc.
//
// lux equation approximation without floating point calculations
//////////////////////////////////////////////////////////////////////////////
// Routine: unsigned int CalculateLux(unsigned int ch0, unsigned int ch0, int iType)
//
// Description: Calculate the approximate illuminance (lux) given the raw
// channel values of the TSL2560. The equation if implemented
// as a piece.wise linear approximation.
//
// Arguments: unsigned int iGain . gain, where 0:1X, 1:16X
// unsigned int tInt . integration time, where 0:13.7mS, 1:100mS, 2:402mS,
// 3:Manual
// unsigned int ch0 . raw channel value from channel 0 of TSL2560
// unsigned int ch1 . raw channel value from channel 1 of TSL2560
// unsigned int iType . package type (T or CS)
//
// Return: unsigned int . the approximate illuminance (lux)
//
//////////////////////////////////////////////////////////////////////////////
unsigned int CalculateLux(unsigned int iGain, unsigned int tInt, unsigned int ch0, unsigned int ch1, int iType)
{
unsigned long ratio1;
unsigned long ratio;
unsigned long temp;
unsigned long lux;
unsigned long chScale; //TSL2561
unsigned long channel1; //TSL2561
unsigned long channel0; //TSL2561
unsigned int b, m;
//........................................................................
// first, scale the channel values depending on the gain and integration time
// 16X, 402mS is nominal.
// scale if integration time is NOT 402 msec
switch (tInt)
{
case 0: // 13.7 msec
chScale = CHSCALE_TINT0;
break;
case 1: // 101 msec
chScale = CHSCALE_TINT1;
break;
default: // assume no scaling
chScale = (1 << CH_SCALE);
break;
}
// scale if gain is NOT 16X
if (!iGain) chScale = chScale << 4; // scale 1X to 16X
// scale the channel values
channel0 = (ch0 * chScale) >> CH_SCALE;
channel1 = (ch1 * chScale) >> CH_SCALE;
//........................................................................
// find the ratio of the channel values (Channel1/Channel0)
// protect against divide by zero
ratio1 = 0;
if (channel0 != 0) ratio1 = (channel1 << (RATIO_SCALE+1)) / channel0;
// round the ratio value
ratio = (ratio1 + 1) >> 1;
// is ratio <= eachBreak ?
switch (iType)
{
case 0: // T package
if ((ratio >= 0) && (ratio <= K1T))
{b=B1T; m=M1T;}
else if (ratio <= K2T)
{b=B2T; m=M2T;}
else if (ratio <= K3T)
{b=B3T; m=M3T;}
else if (ratio <= K4T)
{b=B4T; m=M4T;}
else if (ratio <= K5T)
{b=B5T; m=M5T;}
else if (ratio <= K6T)
{b=B6T; m=M6T;}
else if (ratio <= K7T)
{b=B7T; m=M7T;}
else if (ratio > K8T)
{b=B8T; m=M8T;}
break;
case 1:// CS package
/*
if ((ratio >= 0) && (ratio <= K1C))
{b=B1C; m=M1C;}
else if (ratio <= K2C)
{b=B2C; m=M2C;}
else if (ratio <= K3C)
{b=B3C; m=M3C;}
else if (ratio <= K4C)
{b=B4C; m=M4C;}
else if (ratio <= K5C)
{b=B5C; m=M5C;}
else if (ratio <= K6C)
{b=B6C; m=M6C;}
else if (ratio <= K7C)
{b=B7C; m=M7C;}
else if (ratio > K8C)
{b=B8C; m=M8C;}
*/
break;
}
temp = ((channel0 * b)- (channel1 * m));
// do not allow negative lux value
if (temp < 0) temp = 0;
// round lsb (2^(LUX_SCALE.1))
temp += (1 << (LUX_SCALE-1));
// strip off fractional portion
lux = temp >> LUX_SCALE;
return(lux);
}
/*******************************************************************************
* 名 稱: GetLux()
* 功 能: 啟動I2C操作
* 入口參數: 無
* 出口參數: 無
*******************************************************************************/
INT GetLux(void)
{
INT i;
i=0;
CH0=TSL2561_read_byte(REG_CH0_L);
CH0=CH0+TSL2561_read_byte(REG_CH0_H)*256;
CH1=TSL2561_read_byte(REG_CH1_L);
CH1=CH1+TSL2561_read_byte(REG_CH1_H)*256;
i=CalculateLux(GAIN_1X,ITIME_400MS,CH0,CH1,FootType_T);
return (i);
}