//********************************************************** //** IIC驱动程序 ** //** 单片机: STC12C5410AD 主频: 24MHz ** //** Jumping <2008.04.20> ** //********************************************************** //#include // AT89C4051头文件 #include "../inc/STC12C5410AD.H" // AT89C4051头文件 #include // 系统调令头文件 #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); }