对于死太惨"1T"的单片机需要加快延时。建议直接在后面加一个0,I2C就没有问题了。
这个程序并不是我原创。是ourDEV中某个24C串口操作里面剥离的。感觉蛮好用。不过稍微改变语法,让它在SDCC中通过。
这个函数支持TEA5767/24C系列串行储存器的操作。理论是只要是I2C的器件都没有问题。
该程序在89C52/SDCC v3.1.0中通过,上代码。
#ifndef __I2C_H__ #define __I2C_H__ //--------------------------------------------------------------- #define I2C_SCL_0 I2C_SCL = 0 #define I2C_SCL_1 I2C_SCL = 1 #define I2C_SDA_0 I2C_SDA = 0 #define I2C_SDA_1 I2C_SDA = 1 //--------------------管脚定义----------------------------------- #define I2C_SCL P1_1 // I2C总线的时钟信号 #define I2C_SDA P1_2 // I2C总线的数据信号 //--------------------------------------------------------------- #define DELAY_nT 1 // 延时1个机器周期(2+2*DELAY_nT), // (延时时间大于5us,因此机器个数 // 根据晶振频率而定) void Delay_I2C() { unsigned char t=DELAY_nT; while(--t); } //*********************************************************************** // 函数名称:I2C_Start() // 功 能:启动I2C总线 // 入口参数:无 // 出口参数:无 //*********************************************************************** void I2C_Start(void) { I2C_SDA_1; I2C_SCL_1; Delay_I2C(); // 大于5us I2C_SDA_0; Delay_I2C(); // 大于5us I2C_SCL_0; Delay_I2C(); // 大于5us } //*********************************************************************** // 函数名称:I2C_Stop() // 功 能:终止I2C总线 // 入口参数:无 // 出口参数:无 //*********************************************************************** void I2C_Stop(void) { /*I2C_SDA_0; I2C_SCL_1; t = DELAY_nT; while(--t); // 大于4us I2C_SDA_1; t = DELAY_nT; while(--t); // 大于5us I2C_SCL_0; t = DELAY_nT; while(--t); // 大于5us I2C_SCL_1;*/ I2C_SCL_0; I2C_SDA_0; Delay_I2C(); // 大于5us I2C_SCL_1; Delay_I2C(); // 大于5us I2C_SDA_1; Delay_I2C(); // 大于5us } //*********************************************************************** // 函数名称:I2C_Send_Bit_0() // 功 能:发送比特0 // 入口参数:无 // 出口参数:无 //*********************************************************************** void I2C_Send_Bit_0(void) { I2C_SDA_0; I2C_SCL_1; Delay_I2C(); // 大于5us // tL = 6us I2C_SCL_0; // t = DELAY_nT; while(--t); // 大于5us } //*********************************************************************** // 函数名称:I2C_Send_Bit_1() // 功 能:发送比特1 // 入口参数:无 // 出口参数:无 //*********************************************************************** void I2C_Send_Bit_1(void) { I2C_SDA_1; I2C_SCL_1; Delay_I2C(); // 大于5us I2C_SCL_0; // Delay_I2C(); // 大于5us } //*********************************************************************** // 函数名称:I2C_Check_Ack() // 功 能:发送完一个字节后检验设备的应答信号 // 入口参数:无 // 出口参数:返回值为True,成功 // 返回值为False,失败 //*********************************************************************** unsigned char I2C_Check_Ack(void) { I2C_SDA_1; I2C_SCL_1; Delay_I2C(); // 大于5us F0 = I2C_SDA; Delay_I2C(); // 大于5us I2C_SCL_0; Delay_I2C(); // 大于5us if( F0 == 1 ) return FALSE; else return TRUE; } //*********************************************************************** // 函数名称:I2C_Write8Bit() // 功 能:向I2C总线写入8bit数据 // 入口参数:I2C_data 将要写入I2C总线的8bit数据 // 出口参数:无 //*********************************************************************** void I2C_Write8Bit(unsigned char I2C_data) { unsigned char i; for( i=0;i<8;i++ )//秒懂。好猥琐的写法,致远吐糟ing { if( (I2C_data<<i)&0x80 ) I2C_Send_Bit_1(); else I2C_Send_Bit_0(); } } //*********************************************************************** // 函数名称:I2C_Read8Bit() // 功 能:从I2C总线接收8bit数据 // 入口参数:无 // 出口参数:返回值为从I2C总线上接收到的8bit数据 //*********************************************************************** unsigned char I2C_Read8Bit(void) { unsigned char t,I2C_data = 0,i; for( i = 0; i < 8; i++ ) { I2C_data = I2C_data << 1; I2C_SDA_1; I2C_SCL_1; t = DELAY_nT; while(--t); F0 = I2C_SDA; t = DELAY_nT; while(--t); I2C_SCL_0; if( F0 == 1 ) I2C_data = I2C_data | 0x01; } return I2C_data; } #endif
欢迎光临 (http://www.51hei.com/bbs/) | Powered by Discuz! X3.1 |