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

📄 i2cint.c

📁 ARM7通用串行口的开发程序
💻 C
字号:
#define IN_I2C
#include "config.h"


static OS_EVENT     *I2C_Sem;
static OS_EVENT     *I2C_Mbox;
static volatile     uint8 	I2C_sla;			/* I2C器件从地址 					*/
static volatile     uint32	I2C_suba;			/* I2C器件内部子地址 				*/
static volatile     uint8 	I2C_suba_num;		/* I2C子地址字节数					*/
static volatile     uint8   *I2C_buf;        	/* 数据缓冲区指针  					*/
static volatile     uint32  I2C_num;			/* 要读取/写入的数据个数 			*/
static volatile     uint8 	I2C_end;			/* I2C总线结束标志:结束总线是置1 	*/
static volatile     uint8 	I2C_suba_en;		/* 子地址控制。
										           0--子地址已经处理或者不需要子地址
										           1--读取操作
										           2--写操作
									            */
									
#define I2C_WRITE_END       1           /* 写完成   */
#define I2C_READ_END        2           /* 读完成   */
#define I2C_NOT_GET_BUS     4           /* 丢失仲裁 */
#define I2C_ACK_ERR         8           /* 接收ACK错误 */

//uint8 I2C_Buf[256];


uint8 I2C_Init(uint32 Fi2c)
{
    VICIntEnClr = 1 << 9;                               // 禁止能I2C_中断 
    if (Fi2c <= 400000)
    {
        PINSEL0 = (PINSEL0 & 0xffffff0f) | 0x50;        // 选择管脚为I2C
        I2CONCLR = 0x6C;                                // 清除控制寄存器
        I2SCLH = (Fpclk / Fi2c + 1) / 2;                // 设置高电平时间
        I2SCLL = (Fpclk / Fi2c) / 2;                    // 设置低电平时间
        I2C_Sem = OSSemCreate(1);                       // 信号量用于互斥操作总线 
        I2C_Mbox = OSMboxCreate(NULL);                  // 消息邮箱用于中断向任务传递操作结果
        if (I2C_Mbox == NULL)
        {
            return FALSE;
        }
        if (I2C_Sem != NULL)
        {
            return TRUE;
        }
    }
    return FALSE;
}


uint8  I2C_ISendByte(uint8 sla, uint8 dat)
{   uint8 err;
 
    OSSemPend(I2C_Sem, 0, &err);
    
    I2C_sla     = sla;		    // 写操作的器件地址
    I2C_buf     = &dat;		    // 待发送的数据
    I2C_num     = 1;			// 发送1字节数据
    I2C_suba_en = 0;		 	// 无子地址
    I2C_end     = 0;
   
    I2CONCLR = 0x2C;
    I2CONSET = 0x60;            // 设置为主机,并启动总线
   
    while(0 == I2C_end);
    if(1 == I2C_end) 
    {
        OSSemPost(I2C_Sem);
        return TRUE;
    }
    else 
    {
        OSSemPost(I2C_Sem);
        return FALSE;
    }
}

uint8  I2C_IRcvByte(uint8 sla, uint8 *dat)
{   uint8 err;

    OSSemPend(I2C_Sem, 0, &err);
    
    I2C_sla     = sla+1;        // 读操作的器件地址
    I2C_buf     = dat;
    I2C_num     = 1;
    I2C_suba_en = 0;            // 无子地址
    I2C_end     = 0;
   
    I2CONCLR = 0x2C;
    I2CONSET = 0x60;            // 设置为主机,并启动总线
   
    while(0 == I2C_end);
    if(1 == I2C_end) 
    {
        OSSemPost(I2C_Sem);
        return TRUE;
    }
    else 
    {
        OSSemPost(I2C_Sem);
        return FALSE;
    }
}



uint8 I2C_ReadNByte (uint8 sla, uint32 suba_type, uint32 suba, uint8 *s, uint32 num)
{   uint8 err;

	if (num > 0)	/* 判断num个数的合法性 */
	{	/* 参数设置 */
        OSSemPend(I2C_Sem, 0, &err);
	
		if (suba_type == 1)
		{	/* 子地址为单字节 */
			I2C_sla     	= sla + 1;							/* 读器件的从地址,R=1 	*/
			I2C_suba    	= suba;								/* 器件子地址 			*/
			I2C_suba_num	= 1;								/* 器件子地址为1字节 	*/
		}
		if (suba_type == 2)
		{	/* 子地址为2字节 */
			I2C_sla     	= sla + 1;							/* 读器件的从地址,R=1 	*/
			I2C_suba   	 	= suba;								/* 器件子地址 			*/
			I2C_suba_num	= 2;								/* 器件子地址为2字节 	*/
		}
		if (suba_type == 3)
		{	/* 子地址结构为8+X*/
			I2C_sla			= sla + ((suba >> 7 )& 0x0e) + 1;	/* 读器件的从地址,R=1	*/
			I2C_suba		= suba & 0x0ff;						/* 器件子地址	 		*/
			I2C_suba_num	= 1;								/* 器件子地址为8+x	 	*/
		}
		I2C_buf     = s;										/* 数据接收缓冲区指针 	*/
		I2C_num     = num;										/* 要读取的个数 		*/
		I2C_suba_en = 1;										/* 有子地址读 			*/
		I2C_end     = 0;
		

        I2CONCLR = (1 << 6)|                                // 清除控制寄存器
                   (1 << 5)|
                   (1 << 3)|
                   (1 << 2);
                   
        I2CONSET = (1 << 6)|                                // 设置为主模式,启动总线
                   (1 << 5)|
                   (1 << 2);
        VICIntEnable = 1 << 9;
        
        OSMboxPend(I2C_Mbox, 0, &err);	
        
        VICIntEnClr = 1 << 9;
        
        OSSemPost(I2C_Sem);
        return TRUE;
	}
    else 
    {
        return FALSE;
    }
}


