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

📄 i2c.c

📁 Freescale MCF5445evb 参考测试代码
💻 C
字号:
/* * File:		I2C.c * Purpose:		I2C transfer functions and interrupt handler * * Notes:		 *   */ #include "common.h"#include "i2c.h"/* Globals to be shared throughout the project */I2C_BUFFER i2c_tx_buffer;I2C_BUFFER i2c_rx_buffer;/* Globals for this file only */uint8 master_mode;uint8 master_tx_done;/******************************************************************************//*	Purpose:  	General function for performing I2C master transfers.  Capable *				of performing Master TX, Master RX, and Master TX/RX w/ Repeated *				Start. *				 *	Arguments:	mode - Valid modes include I2C_TX, I2C_RX, and I2C_TXRX  *					(all modes defined in i2c.h) *				slave_address - The slave address of the I2C module that needs *					to be dealt with.   */voidi2c_master (uint8 mode, uint8 slave_address){    #ifdef POLLING_MODE		    int i;    uint8 dummy_read;        /* Clear IBCR.IBDIS, disable interrupts */    MCF_I2C_I2CR = 0x80;			    /* Reset index for TX and RX buffers */    i2c_tx_buffer.tx_index = 0;    i2c_rx_buffer.rx_index = 0;        if (mode == I2C_TXRX)    {	/* Make sure bus is idle */	while (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB);	/* Put module in master TX mode (generates START) */	MCF_I2C_I2CR |= (MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_MTX);	/* Put target address into IBDR */	MCF_I2C_I2DR = ( 0 | slave_address | I2C_TX);	/* Wait for I2SR[IBB] (bus busy) to be set */	while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IBB));		/* Wait for address transfer to complete */	while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF));	MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;		/* Send the contents of the TX buffer */	while (i2c_tx_buffer.length > 0)	{	    MCF_I2C_I2DR = i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++];	    i2c_tx_buffer.length--;	    /* Wait for transfer to complete */	    while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF));	    MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;	}		/* Wait for a bit */	i=10000;	while(i--);		/* Set IBCR.RSTA and put in master RX mode */	MCF_I2C_I2CR |= (0 | MCF_I2C_I2CR_RSTA);	/* Put target address into IBDR and set the R/!W bit */	MCF_I2C_I2DR = (0 | slave_address | I2C_RX);		/* Wait for address transfer to complete */	while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF));	MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;		/* Clear TX/RX bit in order to set receive mode */	MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX; 		/* Dummy read of IBDR to signal the module is ready for the next byte */	dummy_read = MCF_I2C_I2DR;		/* Receive data from slave */	while (i2c_rx_buffer.length > 0) 	{	    /* Wait for transfer to complete */	    while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF));	    MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;	    /* Check for second-to-last and last byte transmission.  After second-to-last	       byte is received, it is required to disable the ACK bit in order to signal	       to the slave that the last byte has been received.  The actual NAck does not	       take place until after the last byte has been received. */	    if (i2c_rx_buffer.length == 2) 	    {		/* Disable Acknowledge, generate STOP after next byte transfer */		MCF_I2C_I2CR |= MCF_I2C_I2CR_TXAK;	    }	    if(i2c_rx_buffer.length == 1) 	    {		/* Generate STOP */		MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;	    }	    	    /* Store received data in RX buffer */	    i2c_rx_buffer.buf[i2c_rx_buffer.rx_index++] = MCF_I2C_I2DR;	    i2c_rx_buffer.length--;	}		/* Restore module to it's idle (but active) state */	MCF_I2C_I2CR = 0xC0;		return;	    }    else if (mode == I2C_TX)    {	/* Make sure bus is idle */	while (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB);	/* Put module in master TX mode (generates START) */	MCF_I2C_I2CR |= (MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_MTX);	/* Put target address into IBDR */	MCF_I2C_I2DR = ( 0 | slave_address | I2C_TX);	/* Wait for I2SR[IBB] (bus busy) to be set */	while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IBB));		/* Wait for address transfer to complete */	while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF));	MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;		/* Send the contents of the TX buffer */	while (i2c_tx_buffer.length > 0)	{	    MCF_I2C_I2DR = i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++];	    i2c_tx_buffer.length--;	    /* Wait for transfer to complete */	    while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF));	    MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;	}		/* Restore module to it's idle (but active) state */	MCF_I2C_I2CR = 0xC0;		return;    }    else if (mode == I2C_RX)    {	/* Make sure bus is idle */	while (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB);	/* Put module in master TX mode (generates START) */	MCF_I2C_I2CR |= (MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_MTX);	/* Put target address into IBDR */	MCF_I2C_I2DR = ( 0 | slave_address | I2C_RX);	/* Wait for I2SR[IBB] (bus busy) to be set */	while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IBB));		/* Wait for address transfer to complete */	while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF));	MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;		/* Clear TX/RX bit in order to set receive mode */	MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX; 		/* Dummy read of IBDR to signal the module is ready for the next byte */	dummy_read = MCF_I2C_I2DR;		/* Receive data from slave */	while (i2c_rx_buffer.length > 0) 	{	    /* Wait for transfer to complete */	    while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF));	    MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;	    /* Check for second-to-last and last byte transmission.  After second-to-last	       byte is received, it is required to disable the ACK bit in order to signal	       to the slave that the last byte has been received.  The actual NAck does not	       take place until after the last byte has been received. */	    if (i2c_rx_buffer.length == 2) 	    {		/* Disable Acknowledge, generate STOP after next byte transfer */		MCF_I2C_I2CR |= MCF_I2C_I2CR_TXAK;	    }	    if(i2c_rx_buffer.length == 1) 	    {		/* Generate STOP */		MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;	    }	    	    /* Store received data in RX buffer */	    i2c_rx_buffer.buf[i2c_rx_buffer.rx_index++] = MCF_I2C_I2DR;	    i2c_rx_buffer.length--;	}		/* Restore module to it's idle (but active) state */	MCF_I2C_I2CR = 0xC0;		return;		    }    else	printf("**ERROR** : Invalid Master transfer mode selected.\n");        /* Interrrupt-Driven */#else        master_mode = mode;    master_tx_done = FALSE;    /* Reset index for TX and RX buffers */    i2c_tx_buffer.tx_index = 0;    i2c_rx_buffer.rx_index = 0;        /* Transmit followed by receive using RSTA */    if (mode == I2C_TXRX)    {	/* Make sure bus is idle */	while (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB);	/* Put module in master TX mode (generates START) */	MCF_I2C_I2CR |= (MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_MTX);	/* Put target address into IBDR */	MCF_I2C_I2DR = ( 0 | slave_address | I2C_TX);	/* Wait for I2SR[IBB] (bus busy) to be set */	while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IBB));	/* Wait for TX to finish before starting RX */	while (!master_tx_done);		master_mode = I2C_RX;	/* Set IBCR.RSTA and put in master RX mode */	MCF_I2C_I2CR |= (0 | MCF_I2C_I2CR_RSTA);	/* Put target address into IBDR and set the R/!W bit */	MCF_I2C_I2DR = (0 | slave_address | I2C_RX);		/* Wait for bus to become free before continuing */	while (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB);		/* Restore module to it's idle (but active) state */	MCF_I2C_I2CR = 0xC0;		return;    }    /* Single TX or RX */    else if ( (mode == I2C_TX) | (mode == I2C_RX) )    {	/* Make sure bus is idle */	while (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB);	/* Put module in master TX mode (generates START) */	MCF_I2C_I2CR |= (0 | MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_MTX);	/* Put target address into IBDR */	MCF_I2C_I2DR = ( 0 | slave_address | mode);	/* Wait for I2SR[IBB] (bus busy) to be set */	while (!(MCF_I2C_I2SR & MCF_I2C_I2SR_IBB));		/* Wait for bus to become free before continuing */	while (MCF_I2C_I2SR & MCF_I2C_I2SR_IBB);	/* Restore module to it's idle (but active) state */	MCF_I2C_I2CR = 0xC0;		return;    }    else	printf("**ERROR** : Invalid Master transfer mode selected.\n");#endif}/******************************************************************************//*	Purpose:  	General I2C handler, created using the flowchart example  *				included in the I2C chapter of the UM.   */__interrupt__void i2c_handler(void){    /* Temp variable for dummy reads */    uint8 dummy_read;		    /* Clear the I2C Interrupt Flag. */    MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;        /* Check if this device is in Master or Slave Mode. */    if (MCF_I2C_I2CR & MCF_I2C_I2CR_MSTA)    {	/* Master Mode - Check if this device is in Transmit or Receive Mode. */	if (MCF_I2C_I2CR & MCF_I2C_I2CR_MTX)	{	    /* Master Transmit Mode - Check if last byte was tranmitted. */	    if ((i2c_tx_buffer.length == 0) && (master_mode != I2C_RX))	    {		/* Last byte was transmitted - 		   Generate Stop signal by changing to Slave Mode. */		/* If TXRX mode (Repeated Start), signal end of TX */		if (master_mode == I2C_TXRX)		    master_tx_done = TRUE;		/* Issue STOP */		else		    MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;		                #ifdef DEBUG		     printf("Master TX mode: Last Byte\n");                #endif	    }	    else	    {		/* More bytes to be transmitted - Check if ACK received. */		if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK)		{		    /* ACK not received - Generate STOP */		    MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;		                        #ifdef DEBUG		         printf("Master TX mode: NAK\n");                    #endif		}		else		{		    /* Check if end of address cycle */		    if (master_mode == I2C_RX)		    {			MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX;			dummy_read = MCF_I2C_I2DR;			                        #ifdef DEBUG			     printf("Master TX mode: End of RX address cycle, switch to RX mode.\n");                        #endif		    }		    /* ACK received, send data */		    else		    {			/* Not end of address cycle - Write next byte to MBDR */			MCF_I2C_I2DR = i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++];			i2c_tx_buffer.length--;                        #ifdef DEBUG			     printf("Master TX mode: Send Byte - 0x%02X\n",i2c_tx_buffer.buf[i2c_tx_buffer.tx_index-1]);                        #endif		    }		}	    } 	}	else	{	    /* Master Receive Mode - Check if this is last byte to be read. */	    	    if (i2c_rx_buffer.length == 1)	    {		printf("I2CR TXAK = 0x%02X\n",MCF_I2C_I2CR);		/* Last byte to be read - 		   Generate Stop signal by changing to Slave Mode. */		MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;		#ifdef DEBUG		     printf("Master RX mode: All data received, send STOP.\n");                #endif	    }	    else	    {		/* Not last byte to be read - Check if second to last byte. */		if (i2c_rx_buffer.length == 2)		{		    printf("I2CR S2L  = 0x%02X\n",MCF_I2C_I2CR);		    /* Second to last byte to be read - Set Transmit Acknowledge Enable		       bit so no ACK is sent after the next byte is received, which		       indicates "end of data" to the slave. */		    MCF_I2C_I2CR |= MCF_I2C_I2CR_TXAK;		    		    #ifdef DEBUG		         printf("Master RX mode: Second-to-last byte received, set TXAK.\n");                    #endif		}	    }	    /* Store received data in RX buffer */	    i2c_rx_buffer.buf[i2c_rx_buffer.rx_index++] = MCF_I2C_I2DR;	    i2c_rx_buffer.length--;	    #ifdef DEBUG	         printf("Master RX mode: Receive byte - 0x%02X\n",i2c_rx_buffer.buf[i2c_rx_buffer.rx_index-1]);            #endif	}    }    else    {	/* Slave Mode - Check if Arbitration Lost. */	if (MCF_I2C_I2SR & MCF_I2C_I2SR_IAL)	{	    #ifdef DEBUG	         printf("Arbitration Lost.\n");            #endif	    /* Clear IAL bit */	    MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IAL;	    	    /* Arbitration Lost - Check if this device is being addressed as slave.	       (If not, nothing more needs to be done.) */	    if (MCF_I2C_I2SR & MCF_I2C_I2SR_IAAS)	    {		/* Addressed as slave - 		   Check if master was reading from slave or writing to slave. */		if (MCF_I2C_I2SR & MCF_I2C_I2SR_SRW)		{		    /* Set tx_index to 0 */		    i2c_tx_buffer.tx_index = 0;		    		    /* Master was reading from slave - Set Transmit Mode. */		    MCF_I2C_I2CR |= MCF_I2C_I2CR_MTX;		    		    /* Write data to MBDR. */		    MCF_I2C_I2DR = i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++];		    #ifdef DEBUG		         printf("Arbitration Lost: Addressed as slave - TX mode.\n");                    #endif		}		else		{		    /* Set rx_index to 0 */		    i2c_rx_buffer.rx_index = 0;		    		    /* Master was writing to slave - Set Receive Mode. */		    MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX;		    		    /* Dummy read from MBDR, to clear the ICF bit. */		    dummy_read = MCF_I2C_I2DR;		    		    #ifdef DEBUG		         printf("Arbitration Lost: Addressed as slave - RX mode.\n");                    #endif		}	    }	    	}	else	{	    /* Arbitration Not Lost - Check if data byte is this devices's Slave Address byte. */	    if (MCF_I2C_I2SR & MCF_I2C_I2SR_IAAS)	    {		/* Data byte is Slave Address byte - Check Slave Read/Write bit. */		if (MCF_I2C_I2SR & MCF_I2C_I2SR_SRW)		{		    /* Set tx_index to 0 */		    i2c_tx_buffer.tx_index = 0;		    		    /* Master was reading from slave - Set Transmit Mode. */		    MCF_I2C_I2CR |= MCF_I2C_I2CR_MTX;		    		    /* Write data to MBDR. */		    MCF_I2C_I2DR = i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++];		    #ifdef DEBUG		         printf("Slave TX: First byte - 0x%02X\n",i2c_tx_buffer.buf[i2c_tx_buffer.tx_index-1]);                    #endif		}		else		{		    /* Master has specified Slave Receive Mode.		       Set Receive Mode.  (Writing to MBCR clears IAAS.) */		    		    /* Set rx_index to 0 */		    i2c_rx_buffer.rx_index = 0;		    		    MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX;		    		    /* Read address data from MBDR and store it. */		    dummy_read = MCF_I2C_I2DR;		    #ifdef DEBUG		         printf("Slave RX: Receive address.\n");                    #endif		}	    }	    else	    {		/* Data byte received is not Slave Address byte - 		   Check if this device is in Transmit or Receive Mode. */		if (MCF_I2C_I2CR & MCF_I2C_I2CR_MTX)		{		    		    /* Last byte received? */		    if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK)		    {			MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX;			dummy_read = MCF_I2C_I2DR;			#ifdef DEBUG			     printf("Slave TX: Last byte has been sent.\n");                        #endif		    }		    else		    {			/* Write data to MBDR. */			MCF_I2C_I2DR = i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++];			i2c_tx_buffer.length--;			#ifdef DEBUG			     printf("Slave TX: Send byte - 0x%02X\n",i2c_tx_buffer.buf[i2c_tx_buffer.tx_index-1]);                        #endif		    }		}		else		{		    /* Receive Mode - Read data from MBDR and store it. */		    i2c_rx_buffer.buf[i2c_rx_buffer.rx_index++] = MCF_I2C_I2DR;		    i2c_rx_buffer.length++;		    i2c_rx_buffer.data_present = TRUE;		    #ifdef DEBUG		         printf("Slave RX: Receive byte - 0x%02X\n",i2c_rx_buffer.buf[i2c_rx_buffer.rx_index-1]);                    #endif		}	    }	}    }}

⌨️ 快捷键说明

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