s3c2440 iic eeprom


1、使用2440 iic 模块控制

#include "2440addr.h"
#include "uart.h"


volatile int ackFlag = 0;

void delay()
{
	int i,j;
	for(i = 0; i < 500;i++)
		for(j = 0; j < 500; j++)
		;
}

/***********************************************
Function  name  :   Iic_ISR
Description     :   iic 中断处理函数
Input parameter :   none	
Return          :   none 	
Others		    :                   	                    
*************************************************/
static void __irq Iic_ISR()
{
	//清除中断
	rSRCPND |= (1 << 27);
	rINTPND |= (1 << 27);
	
	ackFlag = 1;
}



/***********************************************
Function  name  :   iic_init
Description     :   iic 通信初始化
Input parameter :   none	
Return          :   none 	
Others		    :                   	                    
*************************************************/
void iic_init(void)
{
	//配置GPE14\15 为 IICSCL 、IICSDA、不使能拉高电阻(GPE14\15没有对应的位)
	rGPECON &= ~(0xf << 28);
	rGPECON |= (0x2 << 30) | (0x2 << 28);
	
	//清除中断
	rSRCPND |= (1 << 27);
	rINTPND |= (1 << 27);
	//开启iic中断
	rINTMSK &= ~(1 << 27);
	
	//设置中断处理函数
	pISR_IIC = (unsigned)Iic_ISR;
	
	//配置IICCON寄存器:使能ACK,时钟源选择fPCLK /512
	//(从eeprom手册看出,其最大的传输频率为100kHZ)
	//使能中断,发送时钟值为0xf。
	//Tx clock = IICCLK/(IICCON[3:0]+1)=50000000/512=97kHz
	rIICCON = (1<<7)|(1<<6)|(1<<5);
	
	//设置CPU的从设备地址(未使用)
	rIICADD = 0x10;
	//IIC-bus data output enable
	rIICSTAT |= (1<<4);
	

}

/***********************************************
Function  name  :   iic_Tx
Description     :   iic 发送数据
Input parameter :   buffer 要发送的数据	
					size:数据大小
Return          :   none 	
Others		    :                   	                    
*************************************************/
void iic_Tx(unsigned char devAddr,unsigned char wordAddr,char buffer[],int size)
{
	int i = 0,j = 0;
	
	ackFlag = 0;
	
	//写从设备地址到IICDS寄存器
	rIICDS = devAddr;
	
	//配置为主发送模式
	//写0XF0到IICSTAT(主发送模式,并开始)
	rIICSTAT = 0xf0;
	for(i = 0; i < 100; i++);
	//清除挂起位
	rIICCON &= ~(1<<4);
	//等待ack中断响应
	//while(!ackFlag);
	//注意:这里等待挂起可以单独判断pending,但不能单独判断ack,防止数据丢失
	while(!ackFlag)
		delay();
	ackFlag = 0;
	
	//写起始地址到IICDS寄存器
	rIICDS = wordAddr;
	for(i = 0; i < 100; i++);
	//清除挂起位
	rIICCON &= ~(1<<4);
	//等待ack中断响应
	while(!ackFlag)
		delay();
	ackFlag = 0;
	
	//向IICDS写入发送数据直到发送结束
	for(j = 0; j < size; j++)
	{
		//写入新数据
		rIICDS = buffer[j];
		for(i = 0; i < 100; i++);
		//清除挂起位
		rIICCON &= ~(1<<4);
		//等待ack中断
		while(!ackFlag)
			delay();
		ackFlag = 0;
		
	}
	
	//发送结束,写0XD0到 IICSTAT
	rIICSTAT = 0xd0;
	rIICCON = 0xe0;
	
	//等待停止条件生效
	delay();
	
}



