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

📄 drivereeprom.c

📁 飞利浦公司lpc213x硬件中断方式I2C程序
💻 C
字号:
/*
* Copyright (c) 2006,深圳国人通信网优中心软件开发部
* All rights reserved.
* 
* 文件名:DriverEeprom.c
*
* 版本号:V1.0
*
* 创建日期:2006年3月20日
*
* 摘  要:ARM自带的I2C0驱动程序
*
* 作  者:段斌
* 
*
* 修改人:
*
* 修改日期:
*
* 修改摘要:
*/
#define EEPROM_GLOBE
#include "..\include\DriverEeprom.h"

#if(SOURCE_VER  ==  TEST_SOURCE_IIC)    //??????????????????????????????????????????????????????
#define BEEP  1 << 7										//P0.7控制BEEP,低电平蜂鸣
#endif
/**********************************************************
** 函数名称: 
** 功能说明:  eprom初始化
** 输入参数:  u32_Fi2c       设置I2C的时钟值,单位HZ
** 输出参数:  无
** 返 回 值:  无
** 引用函数: 
** 创 建 人: 段斌       
** 创建时间:2006-03-17
***********************************************************/
void I2cInit(UINT32 u32_Fi2c)
{
 #if(SOURCE_VER  ==  TEST_SOURCE_IIC)   //??????????????????????????????????????????????????????    
  UINT32 i;
  UCHAR8 data_buf[32];
 #endif 
 
 	if (u32_Fi2c > 400000)               		//I2C的最大速率400K
		u32_Fi2c = 400000;
		
	PINSEL0 = (PINSEL0 & (~0xF0)) | 0x50; 	// 不影响其它管脚连接,pinsel05:4对应SCL值01,pinsel07:6对应SDA值01
	I2SCLH = (Fpclk/u32_Fi2c + 1) / 2;			// 设定I2C时钟 	
	I2SCLL = (Fpclk/u32_Fi2c)/2;
	I2CONCLR = 0x2C;												//清除AA,SI,STA位
	I2CONSET = 0x40;												// 使能主I2C,即设置I2EN位 	
	
	// 设置I2C中断允许
	VICIntSelect = 0x00000000;				 			// 设置所有通道为IRQ中断 	
	VICVectCntl1 = (0x20 | 0x09);			 			// I2C通道分配到IRQ slot1,次高优先级,0x09为I2C0对应中断编号 
	VICVectAddr1 = (int32)IRQ_I2C0;		 			//设置I2C中断向量 	
	VICIntEnable = VICIntEnable | (1 << 9);	//使能I2C0中断,0x09为I2C0对应中断编号 		 


	//IRQEnable();													//打开中断	
#if(SOURCE_VER  ==  TEST_SOURCE_IIC)   //??????????????????????????????????????????????????????  			
	IO0DIR  = IO0DIR | BEEP;								// 设置蜂鸣器控制口输出	
	IO0SET  = IO0SET | BEEP;								//先关闭蜂鸣器		
	//I2cInit(100000);											//I2C初始化,100K	
	
	for (i=0; i<10; i++)
	{
		data_buf[i] = i + '0';								//数据0~9,转换成ASCII码	
	}
	I2C_WriteNByte(AT24C16, X_ADD_8_SUBA, 0x00, data_buf, 10);//往起始地址0x00开始写入10个数据

	DelayNS(10);
	

	for (i=0; i<10; i++)										//清零数据缓冲区,防止出错	
	{	
		data_buf[i] = 0;
	}

	I2C_ReadNByte(AT24C16, X_ADD_8_SUBA, 0x00, data_buf, 10); 	//读回刚才写入的数据
	
	for (i=0; i<10; i++)									//判断读回的数据是否正确
	{
		if (data_buf[i] != (i + '0'))
		{
			while (1)
			{						
				IO0SET = BEEP;                //出错,连续蜂鸣
				DelayNS(20);
				IO0CLR = BEEP;
				DelayNS(20);
			}
		}
	}
																		 //正确,蜂鸣一次 
	IO0CLR = BEEP;							
	DelayNS(50);
	IO0SET = BEEP;
	
	while (1);	
#endif	 
}

