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

📄 i2c.c

📁 基于philips的lpc2148开发源代码
💻 C
字号:
#define		I2C_GLOBALS

#include 	"configLPC.h"

BYTE ack;

#define		 	SCL			(0x04)//(0x01 << 2)
#define 		SDA			(0x08)//(0x01 << 3)



BYTE InitI2C()
{
	PINSEL0 &=  0xFFFFFF0F;				
	IO0DIR |= 	0x0000000C;
	//IO0CLR |= 	0x10000000;
	
	return 1;
}
//****************************************************************************
// DelayInuSec
//****************************************************************************
// Delay a certain number of microseconds.
// 
//
//
void DelayInuSec(DWORD uS)
{
    DWORD passed;
    DWORD i;

    //startTime= *TIM_DEBUGVALUELOW;
    passed=0;
    
    //
    // Get stuck in this loop until 
    //
    while ( passed < uS) 
    {
    	i = 5;
    	while (i--);
        passed++;
    }
}


/*******************************************************************
                     起动总线函数               
函数原型: void  Start_I2c();  
功能:       启动I2C总线,即发送I2C起始条件.
  
********************************************************************/
void Start_I2c()
{
	ack=0;

	IO0SET = (SCL | SDA);//0x0000000C;
	DelayInuSec(5);    //起始条件建立时间大于4.7us,延时
	IO0CLR = SDA;   	 //发送起始信号
	DelayInuSec(5);    // 起始条件锁定时间大于4μs
	IO0CLR = SCL;
	DelayInuSec(5);
}




/*******************************************************************
                      结束总线函数               
函数原型: void  Stop_I2c();  
功能:       结束I2C总线,即发送I2C结束条件.
  
********************************************************************/
void Stop_I2c()
{
	IO0CLR = SDA;			//发送结束条件的数据信号
	DelayInuSec(1);			//发送结束条件的时钟信号
	IO0SET = SCL;			//结束条件建立时间大于4μs
	DelayInuSec(5);
	IO0SET = SDA | SCL;		 //发送I2C总线结束信号
	DelayInuSec(5);
}


/*******************************************************************
                 字节数据传送函数               
函数原型: void  SendByte(BYTE c);
功能:  将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
     此状态位进行操作.(不应答或非应答都使ack=0 假)     
     发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
void  SendByte(BYTE c)
{
	BYTE BitCnt;

	for (BitCnt = 0; BitCnt < 8; BitCnt++)  /*要传送的数据长度为8位*/
	{
		if ((c << BitCnt) & 0x80)
		{
			IO0SET = SDA;				   /*判断发送位*/
		}else  
		{
			IO0CLR = SDA;
		}
		DelayInuSec(5);
		IO0SET = SCL;               /*置时钟线为高,通知被控器开始接收数据位*/
		DelayInuSec(5);               /*保证时钟高电平周期大于4μs*/
		IO0CLR = SCL; 
	}

	//DelayInuSec(2);
	IO0SET = SDA;              /*8位发送完后释放数据线,准备接收应答位*/
	IO0DIR &= ~SDA;				//SDA输入
	DelayInuSec(5);
	IO0SET = SCL;
	DelayInuSec(2);
	if (IO0PIN & SDA)
	{
		ack = 0;
	}else 
	{
		ack=1;        /*判断是否接收到应答信号*/
	}
	DelayInuSec(3);
	IO0DIR |= SDA;
	IO0CLR = SCL;
}






/*******************************************************************
                 字节数据接收函数               
函数原型: BYTE  RcvByte();
功能:  用来接收从器件传来的数据,并判断总线错误(不发应答信号),
     发完后请用应答函数。  
********************************************************************/	
BYTE  RcvByte()
{
	BYTE retc;
	BYTE BitCnt;

	retc = 0; 
	IO0DIR &= ~SDA;				//SDA 输入
	IO0SET = SDA;            	/*置数据线为输入方式*/
	for (BitCnt = 0; BitCnt < 8; BitCnt++)
	{
		DelayInuSec(1);
		IO0CLR = SCL; 			/*置时钟线为低,准备接收数据位*/
		DelayInuSec(5);         /*时钟低电平周期大于4.7μs*/
		IO0SET = SCL;       	/*置时钟线为高使数据线上数据有效*/
		DelayInuSec(2);
		retc = retc << 1;
		if (IO0PIN & SDA)
		{
			retc = retc + 1; /*读数据位,接收的数据位放入retc中 */
		}
		DelayInuSec(2);
	}
	IO0CLR = SCL;    
	DelayInuSec(2);
	IO0DIR |= SDA;
	return (retc);
}




/********************************************************************
                     应答子函数
原型:  void Ack_I2c(BYTE a);
 
功能:主控器进行应答信号,(可以是应答或非应答信号)
********************************************************************/
void Ack_I2c(BYTE a)
{
  
	if (a == 0)
	{
		IO0CLR = SDA;     /*在此发出应答或非应答信号 */
	}else 
	{
		IO0SET = SDA;
	}
	DelayInuSec(3);
	IO0SET = SCL;
	DelayInuSec(5);             /*时钟低电平周期大于4μs*/
	IO0CLR = SCL;                /*清时钟线,钳住I2C总线以便继续接收*/
	DelayInuSec(2);
}






