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

📄 i2cint.c

📁 I2C在ARM中rlm 的RTX驱动和程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************************************************
调用说明:
 1. 此中函数规定在RTX中使用;
 2. 参数设置除了按配置设置外,不同I2C控制器的引脚分配需另外设定;
 3. 同一个I2C控制器函数只能在同一线程中使用,不同I2C控制器可以在不同线程中使用
*****************************************************************************************************************/

/*
// *** <<< Use Configuration Wizard in Context Menu >>> ***
*/

/*
// Peripheral clock, depends on VPBDIV
// <o> PCLK value <1-1000000000>
*/
#define  PCLK            12000000

/*
// <e>Use I2C Controller0
*/
#define USE_I2C_CTRL0          	 1
/*
// </e>
*/

/*
// <e>Use I2C Controller1
*/
#define USE_I2C_CTRL1            0
/*
// </e>
*/

/*
// <e>Use I2C Controller2
*/
#define USE_I2C_CTRL2            1
/*
// </e>
*/

/*
// *** <<< End of Configuration section             >>> ***
*/


#include <LPC23xx.H> 
#include <RTL.h>
#include "I2CINT.H"

/* 定义用于和I2C中断传递信息的全局变量 */
#if USE_I2C_CTRL0 == 1
volatile U8 	I2C0_sla;			/* I2C器件从地址 					*/
volatile U32	I2C0_suba;			/* I2C器件内部子地址 				*/
volatile U8 	I2C0_suba_num;		/* I2C子地址字节数					*/
volatile U8 	*I2C0_buf;        	/* 数据缓冲区指针  					*/
volatile U32 	I2C0_num;			/* 要读取/写入的数据个数 			*/
volatile U8 	I2C0_suba_en;		/* 	子地址控制。
										0--子地址已经处理或者不需要子地址
										1--读取操作
										2--写操作						*/
OS_SEM wait_end0_sem;				/* 等待I2C0总线结束信号量           */
#endif
#if USE_I2C_CTRL1 == 1
volatile U8 	I2C1_sla;			/* I2C器件从地址 					*/
volatile U32	I2C1_suba;			/* I2C器件内部子地址 				*/
volatile U8 	I2C1_suba_num;		/* I2C子地址字节数					*/
volatile U8 	*I2C1_buf;        	/* 数据缓冲区指针  					*/
volatile U32 	I2C1_num;			/* 要读取/写入的数据个数 			*/
volatile U8 	I2C1_suba_en;		/* 	子地址控制。
										0--子地址已经处理或者不需要子地址
										1--读取操作
										2--写操作						*/
OS_SEM wait_end1_sem;				/* 等待I2C1总线结束信号量           */
#endif
#if USE_I2C_CTRL2 == 1
volatile U8 	I2C2_sla;			/* I2C器件从地址 					*/
volatile U32	I2C2_suba;			/* I2C器件内部子地址 				*/
volatile U8 	I2C2_suba_num;		/* I2C子地址字节数					*/
volatile U8 	*I2C2_buf;        	/* 数据缓冲区指针  					*/
volatile U32 	I2C2_num;			/* 要读取/写入的数据个数 			*/
volatile U8 	I2C2_suba_en;		/* 	子地址控制。
										0--子地址已经处理或者不需要子地址
										1--读取操作
										2--写操作						*/
OS_SEM wait_end2_sem;				/* 等待I2C2总线结束信号量           */
#endif