/*
**********************************************************************************************************
** 函数名称:ISendByte()
** 函数功能:向无子地址器件发送1字节数据。
** 入口参数:sla		器件地址
**           dat		要发送的数据
** 出口参数:返回值为0时表示出错,为1时表示操作正确。
** 说明:	使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
*********************************************************************************************************
*/
UCHAR8  ISendByte(UCHAR8 sla, UCHAR8 dat)
{  
   I2C_sla     = sla;			// 写操作的器件地址
   I2C_buf     = &dat;		// 待发送的数据
   I2C_num     = 1;				// 发送1字节数据
   I2C_suba_en = 0;		 		// 无子地址
   I2C_end     = 0;
   
   I2CONCLR = 0x2C;
   I2CONSET = 0x60;       // 设置为主机,并启动总线
   
   while(0==I2C_end);
   if(1==I2C_end) 
   {
     return(1);
   }  
   else 
   {
     return(0);
   }  
}

/*
*********************************************************************************************************
** 函数名称:IRcvByte()
** 函数功能:向无子地址器件读取1字节数据。
** 入口参数:sla		器件地址
**           dat		接收数据的变量指针
** 出口参数:返回值为0时表示操作出错,为1时表示操作正确。
** 说明:使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
*********************************************************************************************************
*/
UCHAR8  IRcvByte(UCHAR8 sla, UCHAR8 *dat)
{  
   I2C_sla     = sla+1;		// 读操作的器件地址
   I2C_buf     = dat;
   I2C_num     = 1;
   I2C_suba_en = 0;				// 无子地址
   I2C_end     = 0;
   
   I2CONCLR = 0x2C;
   I2CONSET = 0x60;       // 设置为主机,并启动总线
   
   while(0==I2C_end);
   if(1==I2C_end) return(1);
     else return(0);
}


/*
*********************************************************************************************************
** 函数名称 :I2C_ReadNByte()
** 函数功能 :从有子地址器件任意地址开始读取N字节数据
** 入口参数 :	sla			器件从地址
**				suba_type	子地址结构	1-单字节地址	3-8+X结构	2-双字节地址
**				suba		器件子地址
**				s			数据接收缓冲区指针
**				num			读取的个数
** 出口参数 :	TRUE		操作成功
**				FALSE	和I2C_ADDR_ERRO	操作失败
** 创 建 人: 段斌       
** 创建时间:2006-03-20
*********************************************************************************************************
*/
UCHAR8 I2C_ReadNByte (UCHAR8 sla, UINT32 suba_type, UINT32 suba, UCHAR8 *s, UINT32 num)
{
	if (num > 0)											/* 判断num个数的合法性 */
	{	
		if (suba_type == 1)
		{																/* 子地址为单字节 */
			I2C_sla     	= sla + 1;			/* 读器件的从地址,R=1 	*/
			I2C_suba    	= suba;					/* 器件子地址 			*/
			I2C_suba_num	= 1;						/* 器件子地址为1字节 	*/
		}
		if (suba_type == 2)
		{																/* 子地址为2字节 */
			I2C_sla     	= sla + 1;			/* 读器件的从地址,R=1 	*/
			I2C_suba   	 	= suba;					/* 器件子地址 			*/
			I2C_suba_num	= 2;						/* 器件子地址为2字节 	*/
		}
		if (suba_type == 3)
		{																/* 子地址结构为8+X*/
			I2C_sla			= sla + ((suba >> 7 )& 0x0e) + 1;	/* 读器件的从地址,R=1	*/
			I2C_suba		= suba & 0x0ff;		/* 器件子地址	 		*/
			I2C_suba_num	= 1;						/* 器件子地址为8+x	 	*/
		}
		I2C_buf     = s;								/* 数据接收缓冲区指针 	*/
		I2C_num     = num;							/* 要读取的个数 	*/
		I2C_suba_en = 1;								/* 有子地址读 		*/
		I2C_end     = 0;

  	if((I2C_num == 0) || ((I2C_suba + I2C_num)>0x800))//超过0x800,即2K范围
  	{
    	return(I2C_ADDR_ERRO);
  	}				
																		/* 清除STA,SI,AA标志位 */
		I2CONCLR = 	(1 << 2)|						/* AA 		*/
					(1 << 3)|									/* SI 		*/
					(1 << 5);									/* STA 		*/
		
																		/* 置位STA,启动I2C总线 */
		I2CONSET = 	(1 << 5)|						/* STA 		*/
					(1 << 6);									/* I2CEN 	*/
		
																		/* 等待I2C操作完成 */
	////	while (I2C_end == 0)
	////	{	}
		if (I2C_end == 1)
			return (TRUE);
		else
			return (FALSE);			
	}
	return (FALSE);
}

