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

📄 i2c.c

📁 Lpc2214读写EEPROM到某一指定的存储空间
💻 C
字号:

#include "config.h"

#define I2c_Num		(*((volatile uint16 *) (Psram_BaseAddr+0x100)))
#define I2c_Addr	(*((volatile uint8  *) (Psram_BaseAddr+0x102)))
#define I2C_end		(*((volatile uint8  *) (Psram_BaseAddr+0x103)))	//操作结束标志

volatile uint8 *I2c_Buf;
I2C_Param *I2C_Pa;

#define I2C_WRITE_END       1           /* 写完成   */
#define I2C_READ_END        2           /* 读完成   */
#define I2C_NOT_GET_BUS     4           /* 丢失仲裁 */
#define I2C_ACK_ERR         8           /* 接收ACK错误 */

/*********************************************************************************************************
** 函数名称: I2cInit
** 功能描述: 初始化I2c(主模式)
** 输 入: FI2c:I2c总线频率,最大值为400K
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void I2CInit(uint32 FI2c)
{
    VICIntEnClr = 1 << 9;                           // 禁止能I2c中断
    if (FI2c > 400000) FI2c = 400000;

	PINSEL0 = (PINSEL0 & 0xfffffc0f) | 0x50;    // 选择管脚为I2c
	IO0DIR |= EEPROM_WP;						// P0相关输出引脚初始化
	IO0SET = EEPROM_WP;							// 写保护有效,引脚输出高电平 

	I2CONCLR = 0x6C;                            // 清除控制寄存器
	I2SCLH = (Fpclk / FI2c + 1) / 2;            // 设置高电平时间
	I2SCLL = (Fpclk / FI2c) / 2;                // 设置低电平时间
   /* 设置I2C中断允许 */
	VICIntSelect = 0x00000000;			// 设置所有通道为IRQ中断
	VICVectCntl0 = 0x29;				// I2C通道分配到IRQ slot 0,即优先级最高
	VICVectAddr0 = (int)IRQ_I2C;	    // 设置I2C中断向量地址	
}

