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

📄 i2c.c

📁 一个在PROTEUS 中方真lpcarm的ucosii移植
💻 C
字号:
/****************************************Copyright (c)**************************************************
**--------------File Info-------------------------------------------------------------------------------
** File name: I2C.h
** Last modified Date:2007-12-20
** Last Version: 1.0
** Descriptions: I2C驱动程序,利用中断方式发送或者接受数据,主模式 master mode
**------------------------------------------------------------------------------------------------------
** Created by:   Rein Lee
** Created date: 2007-12-20
** Version:      1.0
** Descriptions: The original version
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Descriptions:
********************************************************************************************************/
#include  "config.h" 
/* 以下为I2C操作时所需要的变量 */
volatile  uint8  I2C_slave;            // 从机地址(即器件地址)
volatile  uint8  I2C_subaddr;          // 子地址
volatile  uint8  *I2C_buffer;          // 数据缓冲区指针 (读操作时会被更改)
volatile  uint8  I2C_number;           // 操作数据个数 (会被更改)
volatile  uint8  I2C_end;              // 操作结束标志,为1时表示操作结束,为0xFF时表示操作失败 (会被设置)
volatile  uint8  I2C_subaddr_enable;   // 子地址使能控制,读操作时请设置为1,写操作时请设置为2 (会被更改)

/*********************************************************************************************************
** 函数名称: I2C_Init
** 功能描述: I2C总线初始化
** 输 入: fi2c I2C总线速率
** 输 出: 无       
** 全局变量: 无
** 调用模块: 无
**------------------------------------------------------------------------------------------------------
** Created by    Rein Lee
** Created date: 2007-12-20
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
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
}
/*********************************************************************************************************
** 函数名称: I2CSendByte()
** 功能描述: 向无子地址器件发送一字节数据。
** 输 入: sla		器件地址
*          dat		要发送的数据 
** 输 出: 返回值为0时表示出错,为1时表示操作正确       
** 全局变量: 无
** 调用模块: 无
**------------------------------------------------------------------------------------------------------
** Created by    Rein Lee
** Created date: 2007-12-20
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8  I2CSendByte(uint8 sla, uint8 dat)
{  /* 参数设置 */
   I2C_slave = sla;		// 写操作的器件地址
   I2C_buffer = &dat;		// 待发送的数据
   I2C_number = 1;			// 发送1字节数据
   I2C_subaddr_enable = 0;		// 无子地址
   I2C_end = 0;
   
   I2CONCLR = 0x2C;
   I2CONSET = 0x60;             // 设置为主机,并启动总线
   
   while(0==I2C_end);
   if(1==I2C_end) return(1);
     else return(0);
}



/*********************************************************************************************************
** 函数名称: I2CSendString()
** 功能描述: 向有子地址器件发送多字节数据。
** 输 入: sla		器件从机地址
*          suba		器件子地址
*          s		数据发送缓冲区指针
*          no		发送数据个数 
** 输 出: 返回值为0时表示出错,为1时表示操作正确       
** 全局变量: 无
** 调用模块: 无
**------------------------------------------------------------------------------------------------------
** Created by    Rein Lee
** Created date: 2007-12-20
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8  I2CSendString(uint8 sla, uint8 suba, uint8 *s, uint8 no)
{  /* 参数设置 */
   I2C_slave = sla;		// 写操作的器件地址
   I2C_subaddr = suba;		// 子地址
   I2C_buffer = s;			
   I2C_number = no;	
   I2C_subaddr_enable = 2;		// 有子地址写
   I2C_end = 0;

   I2CONCLR = 0x2C;
   I2CONSET = 0x60;             // 设置为主机,并启动总线
   VICIntEnable = 1<<9;                //使能I2C中断
   while(0==I2C_end);
   if(1==I2C_end) return(1);
     else return(0);
}