/*
*********************************************************************************************************
** 函数名称 :I2C_WriteNByte()
** 函数功能 :向有子地址器件写入N字节数据
** 入口参数 :	sla			器件从地址
**				suba_type	子地址结构	1-单字节地址	3-8+X结构	2-双字节地址
**			  	suba		器件内部物理地址
**			  	*s			将要写入的数据的指针
**			  	num			将要写入的数据的个数
** 出口参数 :	TRUE		操作成功
**			  	FALSE	和I2C_ADDR_ERRO	操作失败
** 创 建 人: 段斌       
** 创建时间:2006-03-20
*********************************************************************************************************
*/
UCHAR8 I2C_WriteNByte(UCHAR8 sla, UCHAR8 suba_type, UINT32 suba, UCHAR8 *s, UINT32 num)
{

	if (num > 0)										/* 如果读取的个数为0,则返回错误 */
	{		
		if (suba_type == 1)
		{															/* 子地址为单字节 */
			I2C_sla     	= sla;				/* 读器件的从地址	 	*/
			I2C_suba    	= suba;				/* 器件子地址 			*/
			I2C_suba_num	= 1;					/* 器件子地址为1字节 	*/
		}
		if (suba_type == 2)
		{															/* 子地址为2字节 */
			I2C_sla     	= sla;				/* 读器件的从地址 		*/
			I2C_suba   	 	= suba;				/* 器件子地址 			*/
			I2C_suba_num	= 2;					/* 器件子地址为2字节 	*/
		}
		if (suba_type == 3)
		{															/* 子地址结构为8+X */
			I2C_sla			= sla + ((suba >> 7 )& 0x0e);		/* 读器件的从地址		*/
			I2C_suba		= suba & 0x0ff;	/* 器件子地址			*/
			I2C_suba_num	= 1;					/* 器件子地址为8+X	 	*/
		}

		I2C_buf     = s;							/* 数据 				*/
		I2C_num     = num;						/* 数据个数 			*/
		I2C_suba_en = 2;							/* 有子地址,写操作*/
		I2C_end     = 0;
  	
  	if((I2C_num == 0) || ((I2C_suba + I2C_num)>0x800))//超过0x800,即2K范围
  	{
    	return(I2C_ADDR_ERRO);
  	}			
																	/* 清除STA,SI,AA标志位 */
		I2CONCLR = 	(1 << 2)|					/* AA 	*/
					(1 << 3)|								/* SI 	*/
					(1 << 5);								/* STA 	*/
		
																	/* 置位STA,启动I2C总线 */
		I2CONSET = 	(1 << 5)|					/* STA 	*/
					(1 << 6);								/* I2CEN*/
		
																	/* 等待I2C操作完成 */
	///	/while (I2C_end == 0) 
	////	{	}
		if (I2C_end == 1)
			return (TRUE);
		else
			return (FALSE);	
	}
	return (FALSE);
}