/***********************************************
Function  name  :   iic_Rx
Description     :   iic 接收数据
Input parameter :   buffer 接收buffer
Return          :   i: 接收到的数据大小 	
Others		    :                   	                    
*************************************************/
int iic_Rx(unsigned char devAddr,unsigned char wordAddr,char * buffer,int size)
{
	char ch;
	int i = 0,j = 0;
	ackFlag = 0;
	
	//写从设备地址到IICDS寄存器
	rIICDS = devAddr;
	for(i = 0; i < 100; i++);
	//配置为主发送模式
	//写0XF0到IICSTAT(主发送模式,并开始)
	rIICSTAT = 0xf0;
	//清除挂起位
	rIICCON &= ~0x10;
	//等待ack中断响应
	while(!ackFlag)
		delay();
	ackFlag = 0;
	
	
	//写起始地址到IICDS寄存器
	rIICDS = wordAddr;
	for(i = 0; i < 100; i++);
	//清除挂起位
	rIICCON &= ~0x10;
	//等待ack中断响应
	while(!ackFlag)
		delay();
	ackFlag = 0;
	
	
	//写从设备地址到IICDS寄存器
	rIICDS = devAddr;
	for(i = 0; i < 100; i++);
	//写0XB0到IICSTAT(主接收模式,并开始)
	rIICSTAT = 0xb0;
	//清除挂起位
	rIICCON &= ~0x10;
	//等待ack中断响应
	while(!ackFlag)
		delay();
	ackFlag = 0;
	
	//从IICDS读取第一个字节舍弃
	ch = rIICDS;
	//清除挂起位
	rIICCON &= ~0x10;
	//等待ack中断响应
	while(!ackFlag)
		delay();
	ackFlag = 0;
	
	//从IICDS读取数据直到接收结束
	for(j = 0; j < size; j++)
	{
		if(j == size-1)
		{
			rIICCON &= ~0x80;
		}
		//从IICDS读取数据
		buffer[j] = rIICDS;
		for(i=0;i<100;i++);
		//清除挂起位
		rIICCON &= ~0x10;
		//等待ack中断响应
		while(!ackFlag)
			delay();
		ackFlag = 0;
	}
	
	//接收结束,写0X90到 IICSTAT
	rIICSTAT = 0x90;
	rIICCON = 0xe0;
	
	//等待停止条件生效
	delay();
	
	return j;
}

/***********************************************
Function  name  :   iic_test
Description     :   iic 测试
Input parameter :   none
Return          :   none	
Others		    :                   	                    
*************************************************/
int iic_test(void)
{
	iic_init();
	int i = 998;
	int j = 0;
	
	iic_Tx(0xa0,0,(char*)&i,4);
	iic_Rx(0xa0,0,(char*)&j,4);
	
	uart_printf("\nj = %d\n",j);
}


2、使用 io 模拟

/******************
iic.h
*******************/
#ifndef _IIC_H_
#define  _IIC_H_
#include "def.h"

void iic_init(void);

#define  AT24C08_ADDRDRESS    0xa0

#define  true  1
#define  false   0


#define PAGE1   0xa0
#define PAGE2   0xa2
#define PAGE3   0xa4
#define PAGE4   0xa6

#define  IIC_CLOCK_HIGH           rGPEDAT |= (1<<14)
#define  IIC_CLOCK_LOW            rGPEDAT &= ~(1<<14)

#define  IIC_DATA_HIGH            rGPEDAT |= (1<<15)
#define  IIC_DATA_LOW             rGPEDAT &= ~(1<<15)

#define  SET_IIC_DATA_INPUT       rGPECON &= ~(3<<30)
#define  SET_IIC_DATA_OUTPUT      rGPECON |= (1<<30)


U8  i2c_write(U8  device_address, U8  memory_address , U8 data);

U8  i2c_read(U8  device_address,  U8  memory_address, U8 *data);

U8  i2c_page_read(U8  device_address,  U8  memory_address, U8 *destination,U32 size);

U8  i2c_page_write(U8  device_address, U8 memory_address , U8 *source,U32 size);


U8  i2c_largepage_write(U8  device_address, U8 memory_address , U8 *source,U32 size);


void i2c_test(void);

#endif


/*****************************
iic.c
*****************************/

#include "2440addr.h"
#include "def.h"
#include "uart.h"
#include "iic.h"
//#include "timer.h"

#define   DELAY_DECIMUS_MS  100
extern void Delay_MS( unsigned int time);

void delayus( U32 time)
{
	U32 i,j;
	for ( i=0; i<time; i++)
	{
		  for(j=0;j<DELAY_DECIMUS_MS;j++)
		  {
		  }	
       }	
	    	  
}


void iic_init(void)
{
	 /* config  GPE14, GPE15 as output*/
	 rGPECON &=(~((3<<30)|(3<<28)));
	 rGPECON |=(1<<30)|(1<<28);
	
	/* SDA,SCL 默认为高电平 */
	 rGPEDAT |= ((1<<15)|(1<<14));
	 rGPEUP |= ((1<<15)|(1<<14));
	 delayus(1);
	 	
}	
	/* start */
void i2c_start(void)
{	

	IIC_DATA_HIGH; 
	delayus(1);
	IIC_CLOCK_HIGH;
	delayus(1);
	IIC_DATA_LOW;   
	delayus(1);
	IIC_CLOCK_LOW;
}

