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

📄 i2cint.c

📁 LPC2106 控制 GPRS 铁电存储器 时钟等源码
💻 C
字号:
/****************************************************************************
* 文件名:I2CINT.C
* 功能:硬件I2C软件包,利用中断方式操作。
* 说明:主程序要配置好I2C总线接口(I2C引脚功能和I2C中断,并已使能I2C主模式)
****************************************************************************/
#include  "config.h" 
/* 以下为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 (会被更改)



uint8   eeprom[256];                    /* 定义EEPROM存储单元,256字节 */
uint8   adrpoint;                       /* 定义EEPROM读写操作指针 */
uint8   slarv;                          /* 定义子地址接收标志,为1时表示己接收从机地址 */


/*****************************************************************************/
void  I2C_Init(uint32 fi2c)
{  if(fi2c>400000) fi2c = 400000;

   PINSEL0 = (PINSEL0&0xFFFFFF0F) | 0x50; // 设置I2C控制口有效

   I2SCLH = (Fpclk/fi2c + 1) / 2;	// 设置I2C时钟为fi2c
   I2SCLL = (Fpclk/fi2c) / 2;
   I2CONCLR = 0x2C;
   I2CONSET = 0x40;					// 使能主I2C
   
   /* 设置I2C中断允许 */
   VICIntSelect = 0x00000000;		// 设置所有通道为IRQ中断
   VICVectCntl8 = 0x29;				// I2C通道分配到IRQ slot 2,即优先级2
   VICVectAddr8 = (uint32)IRQ_I2C;	    // 设置I2C中断向量地址	
   VICIntEnable = VICIntEnable|0x0200;           // 使能I2C中断 
}
/*********************************************************************************************************
** 函数名称:I2C_SlaveInit()
** 函数功能:从模式I2C初始化,包括初始化其中断为向量IRQ中断。
** 入口参数:adr		本从机地址
** 出口参数:无
********************************************************************************************************/
void  I2C_SlavInit(uint8 adr)
{ 
	PINSEL0 = (PINSEL0&0xFFFFFF0F) | 0x50; // 设置I2C控制口有效

   	I2ADR = adr&0xFE;               	// 设置从机地址
   	I2CONCLR = 0x28;
   	I2CONSET = 0x44;                 // I2C配置为从机模式
   
   // 设置I2C中断允许 
   VICIntSelect = 0x00000000;		// 设置所有通道为IRQ中断
   VICVectCntl8 = 0x29;				// I2C通道分配到IRQ slot 0,即优先级最高
   VICVectAddr8 = (int)IRQ_I2C;	    // 设置I2C中断向量地址	
   VICIntEnable = 0x0200;           // 使能I2C中断 
}
//------------------------------------------------------------------------//

/*void   __irq IRQ_I2C(void)
{  uint8  sta;
   
   sta = I2STAT;                    // 取得I2C状态字
   sta &= 0xF8;
   switch(sta)
   {  case  0x60:                   // 接收到自身SLA+W
      case  0x68:   
            slarv = 0;
            I2CONSET = 0x04;
            break;
            
      case  0xA8:                   // 接收到SLA+R,或已发送数据并接收到ACK位。
      case  0xB0:
      case  0xB8:
            I2DAT = eeprom[adrpoint];
            adrpoint++;
            I2CONSET = 0x04;
            break;
            
      case  0x80:                   // 接收到数据
            if(0==slarv)
            {  adrpoint = I2DAT;
               slarv = 1;
            }
            else
            {  eeprom[adrpoint] = I2DAT;
               adrpoint++;
            }
            I2CONSET = 0x04;
            break;
            
      case  0xA0:                   // 已发送数据,并接收到非ACK
      case  0xC0:                   // 总线结束,或总线重新启动
      default:                      // 其它状态
            I2CONSET = 0x04;
            break;
   }
   
   I2CONCLR = 0x38;                 // 清除标I2C标志位,STA、STO、SI
   
   VICVectAddr = 0x00;   
}

*/

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 = 0x08;
               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;
            
      default: 
            break;
   }
   VICVectAddr = 0x00;              // 中断处理结束
}

/****************************************************************************
* 名称:ISendByte()
* 功能:向无子地址器件发送一字节数据。
* 入口参数:sla		器件地址
*          dat		要发送的数据
* 出口参数:返回值为0时表示出错,为1时表示操作正确。
* 说明:使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
****************************************************************************/
uint8  ISendByte(uint8 sla, uint8 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);
}
/****************************************************************************
* 名称:ISendStr()
* 功能:向有子地址器件发送多字节数据。
* 入口参数:sla		器件从机地址
*          suba		器件子地址
*          s		数据发送缓冲区指针
*          no		发送数据个数
* 出口参数:返回值为0时表示出错,为1时表示操作正确。
* 说明:使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
****************************************************************************/
uint8  ISendStr(uint8 sla, uint8 suba, uint8 *s, uint8 no)
{  /* 参数设置 */
   I2C_sla = sla;		// 写操作的器件地址
   I2C_suba = suba;		// 子地址
   I2C_buf = s;			
   I2C_num = no;	
   I2C_suba_en = 2;		// 有子地址写
   I2C_end = 0;
   
   I2CONCLR = 0x2C;
   I2CONSET = 0x60;             // 设置为主机,并启动总线
   
   while(0==I2C_end);
   if(1==I2C_end) return(1);
     else return(0);
}
/****************************************************************************
* 名称:IRcvByte()
* 功能:向无子地址器件读取一字节数据。
* 入口参数:sla		器件地址
*          dat		接收数据的变量指针
* 出口参数:返回值为0时表示操作出错,为1时表示操作正确。
* 说明:使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
****************************************************************************/
uint8  IRcvByte(uint8 sla, uint8 *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);
}
/****************************************************************************
* 名称:IRcvStr()
* 功能:向有子地址器件读取多字节数据。
* 入口参数:sla		器件地址
*          suba		器件子地址
*          s		数据接收缓冲区指针
*	   	   no 		读取数据个数
* 出口参数:返回值为0时表示操作出错,为1时表示操作正确。
* 说明:使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
****************************************************************************/
uint8  IRcvStr(uint8 sla, uint8 suba, uint8 *s, uint8 no)
{  if(0==no) return(0);
   
   /* 参数设置 */
   I2C_sla = sla+1;		// 读操作的器件地址
   I2C_suba = suba;		
   I2C_buf = s;
   I2C_num = no;
   I2C_suba_en = 1;		// 有子地址读
   I2C_end = 0;
   
   I2CONCLR = 0x2C;
   I2CONSET = 0x60;             // 设置为主机,并启动总线
   
   while(0==I2C_end);
   if(1==I2C_end) return(1);
   else return(0);
}

