I2c
2015-09-22 20:13 1784717631 阅读(300) 评论(1) 收藏 举报在学习单片机的时候就听说过I2c,不过那时候听的一团糟,什么都不会,而且51上面没有集成真正的I2c,只能用IO口模拟它的时序来实现。I2c总线是一种用于Ic器件之间连接的双向二进制总线。所谓总线,就是它上面可以挂多个器件,并且通过两根线连接,占用空间非常小。 其中SDA是数据线,SCL是时钟线。
I2c的几种信号状态:
空闲状态:SCL 高 SDA 高
开始条件: SCL 高 SDA 高-->低
结束条件: SCL 高 SDA 低-->高
数据有效: SCL 高 SDA 稳定
I2c最重要的是时序的掌握,这点和Nandflash有点像,就是要严格按照手册上面的时序图操作。
#include"stdio.h"
#define  u8 unsigned char
//IO口的配置
#define GPD1CON	    (*(volatile unsigned long *)0xE02000C0)
#define 	GPD1PUD 	(*(volatile unsigned long *) 0xE02000C8)
#define IICCON  	    (*(volatile unsigned long *)0xE1800000)
#define IICSTAT	    (*(volatile unsigned long *)0xE1800004)
#define IICDS		    (*(volatile unsigned long *)0xE180000C)
//i2c 的中断源控制器,VIC1  的14 号中断
#define VIC1INTENCLEAR  (*(volatile unsigned long *)0xF2100014)
int init_i2c(void)
{
	  //端口配置
	  //GPD1PUD &= 0xfff0;  //Pull-up/ down disabled
	  //端口配置成i2c的SDA 和SCL
	  GPD1CON &= 0xffffff00;
	  GPD1CON |=0x22;    
	  //关闭i2c0 的中断源   读取的过程中会不断产生中断,只要关闭总的中断,就不会上报给CPU了
	  VIC1INTENCLEAR  |= (1<<14);
	  // 产生应答                 使能中断控制位
	  IICCON = (1<<7) |(0<<6) |(1<<5) |0xf;
	  //使能传输端口
	  IICSTAT = (1<<4);
	  return 0;
}
int write_i2c(u8 data, u8 addr) //地址和数据都是八位的 
{
	  int num;	
	  int i;
	  //发送设备的地址 和写命令(最后一位是0)
	  IICSTAT  = 0xf0;  //产生start 信号
	  IICDS = 0xa0;
	  //wait_i2c_finish();
   WaitOprFinish();
	  //发送写的地址
	  IICDS = addr;
	  //for(i=0; i<20; i++);
	  IICCON &= ~(1<<4);
	  //wait_i2c_finish();
   WaitOprFinish();
	  //发送数据
	  IICDS = data;
	  //for(i=0; i<20; i++);
	  IICCON &= ~(1<<4);
	  //wait_i2c_finish();
   WaitOprFinish();
	   IICSTAT &= ~(1<<5); //产生stop 信号  
	  IICCON &= ~(1<<4);
	  for(num=0; num<10000; num++); //加延时
	  return 0;
}
int read_i2c(u8 addr,u8 *data)
{
	  u8  buf =0;
	  int num;
	
	  IICDS =0xa0;//设备地址发送给移位寄存器
	  IICSTAT =0xf0;//产生start信号       主发送模式
	  //wait_i2c_finish();
   WaitOprFinish();
	  IICDS =addr;	//写的数据的地址
	  IICCON =0xaf;
	  //wait_i2c_finish();
   WaitOprFinish();
	  IICDS  =  0xa0;    // 设备地址发送给移位寄存器
	  IICSTAT = 0xb0;   // 产生start信号,      主接收模式
	  IICCON = 0xaf;      // resume IIC Operation
	  //wait_i2c_finish();
   WaitOprFinish();
	  IICCON = 0x2f;  //无应答
	  //wait_i2c_finish();
   WaitOprFinish();
	  buf = IICDS;
	  IICSTAT = 0x90;//产生停止信号 
	  IICCON  = 0xaf;
for(num=0; num<10000; num++);
	  *data=buf;
}
void WaitOprFinish(void)
{
	  unsigned int  uIICConReg = 0;
	  unsigned int  uRes = 0;
 
	  do
	  {
	       uIICConReg = IICCON;   
	       //取出第四位,当传输结束时会产生中断信号1
	       uRes = uIICConReg & 0x10; 
	  }while(uRes == 0);  //祍却钡酱渫瓿?
	  return ;
}
//最后是测试函数,先写后读
int test_i2c(void)
{
	  int i;
	  volatile int j;
	  u8 buf = 0;
	  int num;
	  init_i2c();
	  printf("write...:\r\n");
	
	  for(i = 0; i<20; i++)
	  {
		    write_i2c(i*2, i);
		    for(j = 0;j < 10000;j++);
	  }
	
	  for(num=0; num<10000; num++);
	
	  printf("read.....:\r\n");
	  for(i = 0; i<20; i++)
	  {
		    read_i2c(i,&buf);
		    printf("%d\r\n", buf);
	  }
}
                    
                
                
            
        
浙公网安备 33010602011771号