/*
*********************************************************************************************************
** 函数名称 :__irq IRQ_I2C()
** 函数名次 :硬件I2C中断服务程序,按照全局变量的设置进行操作及设置软件标志  
** 入口参数 :无
** 出口参数 :无
** 说明     :注意处理子地址为2字节的情况。
** 创 建 人: 段斌       
** 创建时间:2006-03-20 
*********************************************************************************************************
*/
void __irq IRQ_I2C0(void)
{																			
	
	switch (I2STAT & 0xF8)              /* 读取I2C状态寄存器I2DAT */
	{	
		case 0x08:												/* 已发送起始条件,主发送和主接收都有 */
		{																	/* 装入SLA+W或者SLA+R */
		 	if(I2C_suba_en == 1)						/* SLA+R,指定子地址读 */
		 	{	
		 		I2DAT = I2C_sla & 0xFE; 			/* 先写入地址 */
		 	}
      else														/* SLA+W */
      {  	
        I2DAT = I2C_sla;      				/* 否则直接发送从机地址 */
      }
            													/* 清零SI位 */
      I2CONCLR =	(1 << 3)|						/* SI */
            			(1 << 5);						/* STA */
    }
    break;
            
    case 0x10:												/*已发送重复起始条件,主发送和主接收都有 */
    {   															/* 装入SLA+W或者SLA+R */
      I2DAT = I2C_sla;								/* 重起总线后,重发从地址*/
      I2CONCLR = 0x28;								/* 清零SI,STA */
		}
    break;
		
		case 0x18:
    case 0x28:												/* 已发送I2DAT中的数据,已接收ACK */
    {
      if (I2C_suba_en == 0)
      {
	       if (I2C_num > 0)
	       {	I2DAT = *I2C_buf++;
	       		I2CONCLR = 0x28;					/* 清零SI,STA */
	       			I2C_num--;
	       }
	       else													/* 没有数据发送了 */
	       {														/* 停止总线 */
	       		  	I2CONSET = (1 << 4);	/* STO 	*/
	       			I2CONCLR = 0x28;				/* 清零SI,STA */
	       		  	I2C_end = 1;					/* 总线已经停止 */
	       }
       }
       		
       if(I2C_suba_en == 1)						/* 若是指定地址读,则重新启动总线 */
       { 
          if (I2C_suba_num == 2)
          {	
            	I2DAT = ((I2C_suba >> 8) & 0xff);
	       			I2CONCLR = 0x28;				/* 清零SI,STA */
	       			I2C_suba_num--;
	       			break;	
	       	} 
	       		
	       	if(I2C_suba_num == 1)
	       	{	I2DAT = (I2C_suba & 0xff);
	       			I2CONCLR = 0x28;					/* 清零SI,STA */
	       			I2C_suba_num--;
	       			break;	
	       	}
	       		
          if (I2C_suba_num == 0)
          {	I2CONSET = 0x20;
               		I2CONCLR = 0x08;
               		I2C_suba_en = 0;     /* 子地址己处理 */
               		break;
          }
        }
            
        if (I2C_suba_en == 2)					/* 指定子地址写,子地址尚未指定,则发送子地址 */
        {
       		if (I2C_suba_num > 0)
          {	
          	if (I2C_suba_num == 2)
            {	I2DAT = ((I2C_suba >> 8) & 0xff);
            			I2CONCLR = 0x28;
            			I2C_suba_num--;
            			break;
            }
            if (I2C_suba_num == 1)
            {	
            	I2DAT = (I2C_suba & 0xff);
              I2CONCLR = 0x28;
              I2C_suba_num--;
              I2C_suba_en  = 0;
              break;
            }
          }
        }
      }
      break;
       		  
      case 0x40:										/* 已发送SLA+R,已接收ACK */
      {
       	if (I2C_num <= 1)						/* 如果是最后一个字节 */			
       	{	
       		I2CONCLR = 1 << 2;      	/* 下次发送非应答信号 */
       	}
       	else
       	{ 	
       		I2CONSET = 1 << 2;				/* 下次发送应答信号 */
       	}
       	I2CONCLR = 0x28;						/* 清零SI,STA */
      }		
      break;

      case 0x20:										/* 已发送SLA+W,已接收非应答              */
      case 0x30:										/* 已发送I2DAT中的数据,已接收非应答     */
      case 0x38:										/* 在SLA+R/W或数据字节中丢失仲裁         */
   		case 0x48:										/* 已发送SLA+R,已接收非应答              */
      {   	
        I2CONCLR = 0x28;
        I2C_end = 0xFF;
     	}	
     	break;   				
	
		case 0x50:											/* 已接收数据字节,已返回ACK */
		{	
			*I2C_buf++ = I2DAT;
			I2C_num--;
			if (I2C_num == 1)							/* 接收最后一个字节 */
			{  	I2CONCLR = 0x2C;					/* STA,SI,AA = 0 	*/
			}
			else
			{  	I2CONSET = 0x04;					/* AA=1 */
			  	I2CONCLR = 0x28;
			}
		}	
		break;
		
		case 0x58:											/* 已接收数据字节,已返回非应答 */
		{	
			*I2C_buf++ = I2DAT;     			/* 读取最后一字节数据 */
      I2CONSET = 0x10;        			/* 结束总线 */
      I2CONCLR = 0x28;
      I2C_end = 1; 
    }        
    break;
                
    default:
      break;
	}
  VICVectAddr = 0x00;              /* 中断处理结束 */
}


⌨️ 快捷键说明

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