void DelayNS(uint32 timer)
{	uint32 i;
	
	for(i=0;i<timer;i++)
	{
	i=i;i=i;i=i;i=i;i=i;
	i=i;i=i;i=i;i=i;i=i;
	i=i;i=i;i=i;i=i;i=i;
	
	}

}


void GetTime(uint8 *Time)
{
//	uint8 *time;
	
	IRcvStr(PCF8563,0x02,&Time[0],1);
	
	IRcvStr(PCF8563,0x03,&Time[1],1);
	
	IRcvStr(PCF8563,0x04,&Time[2],1);
	
	IRcvStr(PCF8563,0x05,&Time[3],1);
	
	IRcvStr(PCF8563,0x06,&Time[4],1);
	
	IRcvStr(PCF8563,0x07,&Time[5],1);
	
	IRcvStr(PCF8563,0x08,&Time[6],1);
	
	Time[0] = Time[0]&0x7f;Time[1] = Time[1]&0x7f;Time[2] = Time[2]&0x3f;
    Time[3] = Time[3]&0x3f;Time[5] = Time[5]&0x1f;
	
}
void SetTime(uint8 *Time)
{
	
	Time[0] = Time[0]&0x7f;Time[1] = Time[1]&0x7f;Time[2] = Time[2]&0x3f;
    Time[3] = Time[3]&0x3f;Time[5] = Time[5]&0x1f;
	ISendStr(PCF8563,0x02,&Time[0],1);
	
	ISendStr(PCF8563,0x03,&Time[1],1);
	
	ISendStr(PCF8563,0x04,&Time[2],1);
	
	ISendStr(PCF8563,0x05,&Time[3],1);
	
	ISendStr(PCF8563,0x06,&Time[4],1);
	
	ISendStr(PCF8563,0x07,&Time[5],1);
	
	ISendStr(PCF8563,0x08,&Time[6],1);
}






uint8 IIC_UART_Init(uint8 port)//9600
{
    uint8 temp_mr;
    
    //------------------uart复位-----------------------//
    IO0CLR = RST_UART;
    DelayNS(10000);
    IO0SET = RST_UART;
    //-------------------------------------------------//
    port = port<<1;
    temp_mr = 0x83;
	ISendStr(IIC_UART2,0x18|port,&temp_mr,1);
	DelayNS(3000);
	temp_mr = 12;
	ISendStr(IIC_UART2,0x00|port,&temp_mr,1);
	DelayNS(3000);
	temp_mr = 0x00;
	ISendStr(IIC_UART2,0x08|port,&temp_mr,1);
	DelayNS(3000);
	temp_mr = 0x03;
	ISendStr(IIC_UART2,0x18|port,&temp_mr,1);
	DelayNS(3000);
	
	temp_mr = 0x01;//0x01  //fcr
	ISendStr(IIC_UART2,0x10|port,&temp_mr,1);
	DelayNS(3000);
	temp_mr = 0x01;
	ISendStr(IIC_UART2,0x08|port,&temp_mr,1);
	DelayNS(3000);
	
	return 1;

}

uint8 IIC_UART_SenData(uint8 port,uint8 dat)//1200
{
    uint8 temp_mr;
    port = port<<1;
	ISendStr(IIC_UART2,0x00|port,&dat,1);
	
	while((temp_mr&0x40)==0)
	{
	IRcvStr(IIC_UART2,0x28|port,&temp_mr,1);
	//DelayNS(500);
	};
	return 1;

}
uint8 IIC_Sendstr(uint8 port,uint8 *str,uint8 len)
{
	uint8 temp_lenth;
	for(temp_lenth=0;temp_lenth<len;temp_lenth++)
	{
		IIC_UART_SenData(port,str[temp_lenth]);
		//DelayNS(1000);
	}
	return 1;
}


#define     PCA9554_A   0x40
#define     PCA9554_B   0x4E

uint16 Get_key(void)
{
    uint8 temp_key,temp_key1;
    uint16 temp_key2;
    IRcvStr(PCA9554_A,0x00,&temp_key,1);
    IRcvStr(PCA9554_B,0x00,&temp_key1,1);
    temp_key2 = temp_key;
    temp_key2 = ((temp_key2<<8)|temp_key1);
    return temp_key2;
}

⌨️ 快捷键说明

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