×
单片机 > 单片机程序设计 > 详情

ARM7入门11,IIC通信

发布时间:2020-06-15 发布时间:
|
D1点亮说明正确,D1闪烁说明错误。

主程序:

/*******************************************************************************
*File: Main.C
*功能: 使用硬件I2C对EEPROM进行操作,利用中断方式操作
*******************************************************************************/
#include   "config.h"
#define CAT24WC02 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;  
  }
  else
  {I2CONSET=0x04;
   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发送数据
*******************************************************************************/
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读取数据
*******************************************************************************/
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 Slot0,即优先级最高
  VICVectAddr0=(int)IRQ_I2C;  //设置I2C中断向量地址
  VICIntEnable=0x0200;            //使能I2C中断
  
}
/*******************************************************************************
*名称: DelayNS()
*功能: 长软件延时
*******************************************************************************/
void DelayNS(uint32 dly)
{ uint32 i;
  for(;dly>0;dly--)
    for(i=0;i<50000;i++);
}
/*******************************************************************************
*名称: WrEepromErr()
*功能: 读写E2PROM出错报警,即闪动LED1
*******************************************************************************/
void WrEepromErr(void)
{ while(1)
 { IO0SET=LED1CON;
  DelayNS(50);
  IO0CLR=LED1CON;
  DelayNS(50);
 }
}
/*******************************************************************************
*名称: main()
*功能: 向E2PROM写入10字节数据,然后读出判断是否正确写入
*******************************************************************************/
int main(void)
{  uint8  i;
   uint8  data_buf[30];
   PINSEL0=0x00000050;              //设置I/O口工作模式,使用I2C
   PINSEL1=0x00000000;
   IO0DIR=LED1CON;                  //设置LED1控制口为输出,其它I/O为输入
   I2C_Init();                    //I2C初始化
   for (i=0;i<10;i++)data_buf[i]=i+'0';
   I2C_sla=CAT24WC02;
   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=CAT24WC02+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();
   }
   IO0CLR=LED1CON;    //点亮LED1
   while(1);
}

关键字:ARM7入门  IIC通信

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
单片机中高阻态的实质及意义