uint8 I2C_WriteNByte(uint8 sla, uint8 suba_type, uint32 suba, uint8 *s, uint32 num)
{   uint8 err;
    
	if (num > 0)/* 如果读取的个数为0,则返回错误 */
	{   OSSemPend(I2C_Sem, 0, &err);
	
		if (suba_type == 1)
		{	/* 子地址为单字节 */
			I2C_sla     	= sla;								/* 读器件的从地址	 	*/
			I2C_suba    	= suba;								/* 器件子地址 			*/
			I2C_suba_num	= 1;								/* 器件子地址为1字节 	*/
		}
		if (suba_type == 2)
		{	/* 子地址为2字节 */
			I2C_sla     	= sla;								/* 读器件的从地址 		*/
			I2C_suba   	 	= suba;								/* 器件子地址 			*/
			I2C_suba_num	= 2;								/* 器件子地址为2字节 	*/
		}
		if (suba_type == 3)
		{	/* 子地址结构为8+X */
			I2C_sla			= sla + ((suba >> 7 )& 0x0e);		/* 读器件的从地址		*/
			I2C_suba		= suba & 0x0ff;						/* 器件子地址			*/
			I2C_suba_num	= 1;								/* 器件子地址为8+X	 	*/
		}

		I2C_buf     = s;										/* 数据 				*/
		I2C_num     = num;										/* 数据个数 			*/
		I2C_suba_en = 2;										/* 有子地址,写操作 	*/
		I2C_end     = 0;
		
		I2CONCLR = (1 << 6)|                                // 清除控制寄存器
                   (1 << 5)|
                   (1 << 3)|
                   (1 << 2);
                   
        I2CONSET = (1 << 6)|                                // 设置为主模式,启动总线
                   (1 << 5)|
                   (1 << 2);
        VICIntEnable = 1 << 9;
        
        OSMboxPend(I2C_Mbox, 0, &err);	
        
        VICIntEnClr = 1 << 9;
        
        OSSemPost(I2C_Sem);
        return TRUE;
	}
    else 
    {
        return FALSE;
    }
}




