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

📄 i2c.c

📁 基于USB的I2C通信代码
💻 C
字号:
													  
//-----------------------------------------------------------------------------
//
//   Code modified from eeprom.c by Cypress Semiconductor
//   Modified by Nick Merryman, GRASPR team, 2005
//
//   Copyright (c) 2002 Cypress Semiconductor
//
//
//-----------------------------------------------------------------------------

#include <ezusb.h>
#include <ezregs.h>

#include "i2c.h"

// user shouldnt call these
void WaitForI2CWrite();
bit I2CWaitForAck();
bit I2CWaitForDone();
void I2CWaitForStop();


						// 
#define ADCAddr			0x20

BYTE xdata I2CWriteBuf[5];
BYTE xdata I2CReadBuf[5];

					   
void I2CWaitForStop()
{
   // Data should not be written to I2CS or I2DAT until the STOP bit returns low.
   while (I2CS & bmSTOP)
      ;
}

// Return 0 for ok, 1 for error
bit I2CWaitForDone()
{
   BYTE i;

   while (!((i = I2CS) & bmDONE))  // Poll the done bit
      ;
   if (i & bmBERR)
      return 1;
   else
      return 0;
}

// Return 0 for ok, 1 for error
// Same as wait for done, but checks for ACK as well
bit I2CWaitForAck()
{
   BYTE i;

   while (!((i = I2CS) & bmDONE))  // Poll the done bit
      ;
   if (i & bmBERR)
      return 1;
   else if (!(i & bmACK))
      return 1;
   else
      return 0;
}

//I2CREAD or I2CWRITE
void I2CStartAndAddr(BYTE op)
{
      I2CS = bmSTART;
      I2DAT = (ADCAddr << 1) | op;
}


// 0x2e in assembly, less than 0x20 with compiler optimization!!
void WaitForI2CWrite()
{
   I2CWaitForStop();
waitForBusy:
	I2CStartAndAddr(I2CWRITE);

   I2CWaitForDone();
   I2CS |= bmSTOP;	//	; Set the STOP bit
   I2CWaitForStop();

   if (!(I2CS & bmACK))  // If no ACK, try again.
      goto waitForBusy;
}


// Write up to one page of data to the ADC.
// Returns 0 on success, 1 on failure
// Normally called within a while() loop so that errors are retried:
// while (ADCWriteBlock(....))
//    ;
bit I2CWrite(BYTE addr, BYTE xdata * ptr, BYTE len)
{
//	BYTE retval;
   // Make sure the i2c interface is idle
   I2CWaitForStop();
   
   // write the START bit and i2c device address
   I2CStartAndAddr(I2CWRITE);
	
   if(I2CWaitForAck())
   {
      I2CS |= bmSTOP;	//	; Set the STOP bit
      I2CWaitForStop();
      return(1);
   }

   // write the ADC offset
   I2DAT = addr;

   // If the ADC doesn't respond, set the STOP bit to idle the bus, then return error
   if(I2CWaitForAck())
   {
      I2CS |= bmSTOP;	//	; Set the STOP bit
      I2CWaitForStop();
      return(1);
   }

   // Write the data block
   for(; len != 0; len--)
   {
      I2DAT = *ptr++;
      if(I2CWaitForAck())
      {
	      I2CS |= bmSTOP;	//	; Set the STOP bit
	      I2CWaitForStop();
	      return(1);
      }
   }	
   I2CS |= bmSTOP;
   WaitForI2CWrite();
   return 0;
}


// Returns 0 on success, 1 on failure
BYTE I2CRead(BYTE addr, BYTE xdata *buf, BYTE length)
{
   BYTE i;

   // Make sure the i2c interface is idle
   I2CWaitForStop();
   
   // write the START bit and i2c device address
   I2CStartAndAddr(I2CWRITE);

   if(I2CWaitForAck())
      {
      I2CS |= bmSTOP;	//	; Set the STOP bit
      I2CWaitForStop();
      return(1);
      }

   I2DAT = addr;				  // write which register we're going to read from

   // If the ADC doesn't respond, set the STOP bit to idle the bus, then return error
   if(I2CWaitForAck())
      {
      I2CS |= bmSTOP;	//	; Set the STOP bit
      I2CWaitForStop();
      return(1);
      }
	
	I2CS |= bmSTOP;
	I2CWaitForStop();


	//start the read operation here
   I2CStartAndAddr(I2CREAD);

	if(I2CWaitForAck())
	{
		I2CS |= bmSTOP;	//	; Set the STOP bit
		I2CWaitForStop();
		return(1);
	}

	// why are we doing this? -- because the manual says so
   // read dummy byte
    i = I2DAT;
    if(I2CWaitForDone())
	{
		I2CS |= bmSTOP;	//	; Set the STOP bit
		I2CWaitForStop();
		return(1);
	}
	

   for (i=0; i < (length - 1); i++)
   {
		*(buf+i) = I2DAT;
		if(I2CWaitForDone())
		{
			I2CS |= bmSTOP;	//	; Set the STOP bit
			I2CWaitForStop();
			return(1);
		}

		//this is apparently taken care of for us -- tricksy microcontroller
		/*
		I2CS |= bmACK; //send ack from master to device
		if(I2CWaitForDone())
			return(1);
		*/
   }
   
   I2CS = bmLASTRD;
   if(I2CWaitForDone())
      return(1);

   *(buf+i) = I2DAT;
   if(I2CWaitForDone())
      return(1);

   I2CS = bmSTOP;

   i = I2DAT;
   return(0);
}

⌨️ 快捷键说明

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