/****************************************************************************************************************
* 函数名称:I2C_Init
* 函数功能:初始化I2C接口
* 入口参数:channel 	通道 : 0--I2C0  1--I2C1  2--I2C2
			mode 		工作模式: 0--从模式 1--主模式
			fi2c		通信速率 0~400000(如果高于400kHz ,强制设为400kHz,如果设置为从机,参数无效)
			adr			从地址。(当在主模式下,该参数无效,可随意设置)
			prio		I2C中断优先级(0~15)
*           
* 出口参数:1			操作成功
			0			操作失败
*****************************************************************************************************************/
U8 	I2C_Init(U8 channel,U8 mode,U32 fi2c,U8 adr,U8 prio)
{
	BIT init_ok_flag = __FALSE;
	if(mode != 0 && mode != 1)return __FALSE ;
	if(fi2c > 400000) fi2c = 400000;
	switch(channel)
	{
		case 0:									// Enable clock for I2C0               
			#if USE_I2C_CTRL0 == 1 
			PCONP   |= 1 << 7; 		
			PINSEL1 &= 0XFC3FFFFF;				//P0.27 P0.28
			PINSEL1 |= 0X01400000; 
			VICIntSelect = ~(1 << 9);   		//IRQ中断
			if(prio > 15)VICVectPriority9 = 15;
			else VICVectPriority9 = prio;
			VICVectAddr9 = (U32)IRQ_I2C;		//设置中断服务地址
			VICIntEnable = 1 << 9;				//使能I2C0中断
			if(mode == 1)					   	//设置为主模式
			{
				I20SCLH = (PCLK / fi2c) / 2;	//设置I2C时钟
				I20SCLL = (PCLK / fi2c) / 2; 
				I20CONCLR = 0X2C;
				I20CONSET = 0X40;				//使能主I2C 
			}
			else 								//设置为从模式
			{
				I20ADR = adr & 0XFE;			//设置从机地址
				I20CONSET = 0X44;				//使能从I2C 
				I20CONCLR = 0X28;
			}
			os_sem_init (wait_end0_sem, 0);		//初始化I2C0等待信号量
			init_ok_flag = __TRUE;
			#endif
			break;
		case 1:
			#if USE_I2C_CTRL1 == 1
			PCONP   |= 1 << 19; 				// Enable clock for I2C1               	
			PINSEL1 &= 0XFFFFFC3F;				//P0.19 P0.20
			PINSEL1 |= 0X000003C0;
			VICIntSelect = ~(1 << 19);  		//IRQ中断
			if(prio > 15)VICVectPriority19 = 15;
			else VICVectPriority19 = prio;	 
			VICVectAddr19 = (U32)IRQ_I2C;	    //设置中断服务地址 
			VICIntEnable = 1 << 19;				//使能I2C1中断 	
			if(mode == 1)					   	//设置为主模式
			{
				I21SCLH = (PCLK / fi2c) / 2;	//设置I2C时钟
				I21SCLL = (PCLK / fi2c) / 2; 
				I21CONCLR = 0X2C;
				I21CONSET = 0X40;				//使能主I2C 
			}
			else 								//设置为从模式
			{
				I21ADR = adr & 0XFE;			//设置从机地址
				I21CONSET = 0X44;				//使能从I2C 
				I21CONCLR = 0X28;
			}
			os_sem_init (wait_end1_sem, 0);		//初始化I2C1等待信号量
			init_ok_flag = __TRUE;
			#endif
			break;
		case 2:
			#if USE_I2C_CTRL2 == 1
			PCONP   |= 1 << 26; 				// Enable clock for I2C2               	
			PINSEL0 &= 0XFF0FFFFF;				//P0.10 P0.11
			PINSEL0 |= 0X00A00000;
			VICIntSelect = ~(1 << 30);  		//IRQ中断
			if(prio > 15)VICVectPriority30 = 15;
			else VICVectPriority30 = prio;
			VICVectAddr30 = (U32)IRQ_I2C;		//设置中断服务地址中断
			VICIntEnable = 1 << 30;				//使能I2C2中断
			if(mode == 1)					   	//设置为主模式
			{
				I22SCLH = (PCLK / fi2c) / 2;	//设置I2C时钟
				I22SCLL = (PCLK / fi2c) / 2; 
				I22CONCLR = 0X2C;
				I22CONSET = 0X40;				//使能主I2C 
			}
			else 								//设置为从模式
			{
				I22ADR = adr & 0XFE;			//设置从机地址
				I22CONSET = 0X44;				//使能从I2C 
				I22CONCLR = 0X28;
			}
			os_sem_init (wait_end2_sem, 0);		//初始化I2C2等待信号量
			init_ok_flag = __TRUE;
			#endif
			break;
	}
	if(init_ok_flag == __TRUE)return __TRUE;
   	else return  __FALSE ;
}  