/*******************************************************************
                    向无子地址器件发送字节数据函数               
函数原型: BYTE  ISendByte(BYTE sla,ucahr c);  
功能:     从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla.
           如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
BYTE ISendByte(BYTE sla,BYTE c)
{
	Start_I2c();               /*启动总线*/
	SendByte(sla);            /*发送器件地址*/
	if (ack == 0)
		return(0);
	SendByte(c);               /*发送数据*/
	if (ack == 0)
		return(0);
	Stop_I2c();                 /*结束总线*/ 
	return(1);
}




/*******************************************************************
                    向有子地址器件发送多字节数据函数               
函数原型: BYTE  ISendStr(BYTE sla,BYTE suba,ucahr *s,BYTE no);  
功能:     从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
          地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
           如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
BYTE ISendStr(BYTE sla,BYTE suba,BYTE *s,BYTE no)
{
	BYTE i;
	BYTE bRet = 0;

	OS_ENTER_CRITICAL();

	for (i = 0; i < no; i++)
	{
		Start_I2c();               ///启动总线
		SendByte(sla);            //*发送器件地址
		if (ack == 0)
		{
			bRet = 0;
			goto LEAVE;
		}
		SendByte(0);            //*发送器件地址0
		if (ack == 0)
		{
			bRet = 0;
			goto LEAVE;
		}
		SendByte(suba + i);            //*发送器件子地址
		if (ack == 0)
		{
			bRet = 0;
			goto LEAVE;
		}

		SendByte(*(s + i));               //*发送数据
		if (ack == 0)
		{
			bRet = 0;
			goto LEAVE;
		}
		Stop_I2c();                 //*结束总线
		DelayInuSec(3000);
	}
	bRet = 1;

LEAVE:
	OS_EXIT_CRITICAL();
	return bRet;
}






/*******************************************************************
                    向无子地址器件读字节数据函数               
函数原型: BYTE  IRcvByte(BYTE sla,ucahr *c);  
功能:     从启动总线到发送地址,读数据,结束总线的全过程,从器件地
          址sla,返回值在c.
           如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
BYTE IRcvByte(BYTE sla,BYTE *c)
{
   Start_I2c();                /*启动总线*/
   SendByte(sla+1);           /*发送器件地址*/
     if(ack==0)return(0);
   *c=RcvByte();               /*读取数据*/
     Ack_I2c(1);               /*发送非就答位*/
  Stop_I2c();                  /*结束总线*/ 
  return(1);
}



/*******************************************************************
                    向有子地址器件读取多字节数据函数               
函数原型: BYTE  ISendStr(BYTE sla,BYTE suba,ucahr *s,BYTE no);  
功能:     从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
          地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
           如果返回1表示操作成功,否则操作有误。
注意:    使用前必须已结束总线。
********************************************************************/
BYTE IRcvStr(BYTE sla,BYTE suba,BYTE *s,BYTE no)
{
	BYTE i;
	BYTE bRet = 0;

	OS_ENTER_CRITICAL();

	Start_I2c();               /*启动总线*/
	SendByte(sla);            /*发送器件地址*/
	if (ack == 0)
	{
		bRet = 0;
		goto LEAVE;
	}
	SendByte(0);            //*发送器件地址0
	if (ack == 0)
	{
		bRet = 0;
		goto LEAVE;
	}
	SendByte(suba);            /*发送器件子地址*/
	if (ack == 0)
	{
		bRet = 0;
		goto LEAVE;
	}

	Start_I2c();
	SendByte(sla+1);
	if (ack == 0)
	{
		bRet = 0;
		goto LEAVE;
	}

	for (i = 0; i < no-1; i++)
	{   
		*s = RcvByte();  
		Ack_I2c(0); 
		s++;
	} 
	*s=RcvByte();
	Ack_I2c(1);                 //发送非应位
	Stop_I2c();                    //结束总线

	bRet = 1;

LEAVE:
	OS_EXIT_CRITICAL();
	return bRet;
}


//*******************************
//
// 调用实例
//
//*******************************

