⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 i2c协议实现
💻 C
字号:
/********************** I2C总线基本操作函数******************************
[文件名] I2C.c+I2C.H+ASMselect.h
[版本] TV0.2
[修正] hxc 
hxc last change time 2006.4.10 x:x
hxc last check time 2006.4.24 17:00
***************************************************************************/
#include "ASMselect.h "
#if ASMI2C
#include <intrins.h>
#include <reg51x.h>
#include <stdio.h>
#include <i2c.h>
#include "TAB.h"
#include "78e65.h"
sbit SCL		= P4^1;
sbit SDA		= P4^0;
 bit  i2cok;//extern bit  i2cok
/****************************************************************************
*    函数原型: void delay(void);
*    功    能: 本函数实际上只有一条返回指令, 在具体应用中可视具体要求增加延时 
*              指令。
****************************************************************************/
void delay( void ) {
_nop_();_nop_();//_nop_();_nop_();
//_nop_();_nop_();_nop_();_nop_();
}
/****************************************************************************
*    函数原型: void wait_5ms(void);
*    功    能: 提供5ms延时(时钟频率为12MHz)。写入一个数据之后的延时
*****************************************************************************/
#if ASMI2C_wait_5ms
void wait_5ms( void ) {   //现是5ms
   int i ;
	for ( i=0 ; i<1000 ; i++ ) {
		;
	}
}
#endif
#if ASMI2C_wait_1ms
void wait_1ms( void ) {   //现是1ms,只用于连续存入函数
   int i ;
	for ( i=0 ; i<200 ; i++ ) {
		;
	}
}
#endif
/****************************************************************************
*    函数原型: void I_start(void);
*    功    能: 提供I2C总线工作时序中的起始位。                             
****************************************************************************/
void I_start( void ) {
	SCL = HIGH ;
	SDA= HIGH ;
	delay() ;
	SDA = LOW ;
	delay() ;
	SCL = LOW ;
	delay() ;
 }

/****************************************************************************
*    函数原型: void I_stop(void);
*    功    能: 提供I2C总线工作时序中的停止位。
****************************************************************************/
void I_stop( void ) {
	SDA = LOW ;
	SCL = HIGH ;
	delay() ;
	SDA = HIGH ;
	delay() ;
 }

/****************************************************************************
*    函数原型: bit I_clock(void);
*    功    能: 提供I2C总线的时钟信号, 并返回在时钟电平为高期间SDA 信号线上状
*              态。本函数可用于数据发送, 也可用于数据接收。
****************************************************************************/
bit I_clock( void ) {
	bit sample ;
	SCL = HIGH ;
	delay() ;
	sample = SDA ;
	SCL = LOW ;
	delay() ;
	return ( sample ) ;
 }

/****************************************************************************
*    函数原型: bit I_send(uchar Idata);
*    功    能: 向I2C总线发送8位数据, 并请求一个应答信号ACK。如果收到ACK应答
*              则返回1(TRUE), 否则返回0(FALSE)。
****************************************************************************/
bit I_send( uchar Idata ) {
	uchar i ;
	/* 发送8位数据 */
	for ( i=0 ; i<8 ; i++ ) {
		SDA = (bit)( Idata & 0x80 ) ;
		Idata = Idata << 1 ;
		I_clock() ;
	}
	/* 请求应答信号ACK */
	SDA = HIGH ;

	return ( WaitAck());//(~I_clock() );
  }
/****************************************************************************
*    函数原型:  bit WaitAck(void);
*    功    能: 请求一个应答信号ACK。如果收到ACK应答
*              则返回1(TRUE), 否则返回0(FALSE)。
****************************************************************************/
 bit WaitAck(void)
{
   bit HiLo=1; 
unsigned char errtime=255;//因故障接收方无ACK,超时值为255。
	SDA=1;	//SDA -...(wait LOW ).._   timeout error_overtime=0x11
	SCL=1;	//SCL -...           ...\  '
	while(SDA)
	{ 
	  errtime--;
	  if(!errtime)
	    {
		I_stop();
	        	//出错后给全局变量赋值
	    HiLo=0;
		break;
     	}
	}
	SCL=0; 
	return(HiLo);
}

/****************************************************************************
*    函数原型: uchar I_receive(void);
*    功    能: 从I2C总线上接收8位数据信号, 并将接收到8位数据作为一个字节
*              返回, 不回送应答信号ACK。主函数在调用本函数之前应保证SDA信
*              号线处于浮置状态, 即使8051的P1.7脚置1。
****************************************************************************/
uchar I_receive( void ) {
	uchar I_data = 0 ;
	//register
		 uchar i ;
	for ( i=0 ; i<8 ; i++ ) {
		I_data *= 2 ;
		if (I_read_1bit()) I_data++ ;
	}
	return ( I_data ) ;
}

/****************************************************************************
*    函数原型: void I_Ack(void);
*    功    能: 向I2C总线发送一个应答信号ACK, 一般用于连续数据读取时。
*****************************************************************************/
void I_Ack( void ) {
	SDA = LOW ;
	I_clock() ;
	SDA = HIGH ;
}
/****************************************************************************
*    函数原型: I_read_1bit(void);
*    功    能: 向I2C总线读取一位数据并返回。
****************************************************************************/
bit	I_read_1bit(void){
	bit sample ;
	SCL = LOW ;
	delay() ;
	SCL = HIGH ;
	delay() ;
	sample = SDA ;
	SCL = LOW ;
	delay() ;
	return ( sample ) ;
	}
