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

📄 i2c.c

📁 基于MDK的LPC1100处理器开发应用例程
💻 C
字号:
/******************** (C) COPYRIGHT 2010 Embest Info&Tech Co.,LTD. ************
* 文件名: i2c.c
* 作者  : Wuhan R&D Center, Embest
* 日期  : 01/18/2010
* 描述  : NXP LPC11xx 系列处理器 I2C API 文件.
*******************************************************************************
*******************************************************************************
* 历史:
* 01/18/2010		 : V1.0		   初始版本
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "LPC11xx.h"			/* LPC11xx 外设寄存器 */
#include "type.h"
#include "i2c.h"

volatile uint32_t I2CMasterState = I2C_IDLE;
volatile uint32_t I2CSlaveState = I2C_IDLE;

volatile uint32_t I2CMode;

volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
volatile uint32_t I2CCount = 0;
volatile uint32_t I2CReadLength;
volatile uint32_t I2CWriteLength;

volatile uint32_t RdIndex = 0;
volatile uint32_t WrIndex = 0;

/* 
根据器件的不同,I2C 通信协议也会不同,在一下例子中, 协议还采用重复开始读取数据
或写入到设备:
从主机读:顺序为: STA,Addr(W),offset,RE-STA,Addr(r),data...STO 
从主机写:顺序为: STA,Addr(W),offset,RE-STA,Addr(w),data...STO
也既是,在状态 8,地址始终允许写。在状态 10,地址是否允许读写依赖于 I2C 命令。
*/   

/**
  * 函数名:	I2C_IRQHandler
  * 描述:   I2C 中断处理程序,只在主模式。
  * 参数:	无
  * 返回值:	无
  */
void I2C_IRQHandler(void) 
{
  uint8_t StatValue;

  /* 该处理程序只在主机读和写时 */
  StatValue = LPC_I2C->STAT;
  switch ( StatValue )
  {
  /* 起始条件发出。 */
	case 0x08:			
	WrIndex = 0;
	LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
	LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
	I2CMasterState = I2C_STARTED;
	break;
	
	/* 一个重复开始发出。 */
	case 0x10:			
	RdIndex = 0;
	/* 发送 SLA 在 R 位设置 */
	LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
	LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
	I2CMasterState = I2C_RESTARTED;
	break;
	
	/* 忽略, 是 ACK */
	case 0x18:			
	if ( I2CMasterState == I2C_STARTED )
	{
	  LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
	  I2CMasterState = DATA_ACK;
	}
	LPC_I2C->CONCLR = I2CONCLR_SIC;
	break;
	
	/* 数据类型传输,不管是 ACK 或者 NACK */
	case 0x28:	
	case 0x30:
	if ( WrIndex < I2CWriteLength )
	{   
	  /* 这将是最后一个 */
	  LPC_I2C->DAT = I2CMasterBuffer[WrIndex++]; 
	  I2CMasterState = DATA_ACK;
	}
	else
	{
	  if ( I2CReadLength != 0 )
	  {
	  /* 设置重复开始标志 */
		LPC_I2C->CONSET = I2CONSET_STA;	
		I2CMasterState = I2C_REPEATED_START;
	  }
	  else
	  {
		I2CMasterState = DATA_NACK;
		/* 设置结束标志 */
		LPC_I2C->CONSET = I2CONSET_STO;      
	  }
	}
	LPC_I2C->CONCLR = I2CONCLR_SIC;
	break;
	
	/* 主机接收, SLA_R 已经发送 */
	case 0x40:	
	/* 假定数据后的 ACK 已经接收到 */
	LPC_I2C->CONSET = I2CONSET_AA;	
	LPC_I2C->CONCLR = I2CONCLR_SIC;
	break;
	
	/* 数据类型已经接收到,无论之后是否有 ACK 或 NACK */
	case 0x50:	
	I2CSlaveBuffer[RdIndex++] = LPC_I2C->DAT;
	if ( RdIndex < I2CReadLength )
	{   
	  I2CMasterState = DATA_ACK;
	}
	else
	{
	  I2CMasterState = DATA_NACK;

	}
	/* 假定数据后的 ACK 已经接收到 */
	LPC_I2C->CONSET = I2CONSET_AA;	
	LPC_I2C->CONCLR = I2CONCLR_SIC;
	break;
	
	case 0x58:
	I2CSlaveBuffer[RdIndex++] = LPC_I2C->DAT;
	I2CMasterState = DATA_NACK;
		/* 设置结束标志 */ 
	LPC_I2C->CONSET = I2CONSET_STO;
		/* 清除 SI 标志 */
	LPC_I2C->CONCLR = I2CONCLR_SIC;
	break;
  /* 忽略,是一个 NACK */
	case 0x20:		
	case 0x48:
	LPC_I2C->CONCLR = I2CONCLR_SIC;
	I2CMasterState = DATA_NACK;
	break;
	
	case 0x38:		/* 仲裁丢失,在该例子中我们不考虑
					多主情况 */
	default:
	LPC_I2C->CONCLR = I2CONCLR_SIC;	
	break;
  }
  return;
}

/**
  * 函数名:	I2CStart
  * 描述:	创建 I2C 开始条件,如果 I2C 一直没有开始
  *         将会设置一个超时值,并超时。这是一个致命错误
  * 参数:	无
  * 返回值:	真或假,如果超时返回假
  */
uint32_t I2CStart( void )
{
  uint32_t timeout = 0;
  uint32_t retVal = FALSE;
 
  /*--- 发出一个开始条件 ---*/
  
  /* 设置开始标志 */
  LPC_I2C->CONSET = I2CONSET_STA;	
    
  /*--- 等待直到 START 发送完成 ---*/
  while( 1 )
  {
	if ( I2CMasterState == I2C_STARTED )
	{
	  retVal = TRUE;
	  break;	
	}
	if ( timeout >= MAX_TIMEOUT )
	{
	  retVal = FALSE;
	  break;
	}
	timeout++;
  }
  return( retVal );
}

/**
  * 函数名:	I2CStop
  * 描述:	设置 I2C 结束条件, 如果没有正常退出
  *			这是一个致命总线错误。
  * 参数:	无
  * 返回值:真或永远不返回
  */
uint32_t I2CStop( void )
{
   /* 设置停止标志 */ 
  LPC_I2C->CONSET = I2CONSET_STO;    
   /* 清除 SI 标志 */  
  LPC_I2C->CONCLR = I2CONCLR_SIC; 
            
  /*--- Wait for STOP detected ---*/
  while( LPC_I2C->CONSET & I2CONSET_STO );
  return TRUE;
}

/**
  * 函数名:	I2CInit
  * 描述:	初始化 I2C 控制器
  * 参数:	I2c 模式是主模式或从模式之一
  * 返回值:	真或假,如果 I2C
  *			中断处理程序没有正确安装返回假
  */
uint32_t I2CInit( uint32_t I2cMode ) 
{
  /*  bit0 为 I2C 控制位, 不同于
  UM.随着 SSP 复位重新测试。 SSP 和 I2C
  复位重叠, 目前已知的 bug,SSP 和 
  I2C 都使用第 0 位使能复位。一旦修复问题,
  更改 "#if 1". */
#if 1
  LPC_SYSCON->PRESETCTRL |= (0x1<<1);
#else
  LPC_SYSCON->PRESETCTRL |= (0x1<<0);
#endif
  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5);
  LPC_IOCON->PIO0_4 &= ~0x3F;	    /*  I2C I/O 配置 */
  LPC_IOCON->PIO0_4 |= 0x01;		/* I2C SCL */
  LPC_IOCON->PIO0_5 &= ~0x3F;	
  LPC_IOCON->PIO0_5 |= 0x01;		/* I2C SDA */

  /*--- 清除所有标志 ---*/
  LPC_I2C->CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;    

  /*--- 重置寄存器 ---*/
#if FAST_MODE_PLUS
  LPC_IOCON->PIO0_4 |= (0x1<<9);
  LPC_IOCON->PIO0_5 |= (0x1<<9);
  LPC_I2C->SCLL   = I2SCLL_HS_SCLL;
  LPC_I2C->SCLH   = I2SCLH_HS_SCLH;
#else
  LPC_I2C->SCLL   = I2SCLL_SCLL;
  LPC_I2C->SCLH   = I2SCLH_SCLH;
#endif

  if ( I2cMode == I2CSLAVE )
  {
	LPC_I2C->ADR0 = PCF8594_ADDR;
  }    

  /* Enable the I2C Interrupt */
  NVIC_EnableIRQ(I2C_IRQn);

  LPC_I2C->CONSET = I2CONSET_I2EN;
  return( TRUE );
}

/**
  * 函数名:	I2CEngine
  * 描述:	常规完成 I2C 通信是从开始到结束。所有的  
  *			阶段步骤都在中断处理程序中处理。
  *			在常规调用之前,必须先填充读长度、写长度、
  *         I2C 主缓冲区和 I2C 命令区域。
  *			查阅 i2cmst.c 更多信息。 
  * 参数:	无
  * 返回值:	真或假,只当开始条件没有被产生返回假 
  */
uint32_t I2CEngine( void ) 
{
  I2CMasterState = I2C_IDLE;
  RdIndex = 0;
  WrIndex = 0;
  if ( I2CStart() != TRUE )
  {
	I2CStop();
	return ( FALSE );
  }

  while ( 1 )
  {
	if ( I2CMasterState == DATA_NACK )
	{
	  I2CStop();
	  break;
	}
  }    
  return ( TRUE );      
}

/**
  * @}
  */ 

/**
  * @}
  */ 

/************* (C) COPYRIGHT 2010 Wuhan R&D Center, Embest *****文件结束*******/

⌨️ 快捷键说明

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