BYTE  TestI2C()
{
	BYTE dat[64];
	int i;
	BYTE status;
	BYTE tmp;
	/*
	while(1)
	{
		IO0SET = SDA;
		DelayInuSec(100);
		IO0CLR = SDA;
	}
	*/
	
	OS_ENTER_CRITICAL();
	status = 0x02;
	ISendStr(0xde,0x3f,&status,1);//printf("send CCR status 02. ret=%d\n",ISendStr(0xde,0x3f,&status,1));
	status = 0x06;
	ISendStr(0xde,0x3f,&status,1);//printf("send CCR status 06. ret=%d\n",ISendStr(0xde,0x3f,&status,1));

	//read write eeprom
	for (i = 0; i < 64; i++)
	{
		dat[i] = 64;
	}
	ISendStr(0xae,0,dat,64);//printf("send ret=%d\n",ISendStr(0xae,0,dat,64));
	memset(dat, 0, 64);
	
	IRcvStr(0xae,0,dat,64);//printf("recv ret=%d\n",IRcvStr(0xae,0,dat,64));
	//for(i = 0; i < 64; i++) //printf(" dat%02x=%02x\n",i,dat[i]);


	//read datetime
	IRcvStr(0xde,0x37,&tmp,1);//printf("year2K:%02x\n",tmp);
	IRcvStr(0xde,0x36,&tmp,1);//printf("dayofweek:%02x\n",tmp);
	IRcvStr(0xde,0x35,&tmp,1);//printf("year:%02x\n",tmp);
	IRcvStr(0xde,0x34,&tmp,1);//printf("month:%02x\n",tmp);
	IRcvStr(0xde,0x33,&tmp,1);//printf("day:%02x\n",tmp);

	IRcvStr(0xde,0x32,&tmp,1);//printf("hour:%02x\n",tmp);
	IRcvStr(0xde,0x31,&tmp,1);//printf("minute:%02x\n",tmp);
	IRcvStr(0xde,0x30,&tmp,1);//printf("second:%02x\n",tmp);

	OS_EXIT_CRITICAL();

	return 1;
}


BYTE MyGetLocalTime(LPSYSTEMTIME lpst)
{
	BYTE status;
	BYTE y2k,wk,yy,mm,dd,hh,mi,ss;
	BYTE bRet = 0;

	OS_ENTER_CRITICAL();

	status=0x02;ISendStr(0xde,0x3f,&status,1);
	status=0x06;ISendStr(0xde,0x3f,&status,1);

	if(IRcvStr(0xde,0x37,&y2k,1) &&
		IRcvStr(0xde,0x36,&wk,1) &&
		IRcvStr(0xde,0x35,&yy,1) &&
		IRcvStr(0xde,0x34,&mm,1) &&
		IRcvStr(0xde,0x33,&dd,1) &&
		IRcvStr(0xde,0x32,&hh,1) &&
		IRcvStr(0xde,0x31,&mi,1) &&
		IRcvStr(0xde,0x30,&ss,1))
	{
		lpst->wYear=(((y2k&0xf0)>>4)*1000 + (y2k&0x0f)*100 + ((yy&0xf0)>>4)*10 + (yy&0x0f) );
		lpst->wMonth=(((mm&0xf0)>>4)*10 + (mm&0x0f) );
		lpst->wDayOfWeek=wk;
		lpst->wDay=(((dd&0xf0)>>4)*10 + (dd&0x0f) );
		lpst->wHour=(((hh&0x70)>>4)*10 + (hh&0x0f) );
		lpst->wMinute=(((mi&0xf0)>>4)*10 + (mi&0x0f) );
		lpst->wSecond=(((ss&0xf0)>>4)*10 + (ss&0x0f) );
		lpst->wMilliseconds=0;
		bRet = 1;
	}
	else 
		bRet = 0;
	OS_EXIT_CRITICAL();
	return bRet;
}

BYTE MySetLocalTime(LPSYSTEMTIME lpst)
{
	BYTE status;
	BYTE y2k,wk,yy,mm,dd,hh,mi,ss;
	BYTE bRet = 0;

	OS_ENTER_CRITICAL();

	status=0x02;ISendStr(0xde,0x3f,&status,1);
	status=0x06;ISendStr(0xde,0x3f,&status,1);


	status=(BYTE)(lpst->wYear/100);
	y2k=( ((status/10)<<4) | ((status%10)&0x0f) );

	status=(BYTE)(lpst->wYear%100);
	yy=( ((status/10)<<4) | ((status%10)&0x0f) );

	wk=(BYTE)(lpst->wDayOfWeek);

	status=(BYTE)(lpst->wMonth);
	mm=( ((status/10)<<4) | ((status%10)&0x0f) );

	status=(BYTE)(lpst->wDay);
	dd=( ((status/10)<<4) | ((status%10)&0x0f) );

	status=(BYTE)(lpst->wHour);
	hh=( ((status/10)<<4) | ((status%10)&0x0f) );
	hh=(hh|0x80);

	status=(BYTE)(lpst->wMinute);
	mi=( ((status/10)<<4) | ((status%10)&0x0f) );

	status=(BYTE)(lpst->wSecond);
	ss=( ((status/10)<<4) | ((status%10)&0x0f) );

	if(ISendStr(0xde,0x37,&y2k,1) &&
		ISendStr(0xde,0x36,&wk,1) &&
		ISendStr(0xde,0x35,&yy,1) &&
		ISendStr(0xde,0x34,&mm,1) &&
		ISendStr(0xde,0x33,&dd,1) &&
		ISendStr(0xde,0x32,&hh,1) &&
		ISendStr(0xde,0x31,&mi,1) &&
		ISendStr(0xde,0x30,&ss,1)) 
		bRet = 1;
	else 
		bRet = 0;

	OS_EXIT_CRITICAL();
	return bRet;
}

⌨️ 快捷键说明

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