/*********************************************************************************************************
** 函数名称: I2CRcvByte()
** 功能描述: 向无子地址器件读取一字节数据。
** 输 入: sla		器件地址
*          dat		接收数据的变量指针 
** 输 出: 返回值为0时表示出错,为1时表示操作正确       
** 全局变量: 无
** 调用模块: 无
**------------------------------------------------------------------------------------------------------
** Created by    Rein Lee
** Created date: 2007-12-20
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8  I2CRcvByte(uint8 sla, uint8 *dat)
{  /* 参数设置 */
   I2C_slave = sla+1;		// 读操作的器件地址
   I2C_buffer = dat;
   I2C_number = 1;
   I2C_subaddr_enable = 0;		// 无子地址
   I2C_end = 0;
   
   I2CONCLR = 0x2C;
   I2CONSET = 0x60;             // 设置为主机,并启动总线
   VICIntEnable = 1<<9;                //使能I2C中断
   while(0==I2C_end);
   if(1==I2C_end) return(1);
     else return(0);
}
/*********************************************************************************************************
** 函数名称: I2CRcvString()
** 功能描述: 向有子地址器件读取多字节数据。
** 输 入: sla		器件从机地址
*          suba		器件子地址
*          s		数据发送缓冲区指针
*          no		发送数据个数 
** 输 出: 返回值为0时表示出错,为1时表示操作正确       
** 全局变量: 无
** 调用模块: 无
**------------------------------------------------------------------------------------------------------
** Created by    Rein Lee
** Created date: 2007-12-20
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8  I2CRcvString(uint8 sla, uint8 suba, uint8 *s, uint8 no)
{  if(0==no) return(0);
   
   /* 参数设置 */
   I2C_slave = sla+1;		// 读操作的器件地址
   I2C_subaddr = suba;		
   I2C_buffer = s;
   I2C_number = no;
   I2C_subaddr_enable = 1;		// 有子地址读
   I2C_end = 0;
   
   I2CONCLR = 0x2C;
   I2CONSET = 0x60;             // 设置为主机,并启动总线
   VICIntEnable = 1<<9;                //使能I2C中断
   while(0==I2C_end);
   if(1==I2C_end) return(1);
     else return(0);
}
/*********************************************************************************************************
** 函数名称: I2C_Exception()
** 功能描述: I2C中断,通过判断I2C状态字进行相应的操作。
** 输 入: 无 
** 输 出: 无       
** 全局变量: 无
** 调用模块: 无
**------------------------------------------------------------------------------------------------------
** Created by    Rein Lee
** Created date: 2007-12-20
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void I2C_Exception(void)
{  
   uint8  sta;
   OS_ENTER_CRITICAL();
   sta = I2STAT;                    // 读出I2C状态字
   switch(sta)
   {  case  0x08:                   // 己发送起始条件 
            if(1==I2C_subaddr_enable) I2DAT = I2C_slave&0xFE;    // 指定子地址读时,先写入地址
              else I2DAT = I2C_slave;                     // 否则直接发送从机地址
            I2CONCLR = 0x28;        // SI=0
            break;
            
      case  0x10:
            I2DAT = I2C_slave;        // 重启动总线后,发送从地址
            I2CONCLR = 0x28;        // SI=0
            break;
   
      case  0x18:                   // 已发送SLA+W,并已接收应答
            if(0==I2C_subaddr_enable)      // 无子地址,则直接发送数据
            {  if(I2C_number>0)
               {  
                  I2DAT = *I2C_buffer++;
                  I2CONCLR = 0x28;
                  I2C_number--;
               }
               else
               {  
                  I2CONCLR = 0x28;
                  I2CONSET = 0x10;  // 无数据发送,结束总线
                  I2C_end = 1;      // 设置总线操作结束标志
               }
               break;
            }
            if(1==I2C_subaddr_enable)      // 发送子地址
            {  
               I2DAT = I2C_subaddr;
               I2CONCLR = 0x28;
            }
            if(2==I2C_subaddr_enable)
            {  
               I2DAT = I2C_subaddr;
               I2CONCLR = 0x28;
               I2C_subaddr_enable = 0;     // 子地址己处理
            }
            break;
            
      case  0x28:                   // 已发送I2C数据,并接收到应答
            if(0==I2C_subaddr_enable)      // 无子地址,则直接发送数据
            {  if(I2C_number>0)
               {  
                  I2DAT = *I2C_buffer++;
                  I2CONCLR = 0x28;
                  I2C_number--;
               }
               else
               {  //Rein
                  I2CONSET = 0x10;  // 无数据发送,结束总线
                  I2CONCLR = 0x28;
                  I2C_end = 1; 
               }
               break;
            }
            if(1==I2C_subaddr_enable)      // 若是指定地址读,则重新启动总线
            {  //Rein
               I2CONSET = 0x20;
               I2CONCLR = 0x08;
               I2C_subaddr_enable = 0;     // 子地址己处理
            }
            break;
   
   
      case  0x20:
      case  0x30:
      case  0x38:
            I2CONCLR = 0x28;        // 总线进入不可寻址从模式
            I2C_end = 0xFF;         // 总线出错,设置标志
            break;
   
   
      case  0x40:                   // 己发送SLA+R,并已接收到应答
            if(1==I2C_number)          // 最后一字节,接收数据后发送非应答信号
            {  I2CONCLR = 0x2C;     // AA=0,接收到数据后产生非应答
            }
            else                    // 接收数据并发送应答信号
            {  
               I2CONCLR = 0x28;
               I2CONSET = 0x04;     // AA=1,接收到数据后产生应答
            }
            break;
            
      case  0x50:
            *I2C_buffer++ = I2DAT;     // 读取数据
            I2C_number--;
            if(1==I2C_number)
            {  I2CONCLR = 0x2C;     // AA=0,接收到数据后产生非应答
            }
            else
            {  
               I2CONSET = 0x04;     // AA=1,接收到数据后产生应答
               I2CONCLR = 0x28;
               
            }
            break;
      
      case  0x58:
            //Rein
            *I2C_buffer++ = I2DAT;     // 读取最后一字节数据
            I2CONSET = 0x10;        // 结束总线
            I2CONCLR = 0x28;
            I2C_end = 1; 
            break;
      
      case  0x48:
            I2CONCLR = 0x28;        // 总线进入不可寻址从模式
            I2C_end = 0xFF; 
            break;
            
      default: 
            if(I2C_end == 1)
              VICIntEnClr = 1 << 9; 	//关闭中断
            break;
   }
   VICVectAddr = 0x00;              // 中断处理结束
   OS_EXIT_CRITICAL();
}
/*********************************************************************************************************
**                            End Of File
********************************************************************************************************/

⌨️ 快捷键说明

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