void  i2c_stop(void)
{	  
	SET_IIC_DATA_OUTPUT;
	delayus(1);
	IIC_DATA_LOW;	 	  
 	delayus(1);  
	IIC_CLOCK_HIGH;   
	delayus(1);  
	IIC_DATA_HIGH;  	
 	delayus(1);  	 
}	

U8  check_ack(void)
{
	 /* ack */	 
	  U8  ret;	

	 U8 ucErrTime=0; 
	 SET_IIC_DATA_INPUT;
	 delayus(1); 
	 IIC_CLOCK_HIGH; //negative edge clock data out of each device
	  delayus(1);
	
	 while(rGPEDAT&(1<<15))
	  {	
	  	ucErrTime++;      				//时间累加
		ret = false;             
		if(ucErrTime>250)                     //如果时间大于250
		{
			i2c_stop();                         //调用IIC停止子函数
			return ret;                         //程序返回值0
		}
        	
	  }
	 
	   ret = true;
	   
	IIC_CLOCK_LOW; 
	delayus(1);	 
	SET_IIC_DATA_OUTPUT; 
	delayus(1);
	return ret;
}	 

void send_no_ack(void)
{
	  delayus(1);   
	  IIC_CLOCK_LOW;  //positive edge clock data into eachEEPROM 
	  delayus(1); 
	  SET_IIC_DATA_OUTPUT;//发送数据时与上升沿同步
	  IIC_DATA_HIGH;           /* 发送高电平no ack */
	  delayus(2); 
	  IIC_CLOCK_HIGH;
	  delayus(1); 
   	  IIC_CLOCK_LOW;
	  delayus(1);
}	
	


void  data_write(U8 data)
{
	  U8 i;
	  SET_IIC_DATA_OUTPUT; 
	  delayus(1);
	    	  
	  /* data transmit */    
	  for (i = 0; i< 8; i++)
	  {
	  	
	  	if(data&(1<<(7-i)))//发送数据时与上升沿同步
	      {
           	 IIC_DATA_HIGH;
	      }
	      else
	      {
	   	      IIC_DATA_LOW;
	      }  
	       
	      delayus(1);
	      IIC_CLOCK_HIGH ;	  
	      delayus(1);	 
		  IIC_CLOCK_LOW ;
	    	delayus(1);
	  }
	  
	   IIC_DATA_HIGH;
	      delayus(1);	
	// UartPuts(" data write over!\n");
	    
}	


void  data_read(U8  *data )
{
	  U8 i;	
	  
	  IIC_DATA_HIGH;  // free
	  delayus(1); 
	  SET_IIC_DATA_INPUT;
	  delayus(1); 

	  
	  /* data reas */    
	  for (i = 0 ; i< 8; i++)
	  {
	  	
	  	 IIC_CLOCK_LOW;
	    	  delayus(1); 
		IIC_CLOCK_HIGH;	 
	  	 delayus(1);	

		  if(rGPEDAT&(1<<15))//接收数据时与下降沿同步
	  	  {   
	  	      (*data) |=(1<<(7-i)) ;
	  	  }   
		  else
		  {
			(*data) &=~(1<<(7-i)) ;
		  }

	    }
	  
	   IIC_CLOCK_LOW;
	     delayus(1); 
	 SET_IIC_DATA_OUTPUT; 
	//  Uart_Printf("----  %4x \n",*data); 
	  
}	





U8  i2c_write(U8  device_address, U8 memory_address , U8 data)
{
	  U8  write_addr;
	  U8  ack_flag;
	  U8  ret;
	  
	  /* start */
   	 i2c_start();
    	  
	  /* write address transmit */    
    	data_write(device_address);
	  
	  /* ack */	 
	  ack_flag = check_ack();
	  //ack_flag = 0;
	  
	  if(!ack_flag)
	  {
	  	 ret =  false;
	  	 UartPuts(" write  i2c  device address  no  ack!\n");
	  	 goto  i2c_stop;
	  }
	  
	   /* write address transmit */    
   	 data_write(memory_address);
	  
	  /* ack */	 
	  ack_flag = check_ack();
	  
	  if(!ack_flag)
	  {	    
	  	 ret =  false;
	  	 UartPuts(" write  memory  address  no  ack!\n");
	  	 while(1);
	  	 goto  i2c_stop;
	  }	  
	  /* write data transmit */  
	     
    	data_write(data);
	  
	  /* ack */	 
	  ack_flag = check_ack();
	  
	  if(!ack_flag)
	  {
	  	 ret =  false;
	  	 UartPuts(" write  data   no  ack!\n");
	  	 goto  i2c_stop;
	  }
	  else
	  {
	  	 ret =  true;
	  }	
	  	   
i2c_stop:
	 	 i2c_stop();
		  delayus(1000);  //延时等待STOP信号生效(10ms)
	 	 return ret;	
}