void I2C_Exception(void)
{
    OS_ENTER_CRITICAL();

    switch (I2STAT & 0xf8)
	{	// I2C总线已启动,准备发送从地址。
        case 0x08:
		 	if(I2C_suba_en == 1)                        // 指定子地址读
		 	{	
		 	    I2DAT = I2C_sla & 0xfe;                 // 先写入地址
		 	}
            else
            {  	
                I2DAT = I2C_sla;                 // 否则直接发送从机地址
            }
            I2CONSET = (1 << 2);                        // AA  = 1 
            I2CONCLR = (1 << 3);                        // SI  = 0
            break;
            
        // 已发送重复起始条件   
       	case 0x10:	
       		I2DAT = I2C_sla;							// 重起总线后,重发从地址
            I2CONSET = (1 << 2);                        // AA  = 1 
            I2CONCLR = (1 << 3);                        // SI  = 0
       		break;
       		
        // 已发送I2DAT中的数据,已接收ACK
		case 0x18:
       	case 0x28:	
       	    // 若是无子地址读
       		if (I2C_suba_en == 0)                       // 若是指定地址读,则重新启动总线
       		{
	       		if (I2C_num > 0)
	       		{	
	       		    I2DAT = *I2C_buf++;
                    I2CONSET = (1 << 2);                // AA  = 1 
                    I2CONCLR = (1 << 3);                // SI  = 0 		
	       			I2C_num--;
	       		}
	       		// 没有数据发送,则发送停止总线标志
	       		else	                                
	       		{		                               
	       		    I2CONSET = (1 << 2)|                // AA  = 1 
	       		               (1 << 4);                // STO = 1
                    I2CONCLR = (1 << 3);                // SI  = 0
	       		  	I2C_end = 1;						// 指示总线停止
	       		  	OSMboxPost(I2C_Mbox, (void *)I2C_WRITE_END);
	       		    VICIntEnClr = 1 << 9;
	       		}
       		}
       		// 若是指定子地址读,则重新启动总线
            if(I2C_suba_en == 1)
            { 
            	if (I2C_suba_num == 2)
            	{
            	    I2DAT = ((I2C_suba >> 8) & 0xff);
	       			I2CONSET = (1 << 2);                // AA  = 1 
                    I2CONCLR = (1 << 3)|                // SI  = 0
                               (1 << 5);                // STA = 0
	       			I2C_suba_num--;
	       			break;	
	       		} 
	       		
	       		if(I2C_suba_num == 1)
	       		{	
	       		    I2DAT = (I2C_suba & 0xff);
	       			I2CONSET = (1 << 2);                // AA  = 1 
                    I2CONCLR = (1 << 3)|                // SI  = 0
                               (1 << 5);                // STA = 0
	       			I2C_suba_num--;
	       			break;	
	       		}
	       		
            	if (I2C_suba_num == 0)
            	{	
                    I2CONSET = (1 << 5);                // STA = 1
                    I2CONCLR = (1 << 3);                // SI  = 0
               		I2C_suba_en = 0;  
               		break;
               	}
            }
            // 指定子地址写,子地址尚未指定,则发送子地址
            if (I2C_suba_en == 2)
       		{
       		 	if (I2C_suba_num > 0)
            	{	if (I2C_suba_num == 2)
            		{	
            		    I2DAT = ((I2C_suba >> 8) & 0xff);
	       			    I2CONSET = (1 << 2);            // AA  = 1 
                        I2CONCLR = (1 << 3)|            // SI  = 0
                                   (1 << 5);            // STA = 0
            			I2C_suba_num--;
            			break;
            		}
            		if (I2C_suba_num == 1)
            		{	
            		    I2DAT    = (I2C_suba & 0xff);
            		    I2CONSET = (1 << 2);            // AA  = 1 
                        I2CONCLR = (1 << 3)|            // SI  = 0
                                   (1 << 5);            // STA = 0
               			I2C_suba_num--;
               			I2C_suba_en  = 0;
               			break;
               		}
               	}
             }
       		break;
       		
       		
        // 已发送SLA+R;已接收ACK
       case 0x40:	
       		if (I2C_num <= 1)		
       		{	
       		    I2CONCLR = (1 << 2);                    // AA  = 0 
       		}
       		else
       		{ 	
       		    I2CONSET = (1 << 2);                    // AA  = 1 
       		}
            I2CONCLR = (1 << 3)|                        // SI  = 0
                       (1 << 5);                        // STA = 0   不能删除,因为STA不能自动清除
       		break;
       		
       		
        // 总线发生异常
       	case 0x20:	// 已发送SLA+W,已接收非应答
       	case 0x30:	// 已发送I2DAT中的数据,已接收非应答
       	case 0x38:	// 在SLA+R/W或数据字节中丢失仲裁
   		case 0x48:	// 已发送SLA+R,已接收非应答
	        I2CONSET = (1 << 2)|                        // AA  = 1 
                       (1 << 4);                        // STO = 1
            I2CONCLR = (1 << 3);                        // SI  = 0
            I2C_end = 0xff;                             // 异常,总线停止
            OSMboxPost(I2C_Mbox, (void *)I2C_ACK_ERR);
            VICIntEnClr = 1 << 9;
       		break;   				
	
	
        // 已接收数据字节,已返回ACK
		case 0x50:	
			*I2C_buf++ = I2DAT;
			I2C_num--;
			if (I2C_num == 1)                           // 接收最后一个字节
			{  	
			    I2CONCLR = (1 << 2)|                    // AA  = 0
                           (1 << 3);                    // SI  = 0
			}
			else
			{  	 
			    I2CONSET = (1 << 2);                    // AA  = 1 
                I2CONCLR = (1 << 3);                    // SI  = 0
			}
			break;
			
			
        // 已接收数据字节,已返回非应答
		case 0x58:	
			*I2C_buf++ = I2DAT;                         // 读取最后一字节数据
	        I2CONSET = (1 << 2)|                        // AA  = 1 
                       (1 << 4);                        // STO = 1
            I2CONCLR = (1 << 3);                        // SI  = 0
            I2C_end = 1; 
            OSMboxPost(I2C_Mbox, (void *)I2C_READ_END);
            VICIntEnClr = 1 << 9;
            break;
            
      	default:
            //I2CONCLR = 0x28;                            // 清除标志
      		break;
	}
    VICVectAddr = 0x00;		

    OS_EXIT_CRITICAL();
}
/*********************************************************************************************************
**                            End Of File
********************************************************************************************************/

⌨️ 快捷键说明

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