/****************************************************************************
*    函数原型: bit E_address(uchar Address);
*    功    能: 向24C04写入器件地址和一个指定的字节地址。
*****************************************************************************/
#if ASMI2C_E_address
bit E_address( uchar Device_WRITE_id,uchar Address ) {
	I_start() ;
	if ( I_send( Device_WRITE_id ) )
		{

		return ( I_send( Address ) ) ;
		}
	else
		{		
		return ( FALSE );}
}
#endif
/****************************************************************************
*    函数原型: bit	i2c_writedata(uchar Address,uchar i2cdata)
*    功    能: i2cdata写入Address内,ok返回1。
*****************************************************************************/
#if ASMI2C_writedata
bit	i2c_writedata(uchar Device_WRITE_id,uchar Address,uchar i2cdata)
	{
	uchar D_id;
	I_init();                         /* I2C 总线初始化 */
	D_id=Device_WRITE_id;
		if ( E_address(D_id,Address) && I_send(i2cdata) ) {
			I_stop();
			wait_5ms();
			return (TRUE);
			}
		 	else {
			return ( FALSE );
			}
	}	
/*************************************
***************************************
*    函数原型: void I_init(void);
*    功    能: I2C总线初始化。在main()函数中应首先调用本函数, 然后再调用
*              其它函数。
****************************************************************************/
void I_init( void ) {
	SCL = LOW ;
	I_stop() ;
}

#endif
/****************************************************************************
*    函数原型: uchar i2c_READdata(uchar Address)
*    功    能: 正确读取指定地址的数据i2cok=1并返回数据,否则i2cok=0
*****************************************************************************/
#if ASMI2C_READdata
uchar i2c_READdata(uchar Device_READ_id,uchar Address)
{
	uchar icdata,D_id;	/* 从地址Address开始读取数据 */
	D_id=Device_READ_id&0xfe;
	if ( E_address( D_id,Address ) )
	 {
		/* 发送重复启动信号 */
		I_start() ;
		if ( I_send( Device_READ_id ) ) {
			icdata= I_receive();
				I_clock();
				I_stop();
				i2cok=1;
			return (icdata);	
			}
		else {
			I_stop();
				i2cok=0;
			}
	}
	else{
		I_stop();
		i2cok=0;
		}
}

#endif
/****************************************************************************
*    函数原型: bit E_read_block(void);  连续读取数据
*    功    能: 从device中读取uccount个字节的数据并转存于* pucbuf_data
*              单元, 采用序列读操作方式从片内ucaddress地址开始连续读取数据。如果
*             device ucid不接受指定的地址则返回0(FALSE)。
*****************************************************************************/
#if ASMI2C_read_block
bit i2c_read_block( uchar ucid,uchar ucaddress,uchar uccount, char *pucbuf_data) {
	uchar i ;
	uchar  *pucbuf_temp;
	//* 从地址ucaddress开始读取数据 *
	if ( E_address(ucid++, ucaddress ) ) {
		//* 发送重复启动信号 *
		I_start() ;
		if ( I_send( ucid ) ) {
			pucbuf_temp = pucbuf_data;
			for ( i=0 ; i<uccount ; i++ ) {
				*pucbuf_data = ( I_receive() ) ;
				#if debug
				printf("\nR%bx=%bx",i,*pucbuf_data);
				#endif
				pucbuf_data++;
				if ( i < uccount-1 ) I_Ack() ;
				else {
					I_clock() ;
					I_stop() ;
				}
			}
			return ( TRUE ) ;
		}
		else {
			I_stop() ;
			return ( FALSE ) ;
		}
	}
	else
		I_stop() ;
		return ( FALSE ) ;
}
#endif
/****************************************************************************
*    函数原型: bit E_write_block; 连续存入数据
*    功    能: 将* pucbuf_data 单元中的数据写入到ucid 的ucaddress地址uccount个字节。
*              采用字节写操作方式, 每次写入时都需要指定片内地址。如果device
*              不接受指定的地址或某个传送的字节未收到应答信号ACK, 则返回0
*              (FALSE)。
*****************************************************************************/
#if ASMI2C_write_block
bit i2c_write_block(uchar ucid,uchar ucaddress,uchar uccount, uchar * pucbuf_data) {
	uchar i;
	//I_init();                         /* I2C 总线初始化 */
		for ( i=0 ; i<uccount ; i++ ) {
		if (( E_address(ucid,ucaddress+i))&&(I_send( * pucbuf_data )  )){
				#if debug
				printf("\nT%bx=%bx",i,*pucbuf_data);
				#endif
				pucbuf_data++;
				I_stop() ;
				wait_1ms();				
			}					
		else {
			I_stop() ;
			wait_1ms();
			return ( FALSE ) ;	
			}
		}
	return ( TRUE ) ;
		
 }
#endif
/*
//此24c16,连续存入时,在地址0x0f以后的数据无法存入
bit i2c_write_block(uchar ucid,uchar ucaddress,uchar uccount, uchar * pucbuf_data) {
	uchar i ;
	I_init();          				               // I2C 总线初始化 
	if ( E_address(ucid,ucaddress) ){
		for ( i=0 ; i<uccount ; i++ ) {
			if (I_send( * pucbuf_data ) ) {
				#if debug
				printf("\nT%bx=%bx",i,*pucbuf_data);
				#endif
				pucbuf_data++;
				}
			else {
				I_stop() ;
				wait_5ms();
				return ( FALSE ) ;
				}
			}
		}
	else {
		I_stop() ;
		wait_5ms();
		return ( FALSE ) ;	
		}
	I_stop();
	wait_5ms();
	return ( TRUE ) ;
		
 }//*/


#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -