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

📄 i2c.c

📁 台湾亚信电子ASIX11015的I2C口驱动,很适合接当今流行的I2C口.希望和大家一起努力!
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *********************************************************************************
 *     Copyright (c) 2005	ASIX Electronic Corporation      All rights reserved.
 *
 *     This is unpublished proprietary source code of ASIX Electronic Corporation
 *
 *     The copyright notice above does not evidence any actual or intended
 *     publication of such source code.
 *********************************************************************************
 */
/*================================================================================
 * Module Name : i2c.c
 * Purpose     : This module handles the I2C serial interface driver.
 * Author      : Robin Lee
 * Date        : 2005-01-10
 * Notes       :
 * $Log: i2c.c,v $
 * Revision 1.2  2006/04/14 00:56:42  robin6633
 * Fixed the function name error "I2cCmd() -> I2C_Cmd()".
 *
 * Revision 1.1  2006/04/07 11:38:34  robin6633
 * no message
 *
 *================================================================================
 */

/* INCLUDE FILE DECLARATIONS */
#include	<stdio.h>
#include	"reg80390.h"
#include	"types.h"
#include	"i2c.h"
#if I2C_SLAVE_ENABLE
#include	"console_debug.h"	
#endif


/* STATIC VARIABLE DECLARATIONS */
static U8_T		i2cCtrl = 0;
static U8_T		i2cEndCond = 0;
static U8_T		i2cActF = 0;	// indicate the condition of a transfer
static U16_T	i2cDataLen = 0;	// The I2cPktLen includes address and data
static U16_T	i2cDataLenCnt = 0;	// Packet's counter of transferring 
static U8_T		i2cPktDir = 0;	// Packet's direction
static I2C_BUF 	*ptI2cTxBuf = 0;
static I2C_BUF 	*ptI2cRxBuf = 0;
static U8_T		i2cState = 0;	// I2C master state flag
static U8_T		i2cSlvRxPkt[SLV_MAX_PKT_NUM];
static U8_T		i2cSlvTxPkt[SLV_MAX_PKT_NUM];


/* LOCAL SUBPROGRAM DECLARATIONS */
static void i2c_MstStatus(U8_T i2cStatus);
static void i2c_SlvStatus(U8_T i2cStatus);
static void i2c_MasterXmit(U8_T wrData, U8_T mstCmd);
static void i2c_MasterRcvr(U8_T *rdData, U8_T mstCmd);
static void i2c_SlaveXmit(U8_T wrData, U8_T slvCmd);
static void i2c_SlaveRcvr(U8_T *rdData, U8_T slvCmd);

#if I2C_SLAVE_ENABLE
static void i2c_SlvRxProcess(void);
#endif


/* LOCAL SUBPROGRAM BODIES */

/*
 *--------------------------------------------------------------------------------
 * static void i2c_MstStatus(U8_T i2cStatus)
 * Purpose : Checks the interrupt status of I2C master mode.
 * Params  : i2cStatus - master status when interrupt occured.
 * Returns : none
 * Note    : none
 *--------------------------------------------------------------------------------
 */
static void i2c_MstStatus(U8_T i2cStatus)
{
	if (i2cPktDir == I2C_MST_XMIT)
	{
		/* Check the current byte ack */
		if ((!(i2cStatus & I2C_NO_ACK)) && (i2cStatus & I2C_INTR_FLAG)
		&& (!(i2cStatus & I2C_TIP)) && (i2cStatus & I2C_BUS_BUSY))
		{
			if (!I2C_FlagChk(I2C_BUSY))
			{
				I2C_FlagEnb(I2C_RESTART);
			}
			else
			{
				if ((i2cCtrl & I2C_10BIT) && (i2cActF & I2C_START_COND))
				{
					i2c_MasterXmit((U8_T)(ptI2cTxBuf->I2cAddr.TenBitAddr & 0x00FF), I2C_MASTER_GO | I2C_CMD_WRITE);
				}
				else
				{
					if (i2cDataLenCnt < (i2cDataLen-1))
					{
						/* transmit the first data byte */
						i2c_MasterXmit(ptI2cTxBuf->I2cData[i2cDataLenCnt], I2C_MASTER_GO | I2C_CMD_WRITE);
						i2cDataLenCnt ++;
					}
					else if (i2cDataLenCnt == (i2cDataLen-1))
					{
						/* transmit the last data byte */
						if (i2cEndCond & I2C_STOP_COND)
						{
							i2c_MasterXmit(ptI2cTxBuf->I2cData[i2cDataLenCnt], I2C_MASTER_GO | I2C_CMD_WRITE | I2C_STOP_COND);
							i2cDataLenCnt = 0;
						}
						else
						{
							i2c_MasterXmit(ptI2cTxBuf->I2cData[i2cDataLenCnt], I2C_MASTER_GO | I2C_CMD_WRITE);
							i2cDataLenCnt = 0;
							EA = 0;
							I2C_FlagClr(I2C_BUSY);
							EA = 1;
						}
					}
				}
			}
		/*	if (i2cActF & I2C_STOP_COND)
			{
				i2cDataLenCnt = 0;
				EA = 0;
				I2C_FlagClr(I2C_BUSY);
				EA = 1;
			}*/
		}
		else if (i2cStatus & I2C_NO_ACK)
		{
			i2cDataLenCnt = 0;
			if (i2cActF & I2C_START_COND)
			{
				/* transmit the STOP condition */
				i2c_MasterXmit(0, I2C_MASTER_GO | I2C_STOP_COND);
				i2cDataLenCnt = 0;
				EA = 0;
				I2C_FlagClr(I2C_BUSY);
				I2C_FlagEnb(I2C_NACK);
				EA = 1;
			}
			else
			{
				i2cDataLenCnt = 0;
				EA = 0;
				I2C_FlagClr(I2C_BUSY);
				EA = 1;
			}
		}
		else if (i2cStatus & I2C_ARB_LOST)
		{
			i2c_MasterXmit(0, I2C_MASTER_GO | I2C_STOP_COND);
			i2cDataLenCnt = 0;
			EA = 0;
			I2C_FlagClr(I2C_BUSY);
			I2C_FlagEnb(I2C_NACK);
			printf("I2C arbitration lost\n\r");
			EA = 1;
		}
		else if (i2cStatus & I2C_TIP)
		{
			i2cDataLenCnt = 0;
			if (i2cActF & I2C_START_COND)
			{
				I2C_FlagClr(I2C_BUSY);
				/* transmit the STOP condition */
				i2c_MasterXmit(0, I2C_MASTER_GO | I2C_STOP_COND);
			}
			else
			{
				/* transmit the STOP condition or repeat START condition */
				I2C_PktBuf(ptI2cTxBuf);
			}
		}
		else if ((!(i2cStatus & I2C_NO_ACK)) && (!(i2cStatus & I2C_TIP)) && (!(i2cStatus & I2C_BUS_BUSY)))
		{
			if (i2cActF & I2C_STOP_COND)
			{
				i2cDataLenCnt = 0;
				EA = 0;
				I2C_FlagClr(I2C_BUSY);
				EA = 1;
			}
		}
	}
	else if (i2cPktDir == I2C_MST_RCVR)
	{
		/* Check the current byte ack */
		if ((!(i2cStatus & I2C_NO_ACK)) && (i2cStatus & I2C_INTR_FLAG)
		&& (!(i2cStatus & I2C_TIP)) && (i2cStatus & I2C_BUS_BUSY))
		{
			if (i2cActF & I2C_START_COND)
			{
				if (i2cDataLenCnt == (i2cDataLen - 1))
					i2c_MasterRcvr(&(ptI2cRxBuf->I2cData[0]), I2C_MASTER_GO | I2C_CMD_READ | I2C_STOP_COND);
				else
					i2c_MasterRcvr(&(ptI2cRxBuf->I2cData[0]), I2C_MASTER_GO | I2C_CMD_READ);
			}
			else if (i2cActF & I2C_STOP_COND)
			{
				I2C_FlagClr(I2C_BUSY);
				i2c_MasterRcvr(&(ptI2cRxBuf->I2cData[i2cDataLenCnt]), 0);
			}
			else
			{
				if (i2cDataLenCnt < (i2cDataLen - 1))
				{
					/* reveive the next byte */
					i2c_MasterRcvr(&(ptI2cRxBuf->I2cData[i2cDataLenCnt]), I2C_MASTER_GO | I2C_CMD_READ);
				}
				else if (i2cDataLenCnt == (i2cDataLen - 1))
				{
					/* receive the last byte */
					i2c_MasterRcvr((U8_T *)(&(ptI2cRxBuf->I2cData[i2cDataLenCnt])), I2C_MASTER_GO | I2C_CMD_READ | I2C_STOP_COND);
				}
			}
		}
		else if (i2cStatus & I2C_NO_ACK)
		{
			i2cDataLenCnt = 0;
			if (i2cActF & I2C_START_COND)
			{
				i2c_MasterXmit(0, I2C_MASTER_GO | I2C_STOP_COND);
				i2cDataLenCnt = 0;
				EA = 0;
				I2C_FlagClr(I2C_BUSY);
				I2C_FlagEnb(I2C_NACK);
				EA = 1;
			}
			else
			{
				i2cDataLenCnt = 0;
				EA = 0;
				I2C_FlagClr(I2C_BUSY);
				EA = 1;
			}
		}
		else
		{
			if (i2cActF & I2C_STOP_COND)
			{
				I2C_FlagClr(I2C_BUSY);
				i2c_MasterRcvr(&(ptI2cRxBuf->I2cData[i2cDataLenCnt]), 0);
			}
		}
	}
}

