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

📄 i2cint.c

📁 使用硬件I2C对E2PROM进行操作
💻 C
字号:
/****************************************************************************
* File:I2CINT.C
* 功能:使用硬件I2C对E2PROM进行操作,利用中断方式操作。
* 说明:将跳线器JP8_LED1、JP12短接。
****************************************************************************/
#include  "config.h" 

#define   CSI24WC02 0xA0            /* 定义器件地址 */

#define	  LED1CON	0x00000400		/* P0.10引脚控制LED1,低电平点亮 */


/* 以下为I2C操作时所需要的变量,在调用I2C子程序前要设置好这些变量 */
volatile  uint8  I2C_sla;           // 从机地址
volatile  uint8  I2C_suba;          // 子地址
volatile  uint8  *I2C_buf;          // 数据缓冲区指针 (读操作时会被更改)
volatile  uint8  I2C_num;           // 操作数据个数 (会被更改)
volatile  uint8  I2C_end;           // 操作结束标志,为1时表示操作结束,为0xFF时表示操作失败 (会被设置)
volatile  uint8  I2C_suba_en;       // 子地址使能控制,读操作时请设置为1,写操作时请设置为2 (会被更改)



/****************************************************************************
* 名称:IRQ_I2C()
* 功能:I2C中断,通过判断I2C状态字进行相应的操作。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void  __irq  IRQ_I2C(void)
{  uint8  sta;

   sta = I2STAT;                    // 读出I2C状态字
   switch(sta)
   {  case  0x08:                   // 己发送起始条件
            if(1==I2C_suba_en) I2DAT = I2C_sla&0xFE;    // 指定子地址读时,先写入地址
              else I2DAT = I2C_sla;                     // 否则直接发送从机地址
            I2CONCLR = 0x28;        // SI=0
            break;
            
      case  0x10:
            I2DAT = I2C_sla;        // 重启动总线后,发送从地址
            I2CONCLR = 0x28;        // SI=0
            break;
   
      case  0x18:                   // 已发送SLA+W,并已接收应答
            if(0==I2C_suba_en)      // 无子地址,则直接发送数据
            {  if(I2C_num>0)
               {  I2DAT = *I2C_buf++;
                  I2CONCLR = 0x28; 
                  I2C_num--;
               }
               else
               {  I2CONSET = 0x10;  // 无数据发送,结束总线
                  I2CONCLR = 0x28;
                  I2C_end = 1;      // 设置总线操作结束标志
               }
               break;
            }
            if(1==I2C_suba_en)      // 发送子地址
            {  I2DAT = I2C_suba;
               I2CONCLR = 0x28;
            }
            if(2==I2C_suba_en)
            {  I2DAT = I2C_suba;
               I2CONCLR = 0x28;
               I2C_suba_en = 0;     // 子地址己处理
            }
            break;
            
      case  0x28:                   // 已发送I2C数据,并接收到应答
            if(0==I2C_suba_en)      // 无子地址,则直接发送数据
            {  if(I2C_num>0)
               {  I2DAT = *I2C_buf++;
                  I2CONCLR = 0x28; 
                  I2C_num--;
               }
               else
               {  I2CONSET = 0x10;  // 无数据发送,结束总线
                  I2CONCLR = 0x28;
                  I2C_end = 1; 
               }
               break;
            }
            if(1==I2C_suba_en)      // 若是指定地址读,则重新启动总线
            {  I2CONSET = 0x20;
               I2CONCLR = 0x18;
               I2C_suba_en = 0;     // 子地址己处理
            }
            break;
   
   
      case  0x20:
      case  0x30:
      case  0x38:
            I2CONCLR = 0x28;        // 总线进入不可寻址从模式
            I2C_end = 0xFF;         // 总线出错,设置标志
            break;
   
   
      case  0x40:                   // 己发送SLA+R,并已接收到应答
            if(1==I2C_num)          // 最后一字节,接收数据后发送非应答信号
            {  I2CONCLR = 0x2C;     // AA=0,接收到数据后产生非应答
            }
            else                    // 接收数据并发送应答信号
            {  I2CONSET = 0x04;     // AA=1,接收到数据后产生应答
               I2CONCLR = 0x28;
            }
            break;
            
      case  0x50:
            *I2C_buf++ = I2DAT;     // 读取数据
            I2C_num--;
            if(1==I2C_num)
            {  I2CONCLR = 0x2C;     // AA=0,接收到数据后产生非应答
            }
            else
            {  I2CONSET = 0x04;     // AA=1,接收到数据后产生应答
               I2CONCLR = 0x28;
            }
            break;
      
      case  0x58:
            *I2C_buf++ = I2DAT;     // 读取最后一字节数据
            I2CONSET = 0x10;        // 结束总线
            I2CONCLR = 0x28;
            I2C_end = 1; 
            break;
      
      case  0x48:
            I2CONCLR = 0x28;        // 总线进入不可寻址从模式
            I2C_end = 0xFF; 
            break;
   }
   

   VICVectAddr = 0x00;              // 中断处理结束
}


/****************************************************************************
* 名称:ISendStr()
* 功能:使用硬件I2C发送数据。
* 入口参数:无
* 出口参数:返回值为0时表示出错,为1时表示操作正确。
* 说明:使用前设置好参数
****************************************************************************/
uint8  ISendStr(void)
{  I2C_end = 0;
   
   I2CONCLR = 0x2C;
   I2CONSET = 0x40;             // 使能I2C
   I2CONSET = 0x64;             // 设置为主机,并启动总线
   
   while(0==I2C_end);
   if(1==I2C_end) return(1);
     else return(0);
}