/*
**********************************************************************************************************
** 函数名称:ISendByte
** 函数功能:向无子地址器件发送1字节数据。
** 入口参数:channel 	通道 : 0--I2C0  1--I2C1  2--I2C2
			 sla		器件地址
**           dat		要发送的数据
**           timeout	等待时间(以系统时间衡量)		
** 出口参数:返回值为0时表示出错,为1时表示操作正确。
** 说明:	使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
*********************************************************************************************************
*/
U8  ISendByte(U8 channel, U8 sla, U8 dat, U16 timeout)
{  
	switch(channel)
	{
	 	case 0:							//I2C0
			#if USE_I2C_CTRL0 == 1 
		   	I2C0_sla     = sla;			// 写操作的器件地址
		   	I2C0_buf     = &dat;		// 待发送的数据
		   	I2C0_num     = 1;			// 发送1字节数据
		   	I2C0_suba_en = 0;		 	// 无子地址
		   	while(os_sem_wait (wait_end0_sem, 0) == OS_R_OK); 	//清令牌数
		   
		   	I20CONCLR = 0x2C;
		   	I20CONSET = 0x60;           // 设置为主机,并启动总线

			if(os_sem_wait (wait_end0_sem, timeout) != OS_R_TMO)return __TRUE;
			#endif
	   		break;
	   	case 1:							//I2C1
		   	#if USE_I2C_CTRL1 == 1
			I2C1_sla     = sla;			// 写操作的器件地址
		   	I2C1_buf     = &dat;		// 待发送的数据
		   	I2C1_num     = 1;			// 发送1字节数据
		   	I2C1_suba_en = 0;		 	// 无子地址
		   	while(os_sem_wait (wait_end1_sem, 0) == OS_R_OK); 	//清令牌数
		   
		   	I21CONCLR = 0x2C;
		   	I21CONSET = 0x60;           // 设置为主机,并启动总线
			
			if(os_sem_wait (wait_end1_sem, timeout) != OS_R_TMO)return __TRUE;
	   		#endif
			break;
		case 2:							//I2C2
		   	#if USE_I2C_CTRL2 == 1
			I2C2_sla     = sla;			// 写操作的器件地址
		   	I2C2_buf     = &dat;		// 待发送的数据
		   	I2C2_num     = 1;			// 发送1字节数据
		   	I2C2_suba_en = 0;		 	// 无子地址
		   	while(os_sem_wait (wait_end2_sem, 0) == OS_R_OK); 	//清令牌数
		   
		   	I22CONCLR = 0x2C;
		   	I22CONSET = 0x60;           // 设置为主机,并启动总线

			if(os_sem_wait (wait_end2_sem, timeout) != OS_R_TMO)return __TRUE;
	   		#endif
			break;
	}
	return __FALSE;
}

/*
*********************************************************************************************************
** 函数名称:IRcvByte
** 函数功能:向无子地址器件读取1字节数据。
** 入口参数:channel 	通道 : 0--I2C0  1--I2C1  2--I2C2
**			 sla		器件地址
**           dat		接收数据的变量指针
**			 timeout	等待时间(以系统时间衡量)
** 出口参数:返回值为0时表示操作出错,为1时表示操作正确。
** 说    明:使用前要初始化好I2C引脚功能和I2C中断,并已使能I2C主模式
*********************************************************************************************************
*/
U8  IRcvByte(U8 channel, U8 sla, U8 *dat, U16 timeout)
{  
	switch(channel)
	{
		case 0:
			#if USE_I2C_CTRL0 == 1 
   			I2C0_sla     = sla+1;		// 读操作的器件地址
   			I2C0_buf     = dat;
  			I2C0_num     = 1;
   			I2C0_suba_en = 0;			// 无子地址
   			while(os_sem_wait (wait_end0_sem, 0) == OS_R_OK); 	//清令牌数
   
   			I20CONCLR = 0x2C;
   			I20CONSET = 0x60;         // 设置为主机,并启动总线

			if(os_sem_wait (wait_end0_sem, timeout) != OS_R_TMO)return __TRUE;
			#endif
			break;
		case 1:
			#if USE_I2C_CTRL1 == 1 
			I2C1_sla     = sla+1;		// 读操作的器件地址
   			I2C1_buf     = dat;
  			I2C1_num     = 1;
   			I2C1_suba_en = 0;			// 无子地址
   			while(os_sem_wait (wait_end1_sem, 0) == OS_R_OK); 	//清令牌数
   
   			I21CONCLR = 0x2C;
   			I21CONSET = 0x60;         // 设置为主机,并启动总线

			if(os_sem_wait (wait_end1_sem, timeout) != OS_R_TMO)return __TRUE;
			#endif
			break;
		case 2:
			#if USE_I2C_CTRL2 == 1
			I2C2_sla     = sla+1;		// 读操作的器件地址
   			I2C2_buf     = dat;
  			I2C2_num     = 1;
   			I2C2_suba_en = 0;			// 无子地址
   			while(os_sem_wait (wait_end2_sem, 0) == OS_R_OK); 	//清令牌数
   
   			I22CONCLR = 0x2C;
   			I22CONSET = 0x60;         // 设置为主机,并启动总线

			if(os_sem_wait (wait_end2_sem, timeout) != OS_R_TMO)return __TRUE;
			#endif
			break;
	}
	return __FALSE;
}


/*
*********************************************************************************************************
** 函数名称 :I2C_ReadNByte
** 函数功能 :从有子地址器件任意地址开始读取N字节数据
** 入口参数 :	channel 	通道 : 0--I2C0  1--I2C1  2--I2C2
**				sla			器件从地址
**				suba_type	子地址结构	1-单字节地址	2-8+X结构	2-双字节地址
**				suba		器件子地址
**				s			数据接收缓冲区指针
**				num			读取的个数
**				timeout		等待时间(以系统时间衡量)
** 出口参数 :	TRUE		操作成功
**				FALSE		操作失败
*********************************************************************************************************

⌨️ 快捷键说明

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