/*
 *--------------------------------------------------------------------------------
 * static void i2c_SlvStatus(U8_T i2cStatus)
 * Purpose : Handles the interrupt status of I2C slave mode.
 * Params  : none
 * Returns : none
 * Note    : none
 *--------------------------------------------------------------------------------
 */
static void i2c_SlvStatus(U8_T i2cStatus)
{
	U8_T	devAddr;

	if (i2cStatus & I2C_SLV_STOP)
	{
		if (!(i2cStatus & I2C_SLV_START))
		{
			if (i2cPktDir == I2C_SLV_RCVR)
			{
				i2cDataLen = i2cDataLenCnt;
				#if I2C_SLAVE_ENABLE
				i2c_SlvRxProcess();
				#endif
			}
			i2cDataLenCnt = 0;
			i2c_SlaveRcvr(&i2cSlvRxPkt[i2cDataLenCnt], I2C_SLAVE_GO);
		}
	}
	if (i2cStatus & I2C_SLV_NACK)
	{
		i2c_SlaveRcvr(&devAddr, I2C_RLS);
	}
	else
	{
		if (i2cStatus & I2C_SLV_WR)
		{
			if (i2cStatus & I2C_SLV_START)
			{
				i2c_SlaveRcvr(&devAddr, I2C_SLAVE_GO);
				i2cPktDir = I2C_SLV_RCVR;
				i2cDataLenCnt = 0;
			}
			else if (i2cStatus & I2C_SLV_STOP)
			{
				i2c_SlaveRcvr(&i2cSlvRxPkt[i2cDataLenCnt], I2C_SLAVE_GO);
				i2cDataLen = i2cDataLenCnt;
				#if I2C_SLAVE_ENABLE
				i2c_SlvRxProcess();
				#endif
				i2cDataLenCnt = 0;
			}
			else if (i2cStatus & I2C_SLV_RESTART)
			{
				i2c_SlaveRcvr(&devAddr, I2C_SLAVE_GO);
				i2cPktDir = I2C_SLV_RCVR;
				i2cDataLenCnt = 0;
			}
			else
			{
				i2c_SlaveRcvr(&i2cSlvRxPkt[i2cDataLenCnt], I2C_SLAVE_GO);
				i2cDataLenCnt ++;
			}
		}
		else if (i2cStatus & I2C_SLV_RD)
		{
			if (i2cStatus & I2C_SLV_STOP)
			{
				i2c_SlaveRcvr(&devAddr, I2C_SLAVE_GO);
				i2cDataLenCnt = 0;
			}
			else if (i2cStatus & I2C_SLV_START)
			{
				i2cPktDir = I2C_SLV_XMIT;
				i2cDataLenCnt = 0;
				#if I2C_SLAVE_ENABLE
				i2c_SlvRxProcess();
				#endif
				i2c_SlaveXmit(i2cSlvTxPkt[i2cDataLenCnt], I2C_SLAVE_GO);
				i2cDataLenCnt ++;
			}
			else if (i2cStatus & I2C_SLV_RESTART)
			{
				i2cPktDir = I2C_SLV_XMIT;
				i2cDataLenCnt = 0;
				#if I2C_SLAVE_ENABLE
				i2c_SlvRxProcess();
				#endif
				i2c_SlaveXmit(i2cSlvTxPkt[i2cDataLenCnt], I2C_SLAVE_GO);
				i2cDataLenCnt ++;
			}
			else
			{
				if (i2cSlvRxPkt[0] == I2C_SLV_BRDM)
				{
					#if I2C_SLAVE_ENABLE
					i2c_SlvRxProcess();
					#endif
				}
				i2c_SlaveXmit(i2cSlvTxPkt[i2cDataLenCnt], I2C_SLAVE_GO);
				i2cDataLenCnt ++;
			}
		}
	}
}

