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

📄 iic.c

📁 程序展示了 ucos在EASYARM2200上的移植。并添加了多个设备在UCOS下的驱动UART:SPI:IIC:ZLG7290.当然还没有完全完成板上其它设备的驱动。由于限制
💻 C
字号:
#include "config.h"

#define IIC_WRITE_END    1
#define IIC_READ_END     2
#define IIC_LOST_BUS     4
#define IIC_ACK_ERROR    8


OS_EVENT *iicSem;     /***IIC互斥访问信号量***/
OS_EVENT *iicMbox;           /***本地信号用于从中断服务程序返回消息***/
static INT8U  *iicBuf;        /***缓冲区***/
static INT16U iicNbyte;      /***读或写的长度***/
static INT8U  iicAddr;        /***设备地址***/

/*********************************************************************************************************
** 功能描述: 初始化IIC 频率不能超过400K
             连接IIC到相应管脚
             创建
********************************************************************************************************/
INT8U initIic(INT32U freq)
{
   VICIntEnClr=1<<INTINDEXIIC;
   if(freq>400000)
      freq=400000;
   PINSEL0=(PINSEL0&0XFFFFFF0F)|0X50;   /***防止硬件初始化的时候没有配置***/
   I2CONCLR=0X6C;/***AAC SIC STAC I2ENC  清除应答位、中断位、起始位、禁止IIC接口***/
   I2SCLH=(Fpclk/freq+1)/2+1;
   I2SCLL=(Fpclk/freq+1)/2;
   //iicMutex=OSMutexCreate(IICMUTEXPRIORITY,&err);/***信用信号量测试,正式应用的时候应该用互斥信号量***/
   
   iicSem=OSSemCreate(1);                          /***创建IIC信号量,只有一个IIC接口可用***/
   
   iicMbox=OSMboxCreate(NULL);
   if(iicMbox==NULL)
      return(FALSE);
  
   if(iicSem!=NULL)
      return(TRUE); 
   return(FALSE);
}

/*********************************************************************************************************
** 功能描述: 写iiC,但不发送STOP信号 ,
             提供给真正的读写函数使用,因为读写操作的时候,总是执行一段相同的处理
             启动IIC 发送起始信号 写入设备地址 如果有子地址 写子地址 
**注意:现行的驱动程序中 数据区包含器件的子地址(如果有)所以长度也包含子地址的长度
********************************************************************************************************/
INT8U __iicWrite(INT8U addr,INT8U *Data,INT16U length)
{
   INT8U err;
   unsigned int result;
   
   iicAddr=addr&0xfe;
   iicNbyte=length;
   iicBuf=Data;
   I2CONSET=0X24;/***发送起始条件***/
   result=(unsigned int)OSMboxPend(iicMbox,0,&err);
   return(result);
}

INT16U iicWrite(INT8U deviceAdd,INT8U*data,INT16U length)
{
   INT8U err;
   OSSemPend(iicSem,0,&err);//等待IIC信号量
   I2CONCLR=0X6C;
   I2CONSET=0X40;/***使能IIC接口***/
   VICIntEnable=1<<INTINDEXIIC;
   if(__iicWrite(deviceAdd,data,length)==IIC_WRITE_END)
      {
         I2CONSET=1<<4;/***发送停止信号***/
         I2CONCLR=0X28;/***清除SI标志***/
      }
   VICIntEnClr=1<<INTINDEXIIC;/***禁止IIC中断***/
   OSSemPost(iicSem);
   return(length-iicNbyte);/***返回已写入的字节数***/
}

