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

📄 i2c.c

📁 周立功PXA270教学实验箱的ARM汇编指令实验2
💻 C
字号:
/****************************************Copyright (c)**************************************************
**                               Guangzhou ZHIYUAN electronics Co.,LTD.
**                                     
**                                 http://www.zyinside.com
**
**--------------File Info-------------------------------------------------------------------------------
** File Name: I2C.c
** Last modified Date: 2006-09-20
** Last Version: v1.0
** Description: PXA270的I2C软件包
**              查询控制方式
**------------------------------------------------------------------------------------------------------
** Created By: 黄绍斌
** Created date: 2006-09-20
** Version: v1.0
** Descriptions:
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
********************************************************************************************************/
#define  IN_I2C
#include  "config.h"


// I2C总线设置宏定义
#define	  BPS_100K		(0<<15)		/* 即ICR_FM位 */
#define	  BPS_400K		(1<<15)

#define   WAIT_MAX		900000		/* 等待最长时间 */



/*********************************************************************************************************
** Function name: InitI2C
** Descriptions: 初始化总线,设置为100KHz总线速率。此函数只需调用一次。
**               (PXA270的I2C支持100KHz和400KHz两种,由ICR的FM位控制)
** Input: 无
** Output: 无
** Created by: 黄绍斌
** Created Date: 2006-09-20
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void  InitI2C(void)
{  	
	uint32  i;
	
	// 使能I2C单元的时钟源
	CKEN = CKEN | (1<<14);
	for(i=0; i<3000; i++);

    // 设置管脚连接GP117(SCL)、GP118(SDA)  
    GPSR3 = (0x03 << (117-96));
    GPDR3 = GPDR3 | (0x03<<(117-96)); 
    GAFR3_U = (GAFR3_U & (~(0x0F<<10))) | 
                           (0x05<<10); 
    
    // I2C寄存器设置
    ISAR = 0x18;						// 设置从方式时的从机地址(没有特定意义的值)
    ICR = ICR_UR | BPS_100K;			// ICR_UR=1,复位I2C单元。I2C总线速度设置为100KHz。同时清0其它位
    ISR = 0x7FF;						// 清0所有状态标志位(写1时清0)
    
    ICR = ICR & (~ICR_UR);				// ICR_UR=0 (所有I2C中断被禁止)
    ICR = ICR | ICR_GCD | ICR_SCLE;		// 允许SCL时钟输出 (禁止全局传呼)
    ICR = ICR | ICR_IUE;				// 使能I2C单元 (仅使用ICR的STOP位发送I2C结束信号)
    for(i=0; i<500; i++);                                      
}



/*********************************************************************************************************
** Function name: StartI2C
** Descriptions: 启动总线,发送从机地址,并发送从机地址
** Input: sla		从机动地址
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Note: sla位最低位为读写控制位
** Created by: 黄绍斌
** Created Date: 2006-09-20
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int  StartI2C(uint8 sla)
{	   
	uint32  i;
	
	ISR = ISR | ISR_ALD | ISR_ITE;   	// 清0标志位ISR_ITE和ISR_ALD(总线仲裁失败)  
	
	IDBR = sla;							// 设置从机地址					
	ICR = ICR | ICR_START | ICR_TB;		// ICR_START=1,ICR_TB=1,启动总线并发送从机地址		
      
    // 等待操作完成 (有超时退出功能)
    i = 0;
    while((ISR & ISR_ITE) == 0)
    {    	
    	if((++i) > WAIT_MAX) 
    	{   
		    ICR = ICR & (~ICR_START);	// ICR_START=0	
		    return(FALSE);
    	}
    }         
    ICR = ICR & (~ICR_START);			// ICR_START=0
    
    // 判断操作是否成功 (从机应答/总线仲载)
   	if((ISR & (ISR_ACKNAK | ISR_ALD)) == 0)
   	{  	
        return(TRUE);     		
   	}   	  	
   	else
   	{
   		return(FALSE);     
   	}   
}		    
	
	

/*********************************************************************************************************
** Function name: I2C_SendByte
** Descriptions: 发送一字节数据,并接收应答位
** Input: dat		要发送的数据
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Created by: 黄绍斌
** Created Date: 2006-09-20 
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int  I2C_SendByte(uint8 dat)
{	
	uint32  i;
	
	ISR = ISR | ISR_ALD | ISR_ITE;   	// 清0标志位ISR_ITE和ISR_ALD(总线仲裁失败) 
	
	IDBR = dat;							// 将数据写入I2C数据寄存器
	ICR = ICR | ICR_TB;					// ICR_TB=1,允许发送数据操作	
    
    // 等待操作完成
    i = 0;
    while((ISR & ISR_ITE) == 0)
    {    	
    	if((++i) > WAIT_MAX) 
    	{   
		    return(FALSE);
    	}
    }     
    
    // 判断操作是否成功 (从机应答/总线仲载)
   	if((ISR & (ISR_ACKNAK | ISR_ALD)) == 0)
   	{  	
        return(TRUE);     		
   	}   	  	
   	else
   	{
   		return(FALSE);     
   	}
}



/*********************************************************************************************************
** Function name: I2C_SendByte_Stop
** Descriptions: 发送一字节数据,并接收应答位,然后产生结束总线信号
** Input: dat		要发送的数据
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Created by: 黄绍斌
** Created Date: 2006-09-20 
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int  I2C_SendByte_Stop(uint8 dat)
{	
	uint32  i;
	
	ISR = ISR | ISR_ALD | ISR_ITE;   	// 清0标志位ISR_ITE和ISR_ALD(总线仲裁失败) 
	
	IDBR = dat;							// 将数据写入I2C数据寄存器
	ICR = ICR | ICR_TB | ICR_STOP;		// ICR_STOP=1,发送完最后一字节数据后发送结束总线信号
    
    // 等待操作完成
    i = 0;
    while((ISR & ISR_ITE) == 0)
    {    	
    	if((++i) > WAIT_MAX) 
    	{   
    		ICR = ICR & (~ICR_STOP);	// ICR_STOP=0	
		    return(FALSE);
    	}
    }
    ICR = ICR & (~ICR_STOP);	// ICR_STOP=0	     
    
    // 判断操作是否成功 (从机应答/总线仲载)
   	if((ISR & (ISR_ACKNAK | ISR_ALD)) == 0)
   	{  	
        return(TRUE);     		
   	}   	  	
   	else
   	{
   		return(FALSE);     
   	}
}



/*********************************************************************************************************
** Function name: I2C_RcvByteNA_Stop
** Descriptions: 接上I2C总线上一字节数据,并发送非应答位,然后产生结束总线信号
** Input: dat		用于接收数据的指针
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Created by: 黄绍斌
** Created Date: 2006-09-20
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int  I2C_RcvByteNA_Stop(uint8 *dat)
{		
	uint32  i;
	
	ISR = ISR | ISR_ALD | ISR_IRF;   	// 清0标志位ISR_IRF和ISR_ALD(总线仲裁失败) 
	
	// 允许接收数据
	ICR = ICR | ICR_ACKNAK | ICR_STOP;	// ICR_STOP=1,接收完最后一字节数据后发送结束总线信号
	ICR = ICR | ICR_TB;	
	
	// 等待接收数据操作完成
	i = 0;
    while((ISR & ISR_IRF) == 0)
    {    	
    	if((++i) > WAIT_MAX) 
    	{   
    		ICR = ICR & (~ICR_STOP);	// ICR_STOP=0	
		    return(FALSE);
    	}
    } 
    ICR = ICR & (~ICR_STOP);			// ICR_STOP=0	        
    
    // 判断操作是否成功 (总线仲裁)
   	if((ISR & ISR_ALD) == 0)   	
   	{  			
		*dat = IDBR;	// 读取数据	
		return(TRUE);  
   	}
   	else
   	{
   		return(FALSE);
   	}   		 	
}



/*********************************************************************************************************
** Function name: I2C_RcvByteA
** Descriptions: 接上I2C总线上一字节数据,并发送应答位
** Input: dat		用于接收数据的指针
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Created by: 黄绍斌
** Created Date: 2006-09-20 
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int  I2C_RcvByteA(uint8 *dat)
{	
	uint32  i;	
	
	ISR = ISR | ISR_ALD | ISR_IRF;   	// 清0标志位ISR_IRF和ISR_ALD(总线仲裁失败) 
	
   	// 允许接收数据
	ICR = ICR & (~ICR_ACKNAK);	
	ICR = ICR | ICR_TB;	
	
	// 等待接收数据操作完成
	i = 0;
    while((ISR & ISR_IRF) == 0)
    {    	
    	if((++i) > WAIT_MAX) 
    	{       		
		    return(FALSE);
    	}
    }   
    
    // 判断操作是否成功 (总线仲裁)
   	if((ISR & ISR_ALD) == 0)   	
   	{  			
		*dat = IDBR;	// 读取数据	
		return(TRUE);  
   	}
   	else
   	{
   		return(FALSE);
   	}   	   	
}






/*********************************************************************************************************
** Function name: ISendStr
** Descriptions: 使用硬件I2C发送数据。
** Input: sla		从机地址
**		  suba	    器件子地址(第一字节用来表示子地址字节个数)
**		  s		    发送数据缓冲区
**		  no		发送数据个数
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Note: 使用前设置好参数。程序不会更改s、suba缓冲区的数据
** Created by: 黄绍斌
** Created Date: 2006-09-20 
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int  ISendStr(uint8 sla, uint8 *suba, uint8 *s, uint8 no)
{	
    int  bak;

	sla = sla & 0xFE;
	if(!StartI2C(sla)) 
	{	 
	    if(!StartI2C(sla)) return(FALSE); 		// 启动总线,发送从机地址
	}
	
	// 发送器件子地址
	bak = *suba++;
	for(; bak>0; bak--)
	{	
	    if(!I2C_SendByte(*suba++)) return(FALSE);
	}
	
	// 发送数据
	for(; no>1; no--)
	{	
	    if(!I2C_SendByte(*s)) return(FALSE); 
		s++;
	} 
	
	if(!I2C_SendByte_Stop(*s)) return(FALSE); 	// 结束总线
	
	return(TRUE);
}



/*********************************************************************************************************
** Function name: IRcvStr
** Descriptions: 使用硬件I2C读取数据。
** Input: sla		从机地址
*		  suba	    器件子地址缓冲区指针(第一字节用来表示子地址字节个数)
*		  s		    接收数据缓冲区
*		  no		接收数据个数
** Output: 操作成功返回TRUE,仲载失败/无从机应答返回FALSE
** Note: 使用前设置好参数。程序不会更改suba缓冲区的数据
** Created by: 黄绍斌
** Created Date: 2006-09-20
**-------------------------------------------------------------------------------------------------------
** Modified by:
** Modified Date: 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int  IRcvStr(uint8 sla,uint8 *suba,uint8 *s,uint8 no)
{  	
    int  bak;

	bak = *suba++;	// 子地址个数
	if(bak > 0)
	{	
	    sla = sla & 0xFE;
		if(!StartI2C(sla)) 
		{	 
		    if(!StartI2C(sla)) return(FALSE);	// 启动总线,发送从机地址(写)
		}
	
		// 发送器件子地址	
		for(; bak>0; bak--)
		{	
		    if(!I2C_SendByte(*suba++)) return(FALSE);
		}
	}
	
	// 重启总线
	sla = sla | 0x01;
	if(!StartI2C(sla)) return(FALSE);			// 启动总线,发送从机地址(读)
	
	// 读取数据	
	for(; no>1; no--)
	{	
	    if(!I2C_RcvByteA(s)) return(FALSE); 	// 发送数据
		s++;
	}	
	if(!I2C_RcvByteNA_Stop(s)) return(FALSE); 	// 结束总线	
		
	return(TRUE);
}

/*********************************************************************************************************
**                            End Of File
********************************************************************************************************/

⌨️ 快捷键说明

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