U8  i2c_dummy_write(U8  device_address, U8 memory_address )
{
	  U8  write_addr;
	  U8  ack_flag;
	  U8  ret;
	  
	  /* start */
   	 i2c_start();
    	  
	  /* write address transmit */    
   	 data_write(device_address);
	  
	  /* ack */	 
	  ack_flag = check_ack();
	  
	  if(!ack_flag)
	  {
	  	 ret =  false;
	  	 UartPuts(" dummy write  i2c  device address  no  ack!\n");
	  	 goto  i2c_stop;
	  }
	  
	   /* write address transmit */    
    	data_write(memory_address);
	  
	  /* ack */	 
	  ack_flag = check_ack();
	  
	  if(!ack_flag)
	  {	    
	  	 ret =  false;
	  	 UartPuts(" dummy write  memory  address  no  ack!\n");
	  	 goto  i2c_stop;
	  }	  
	  /* write data transmit */  
	    else
	  {
	  	 ret =  true;
		 return ret;	
	  }	
	  	   
i2c_stop:
	 	 i2c_stop();
	 	 return ret;	
}


U8  i2c_read(U8  device_address,  U8  memory_address, U8 *data)
{
	  U8  read_addr;	  	    
	  U8  ack_flag;	  
	  U8  ret;
	  
	  ret = i2c_dummy_write( device_address , memory_address);
	  
	  if(!ret)
	  {
	     ret =  false;
	     return ret; 	 
	  }	
	  
	  i2c_start();
	   
	  read_addr =  device_address |1;
   
   	 data_write(read_addr);
    
    	ack_flag = check_ack();
     
  	  if(!ack_flag)
	  {
	  	 ret =  false;
	  	 UartPuts(" i2c_read write  i2c  device address  no  ack!\n");
	  	 goto  i2c_read_stop;
	  }
	  
	  data_read(data);
	  
	  send_no_ack();	  
	  
	  ret =  true;
		  	  
i2c_read_stop:
	 	 i2c_stop();
	 	 return ret;    
     
}		

U8  i2c_page_read(U8  device_address,  U8  memory_address, U8 *destination,U32 size)
{
	int i;
	for(i=0;i<size;i++)
		i2c_read(device_address,memory_address+i,destination+i);

}
U8  i2c_page_write(U8  device_address, U8 memory_address , U8 *source,U32 size)
{
	int i;
	for(i=0;i<size;i++)
		{
		i2c_write(device_address,memory_address+i,source[i]);
		//Uart_Printf("write %d\n",i);
		}

}

U8  i2c_largepage_write(U8  device_address, U8 memory_address , U8 *source,U32 size)
{
	int i;
	int n,m;
	if(size>256)
		Uart_Printf("Size illegal\n");
	//assert(size<=256);//判断参数合法性
		
	n=size/16;		//写入的小页数
	m=size%16;	  //写入小页后剩余的个数
	for(i=0;i<n;i++)
			i2c_page_write(device_address,(memory_address+16*i),(source+16*i),16);
	for(i=0;i<m;i++)
			i2c_write(device_address,(memory_address+16*n+i),*(source+16*n+i));

}

void i2c_test(void)
{
	  U8 flag;
	  
	  U8  write_data;
	  U8  read_data;
	  U8 i,j;
	  i=1;
	  j=1;
	  
  	
	  UartPuts(" Begin to write!\n");
	
	  for(i=1;i<10;i++,j++)
	  {
	    flag = i2c_write(AT24C08_ADDRDRESS,i,j);
	    
	    if(flag)	
        UartPuts(" write i2c ok!\n");
      else
        UartPuts(" write i2c failed!\n");  
        
        Delay_MS(1000);
          
      flag = i2c_read(AT24C08_ADDRDRESS,i,&read_data);
    
       
       if(flag)
       {    
           Uart_Printf(" read  i2c ok! %4x \n",read_data); 
           //UartPutch(0x30+read_data); 
          //UartPuts(" \n");
          //Uart_Printf("%4x",read_data);
       }    
       else
       {
           UartPuts(" read  i2c failed!\n"); 
       } 
                    
       Delay_MS(500);     
    }    

}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值