/*********************************************************************************************************
** 函数名称: __I2cWrite
** 功能描述: 读I2C,但不发送STOP信号 
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void __I2cWrite(void)
{
    I2c_Addr = I2C_Pa->Addr & 0xfe;		// 存储地址写
    I2c_Num = I2C_Pa->WrLen;			// 存储写字节数
    I2c_Buf = I2C_Pa->RTBuf;			// 存储写的数据的指针
	I2C_end=0;
    I2CONSET = 0x24;			// 设置为主机,并启动总线
    
	while(I2C_end==0);
}

/*********************************************************************************************************
** 函数名称: I2cWrite
** 功能描述: 向I2C从器件写数据
** 输 出:发送的数据字节数
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint16 I2cWrite(void)
{
    
    I2C_Pa=(I2C_Param *)I2C_Param_Addr;
    
    I2CONCLR = 0x6C;			// 清除控制寄存器I2EN,STA,SI,AA
    I2CONSET = 0x40;			// 使能I2c,I2EN=1
    VICIntEnable = 1 << 9;		// 使能I2c中断

	__I2cWrite();
    if ( I2C_end == I2C_WRITE_END)
    {
        I2CONSET = 1 << 4;		// 发送停止信号
        I2CONCLR = 0x28;		// 清除标志
    }

    VICIntEnClr = 1 << 9;		/// 禁止能I2c中断

    return (I2C_Pa->WrLen - I2c_Num);
}

/*********************************************************************************************************
** 函数名称: I2cRead
** 功能描述: 从I2c从器件读数据
** 输 出:已读取的字节数
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
int16 I2cRead(void)
{
    I2C_Pa=(I2C_Param *)I2C_Param_Addr;

	I2CONCLR = 0x6C;			// 清除控制寄存器
    I2CONSET = 0x40;			// 使能I2c
    VICIntEnable = 1 << 9;		// 使能I2c中断

    if (I2C_Pa->WrLen > 0)
    {
		__I2cWrite();
		if ( I2C_end != I2C_WRITE_END)
        {
            return -1;
        }
    }

    I2c_Addr = I2C_Pa->Addr | 0x01;	// 存储地址读
    I2c_Num = I2C_Pa->RdLen;		// 存储读字节数
    I2c_Buf = I2C_Pa->RTBuf;		// 存储读到的数据
    I2CONCLR = 0x28;
	I2C_end=0;
    I2CONSET = 0x24;			// 设置为主机,并启动总线
    VICIntEnable = 1 << 9;		// 使能I2c中断

	while(I2C_end==0);

    VICIntEnClr = 1 << 9;		// 禁止能I2c中断
    return (I2C_Pa->RdLen - I2c_Num);
}


/*********************************************************************************************************
** 函数名称: IRQ_I2C_Exception
** 功能描述: I2c中断服务程序
** 输 入: 无
**
** 输 出: 无
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void __irq IRQ_I2C(void)
{
    switch(I2STAT & 0xf8)
    {
        case  0x08:				// 已发送起始条件,与0x18相同处理
        case  0x10:				// 已发送重复起始条件
            I2DAT = I2c_Addr;	// 发送地址
            I2CONCLR = 0x28;	// 清除标志
            break;
        case  0x18:				// 已发送SLA+W,并已接收应答
            I2DAT = *I2c_Buf++;
            I2c_Num--;
            I2CONCLR = 0x28;	// 清除标志
            break;
        case  0x28:				// 已发送I2C数据,并接收到应答
            if (I2c_Num > 0)
            {
                I2DAT = *I2c_Buf++;
                I2c_Num--;
                I2CONCLR = 0x28;	// 清除标志
            }
            else
            {
				I2C_end=I2C_WRITE_END;
                VICIntEnClr = 1 << 9;	// 禁止能I2c中断 */
            }
            break;
        case  0x20:		// 已发送SLA+W;已接收非ACK, 与0x48处理相同
        case  0x30:		// 已发送I2DAT中的数据字节;已接收非ACK, 与0x48处理相同
        case  0x48:		// 已发送SLA+R;已接收非ACK
            I2CONSET = 1 << 4; 		// 发送停止信号
 			I2C_end=I2C_ACK_ERR;
            I2CONCLR = 0x28; 		// 清除标志
            break;
        case  0x38: 		// 在SLA+R/W或数据字节中丢失仲裁
 			I2C_end=I2C_NOT_GET_BUS;
            I2CONCLR = 0x28; 		// 清除标志 */
            break;
        case  0x40: 		// 已发送SLA+R;已接收ACK
            if (I2c_Num <= 1)
            {
                I2CONCLR = 1 << 2; 		// AA=0,下次发送非应答信号
            }
            else
            {
                I2CONSET= 1 << 2; 		// AA=1,下次发送应答信号
            }
            I2CONCLR = 0x28; 			// 清除标志
            break;
        case  0x50: 			// 已接收数据字节;已发送ACK
            *I2c_Buf++ = I2DAT; 		// 接收数据
            I2c_Num--;
            if (I2c_Num <= 1)
            {
                I2CONCLR = 1 << 2; 		// 下次发送非应答信号
            }
            I2CONCLR = 0x28; 			// 清除标志
            break;
        case  0x58: 			// 已接收数据字节;已返发送ACK
            *I2c_Buf = I2DAT;			// 接收数据
            I2c_Num--;
            I2CONSET= 1 << 4; 			// 结束总线
 			I2C_end=I2C_READ_END;
            I2CONCLR = 0x28; 			// 清除标志
            break;
        default:
            I2CONSET = 1 << 4; 		// 发送停止信号
 			I2C_end=0x10;			// 非法状态
            I2CONCLR = 0x28; 			// 清除标志
            break;
    }

    VICVectAddr = 0; 			// 通知中断控制器中断结束
}

⌨️ 快捷键说明

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