/****************************************************************************
* 名称:IRcvStr()
* 功能:使用硬件I2C读取数据。
* 入口参数:无
* 出口参数:返回值为0时表示出错,为1时表示操作正确。
* 说明:使用前设置好参数
****************************************************************************/
uint8  IRcvStr(void)
{  if(0==I2C_num) return(0);

   I2C_end = 0;
   
   I2CONCLR = 0x2C;
   I2CONSET = 0x40;             // 使能I2C
   I2CONSET = 0x64;             // 设置为主机,并启动总线
   
   while(0==I2C_end);
   if(1==I2C_end) return(1);
     else return(0);
}


/****************************************************************************
* 名称:I2C_Init()
* 功能:I2C初始化,包括初始化其中断为向量IRQ中断。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void  I2C_Init(void)
{  /* 设置I2C时钟为100KHz */
   I2SCLH = I2SCLL = 14;            // 晶振为11.0592MHz,Fpclk = 2.7648MHz
   
   /* 设置I2C中断允许 */
   VICIntSelect = 0x00000000;		// 设置所有通道为IRQ中断
   VICVectCntl0 = 0x29;				// I2C通道分配到IRQ slot 0,即优先级最高
   VICVectAddr0 = (int)IRQ_I2C;	    // 设置I2C中断向量地址	
   VICIntEnable = 0x0200;           // 使能I2C中断 
}

	

/****************************************************************************
* 名称:DelayNS()
* 功能:长软件延时
* 入口参数:dly		延时参数,值越大,延时越久
* 出口参数:无
****************************************************************************/
void  DelayNS(uint32  dly)
{  uint32  i;

   for(; dly>0; dly--) 
      for(i=0; i<50000; i++);
}
	
	
/****************************************************************************
* 名称:WrEepromErr()
* 功能:读写EEPRM出错报警,即闪动LED1。
* 入口参数:无
* 出口参数:无
****************************************************************************/	
void  WrEepromErr(void)	
{  while(1)
   {  IOSET = LED1CON;
      DelayNS(10);
      IOCLR = LED1CON;
      DelayNS(10);
   }
}
			

/****************************************************************************
* 名称:main()
* 功能:向E2PROM写入10字节数据,然后读出判断是否正确写入。
****************************************************************************/
int  main(void)
{  uint8  i;
   uint8  data_buf[30];

   PINSEL0 = 0x00000050;			// 设置I/O口工作模式,使用I2C口
   PINSEL1 = 0x00000000;		
   IODIR = LED1CON;			        // 设置LED1控制口为输出,其它I/O为输入
   
   I2C_Init();                      // I2C初始化
   
   for(i=0; i<10; i++) data_buf[i] = i+'0';
   I2C_sla = CSI24WC02;
   I2C_suba = 0x00;
   I2C_suba_en = 2;
   I2C_buf = data_buf;
   I2C_num = 10;
   ISendStr();                      // 在0x00地址处写入10字节数据
   DelayNS(1);                      // 等待写周期结束
   
   for(i=0; i<10; i++) data_buf[i] = 0;
   I2C_sla = CSI24WC02+1;
   I2C_suba = 0x00;
   I2C_suba_en = 1;
   I2C_buf = data_buf;
   I2C_num = 10;
   IRcvStr();                       // 在0x00地址处读出10字节数据
  
   /* 校验读出的数据,若不正确则闪烁LED报警 */
   for(i=0; i<10; i++)
   {  if(data_buf[i]!=(i+'0')) WrEepromErr();
   }

   IOCLR = LED1CON;                 // 点亮LED1
   while(1);
   return(0);					
}

⌨️ 快捷键说明

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