int16 iicRead(INT8U deviceAdd,INT8U *result,INT8U *extendAdd,INT8U extendAddLength,INT16U length)
{
   INT8U err;
   OSSemPend(iicSem,0,&err);
   I2CONCLR=0X6C;
   I2CONSET=0X40;
   VICIntEnable=1<<INTINDEXIIC;
   if(extendAddLength>0)
      {
         if(__iicWrite(deviceAdd,extendAdd,extendAddLength)!=IIC_WRITE_END)
            {
               return(-1);
            } 
      }
   iicAddr=deviceAdd|0x01;//转入读操作
   iicNbyte=length;
   iicBuf=result;
   I2CONCLR=0X28;
   I2CONSET=0x24;//为什么是24 2 起始标志,4  AC 为什么呢
   VICIntEnable=1<<INTINDEXIIC;
   OSMboxPend(iicMbox,0,&err);
   VICIntEnClr=1<<INTINDEXIIC;
   OSSemPost(iicSem);
   return(length-iicNbyte);
}
/***IIC 主机模式 读写中断服务程序;根据数据手册中的中断状态进行处理***/
void IIC_Exception(void)
{
   OS_ENTER_CRITICAL();
   switch(I2STAT&0XF8)
      {
         case 0X08://已发送起始条件
            {
               //break;
            } 
         case 0x10://已发送重新起始条件  目的是发送设备地址,
                   //如果首是写操作,因为CASE 0X08的时候没有break
                   //所以还是发送地址,
            {
               I2DAT=iicAddr;
               I2CONCLR=0X28;
               break;
            } 
         case 0x18://已发送SLA+W;已接受ACK,下面发送数据
            {
               I2DAT=*iicBuf++;
               iicNbyte--;
               I2CONCLR=0X28;
               break;
            }
         case 0x28://已发送I2DAT中的数据字节,已接受ACK
                   //下面若果数据没有发送完毕继续I2DAT=DATA;
                   //如果数据发送完毕,返回__iicWrite()函数,写完成标志
            {
               if(iicNbyte>0)//数据还没有发送完毕
                  {
                     I2DAT=*iicBuf++;//发送数据
                     iicNbyte--;
                     I2CONCLR=0X28;
                  }
               else
                  {
                     OSMboxPost(iicMbox,(void*)IIC_WRITE_END);//写操作完成
                     VICIntEnClr=1<<INTINDEXIIC;
                  }
               break;
            }
         case 0x20://已发送SLA+W;已接收非ACK 
         case 0x30://已发送I2DAT中的数据;已接收非ACK
         case 0x48://已发送SLA+R;已接收非ACK
            {
               I2CONSET=1<<4;//发送STOP
               OSMboxPost(iicMbox,(void *)IIC_ACK_ERROR);
               I2CONCLR=0X28;
               break;
            } 
         case 0x38://在发送SLA+R时丢失仲裁
            {
               OSMboxPost(iicMbox,(void*)IIC_LOST_BUS);
               I2CONCLR=0X28;
               break;
            }
         case 0x40://已发送SLA+R;已接收ACK;无I2DAT动作;硬件将要接收数据;返回应答或者非应答
            {
              if(iicNbyte<=1)
                 {
                    I2CONCLR=1<<2;//下次发送非应答
                 }
              else
                 {
                    I2CONSET=1<<2;//下次发送应答信号
                    
                 }
              I2CONCLR=0X28;
              break;
            }
         case 0x50://已接收到数据字节;已发送ACK
            {
               *iicBuf++=I2DAT;//接收数据
               iicNbyte--;
               if(iicNbyte<=1)
                  {
                     I2CONCLR=1<<2;//如果是还剩下一个数据没有接受下次发送非应答信号
                  }
               I2CONCLR=0X28;
               break;
            }
         case 0x58://已接收数据字节;已发送非ACK
            {
               *iicBuf=I2DAT;//接收最后一个数据
               iicNbyte--;
               I2CONSET=1<<4;//结束总线,发送STOP
               OSMboxPost(iicMbox,(void*)IIC_READ_END);
               I2CONCLR=0X28;
               break;
            }
         default:
            {
               I2CONCLR=0X28;
               break;
            }
      }
   VICVectAddr=0;//通知中断服务程序结束
   OS_EXIT_CRITICAL();//退出中断
}

⌨️ 快捷键说明

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