#if I2C_SLAVE_ENABLE
/*
 *--------------------------------------------------------------------------------
 * static void i2c_SlvRxProcess(void)
 * Purpose : Handling received command functions in I2C slave mode And replying
 *           packets corresponding with the received command.
 * Params  : none
 * Returns : none
 * Note    : none
 *--------------------------------------------------------------------------------
 */
static void i2c_SlvRxProcess(void)
{
	U8_T	slvCmd;
	U8_T	sfrAddr;
	U8_T	cmdIndReg, realReg, realLen;
	U32_T	memAddr, memData;
	U16_T	i;

	slvCmd = i2cSlvRxPkt[0];
	if ((slvCmd & 0xF0) == I2C_SLV_SWSFR)
	{
		realLen = (slvCmd & 0x0F) + 1;
		sfrAddr = i2cSlvRxPkt[1];
		for (i = 0 ; i < realLen ; i ++)
		{
			CLI_SfrWr((U32_T)sfrAddr, (U32_T)i2cSlvRxPkt[i + 2]);
		}
	}
	else if ((slvCmd & 0xF0) == I2C_SLV_SRSFR)
	{
		realLen = (slvCmd & 0x0F) + 1;
		sfrAddr = i2cSlvRxPkt[1];
		for (i = 0 ; i < realLen ; i ++)
		{
			CLI_SfrRd((U32_T)sfrAddr, &memData);
			i2cSlvTxPkt[i] = (U8_T)memData;
		}
	}
	else if ((slvCmd & 0xF0) == I2C_SLV_IWSFR)
	{
		cmdIndReg = i2cSlvRxPkt[1];
		realReg = i2cSlvRxPkt[2];
		realLen = (slvCmd & 0x0F) + 1;
		if (cmdIndReg == SFR_I2CCIR)
		{
			CLI_I2cWr((U32_T)realReg, &i2cSlvRxPkt[3], (U8_T)realLen);
		}
		else if (cmdIndReg == SFR_SPICIR)
		{
			CLI_SpiWr((U32_T)realReg, &i2cSlvRxPkt[3], (U8_T)realLen);
		}
		else if (cmdIndReg == SFR_OWCIR)
		{
			CLI_OwWr((U32_T)realReg, &i2cSlvRxPkt[3], (U8_T)realLen);
		}
		else if (cmdIndReg == SFR_CANCIR)
		{
			CLI_CanWr((U32_T)realReg, &i2cSlvRxPkt[3], (U8_T)realLen);
		}
		else if (cmdIndReg == SFR_TCIR)

⌨️ 快捷键说明

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