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

📄 iic.c

📁 IIC驱动程序
💻 C
字号:


//***************************************************************************************************
//Return Value:     void 
//Parameters:       SSP peripheral setup bytes       
//Description:      This function sets up the SSP module on a
//					PIC18CXXX device for use with a Microchip I2C
//					EEPROM device or I2C bus device.           
//***************************************************************************************************
void OpenAIIC( unsigned char sync_mode, unsigned char slew )
{
	SSPSTAT &= 0x3F;		// power on state 
	SSPCON1 = 0x00;			// power on state
	SSPCON2 = 0x00;			// power on state
	SSPCON1 |= sync_mode;	// select serial mode 
	SSPSTAT |= slew;		// slew rate on/off 
	
	//DDRCbits.RC3 = 1;		// Set SCL (PORTC,3) pin to input
	TRISCbits.TRISC3 = 1;	// Set SCL (PORTC,3) pin to input
	//DDRCbits.RC4 = 1;		// Set SDA (PORTC,4) pin to input
	TRISCbits.TRISC4 = 1;	// Set SDA (PORTC,4) pin to input

	SSPCON1 |= SSPENB;		// enable synchronous serial port 
}


//***************************************************************************************************
//Return Value:     void 
//Parameters:       void       
//Description:      initiate I2C bus operate mode and baudrate.             
//***************************************************************************************************
void InitAIIC(void)
{
	//MASTER, 100K
	OpenAIIC(MASTER, SLEW_OFF);
	SSPADD = 0x09;			//0x27----25K ; 0x09--100K ZDX
	PIR1bits.SSPIF = 0;		// reset SSPIF bit

}
//***************************************************************************************************
//Return Value:     void
//Parameters:       void
//Description:      Send I2C bus start condition.
//***************************************************************************************************
void StartAIIC( void )
{
	SSPCON2bits.SEN = 1;		// initiate bus start condition
	while ( SSPCON2bits.SEN );	// wait until start condition is over 
	while ( !PIR1bits.SSPIF );	// wait until ninth clock pulse received
	PIR1bits.SSPIF = 0;		// reset SSPIF bit
}
//***************************************************************************************************
//Return Value:     void
//Parameters:       void
//Description:      Send I2C bus restart condition.
//***************************************************************************************************
void RestartAIIC( void )
{
	SSPCON2bits.RSEN = 1;		// initiate bus restart condition
	while ( SSPCON2bits.RSEN );	// wait until restart condition is over 
	while ( !PIR1bits.SSPIF );	// wait until ninth clock pulse received
	PIR1bits.SSPIF = 0;			// reset SSPIF bit
}
//***************************************************************************************************
//Return Value:     void
//Parameters:       void
//Description:      Send I2C bus stop condition.
//***************************************************************************************************
void StopAIIC( void )
{
	SSPCON2bits.PEN = 1;		// initiate bus stop condition
	while ( !PIR1bits.SSPIF );	// wait until ninth clock pulse received
	PIR1bits.SSPIF = 0;		// reset SSPIF bit
}
//***************************************************************************************************
//Return Value:     void
//Parameters:       void
//Description:      Initiate ACK bus condition. 
//***************************************************************************************************
void AckAIIC( void )
{
	PIR1bits.SSPIF = 0;			// reset SSPIF bit
	SSPCON2bits.ACKDT = 0;		// set acknowledge bit state for ACK
	SSPCON2bits.ACKEN = 1;		// initiate bus acknowledge sequence
	while ( !PIR1bits.SSPIF );	// wait until ninth clock pulse received
	PIR1bits.SSPIF = 0;			// reset SSPIF bit
}
//***************************************************************************************************
//Return Value:     void
//Parameters:       void
//Description:      Initiate NOT ACK bus condition. 
//***************************************************************************************************
void NotAckAIIC( void )
{
	PIR1bits.SSPIF = 0;			// reset SSPIF bit
	SSPCON2bits.ACKDT = 1;		// set acknowledge bit for not ACK
	SSPCON2bits.ACKEN = 1;		// initiate bus acknowledge sequence
	while ( !PIR1bits.SSPIF );	// wait until ninth clock pulse received
	PIR1bits.SSPIF = 0;			// reset SSPIF bit
}
//***************************************************************************************************
//Return Value:     contents of SSPBUF register 
//Parameters:       void
//Description:      Read single byte from I2C bus.
//***************************************************************************************************
unsigned char ReadAIIC( void )
{
	SSPCON2bits.RCEN = 1;		// enable master for 1 byte reception
	while ( !SSPSTATbits.BF );	// wait until byte received  
	return ( SSPBUF );			// return with read byte
}
//***************************************************************************************************
//Return Value:     Status byte for WCOL detection. 
//Parameters:       Single data byte for I2C bus.
//Description:      This routine writes a single byte to the I2C bus.
//***************************************************************************************************
unsigned char WriteAIIC( unsigned char data_out )
{
	SSPBUF = data_out;			// write single byte to SSPBUF
	if ( SSPCON1bits.WCOL )		// test if write collision occurred
		return ( ERR );			// if WCOL bit is set return negative #
	else
	{
		while( SSPSTATbits.BF );	// wait until write cycle is complete 
        return ( OK );				// if WCOL bit is not set return non-negative #
	}
}
//***************************************************************************************************
//Return Value:     void
//Parameters:       void
//Description:      Test and wait until I2C module is idle.
//***************************************************************************************************
void IdleAIIC( void )
{
	while ( ( SSPCON2 & 0x1F ) | ( SSPSTATbits.R_W ) )
		continue;
}
//***************************************************************************************************
//Return Value:     ACK status.
//Parameters:       void
//Description:      This routine check the slave ACK sigle.
//***************************************************************************************************
unsigned char CheckAckAIIC( void )
{
	//IdleIIC();				// test for idle condition
	while ( !PIR1bits.SSPIF );	// wait until ninth clock pulse received
	PIR1bits.SSPIF = 0;		// reset SSPIF bit
	if ( !SSPCON2bits.ACKSTAT ) // test received ack bit state
		return ( OK ); 
	else
		return ( ERR);			// bus device responded with  NOT ACK

}

unsigned char Master0ControlA(unsigned char  msg)
{
	StartAIIC();				//start IIC
	if ( PIR2bits.BCLIF )	// test for bus collision
		return ( ERR );		// return with Bus Collision error 
	
	if(!WriteAIIC(msg))		//writes a single byte to the I2C bus
		return( ERR );
	if(!CheckAckAIIC())
		return(ERR);
	return(OK);
}

unsigned char Master1ControlA(unsigned char  msg)
{
	RestartAIIC();			//restart IIC
	if ( PIR2bits.BCLIF )	// test for bus collision
		return ( ERR );		// return with Bus Collision error 
	
	if(!WriteAIIC(msg))		//writes a single byte to the I2C bus
		return( ERR );
	if(!CheckAckAIIC())
		return(ERR);
	return(OK);
}

BYTE WriteToRTC(BYTE *pFrom, UCHAR ucAddr, UCHAR ucNum)
{
	UCHAR i;
	UCHAR wtrdrtcaddr, wr_num;
	
	//overlay UCHAR WtRTC_Buf[16];
	//overlay UCHAR * pBuf = &WtRTC_Buf[0];

	wtrdrtcaddr = ucAddr;	
	wr_num = ucNum;


	//DisableInterupt();		
	//for(i=0; i<wr_num; i++)
		//*(pBuf + i) = * pFrom ++;
	//EnableInterupt();		

	//InitIIC();				// initiate I2C bus
	IdleAIIC();                 // test for idle condition
	INTCONbits.GIEH = 0;		//0 = disables all high priority interrupts
	INTCONbits.GIEL = 0;		//0 = disables all low priority peripheral interrupts
	if(Master0ControlA(SLAWC))
	{
		if(!WriteAIIC(wtrdrtcaddr))	//writes address 
		{
			StopAIIC();				
			INTCONbits.GIEH = 1;	//1 = Enables all high priority interrupts
			INTCONbits.GIEL = 1;	//1 = Enables all low priority peripheral interrupts
			return(SEND_ERR);
		}
		if(!CheckAckAIIC())
		{
			StopAIIC();				
			INTCONbits.GIEH = 1;	//1 = Enables all high priority interrupts
			INTCONbits.GIEL = 1;	//1 = Enables all low priority peripheral interrupts
			return(SEND_ERR);
		}
		for(i=0; i<wr_num; i++)
		{
			if(!WriteAIIC(* pFrom++))	//writes data 
			{
				StopAIIC();			
				INTCONbits.GIEH = 1;	//1 = Enables all high priority interrupts
				INTCONbits.GIEL = 1;	//1 = Enables all low priority peripheral interrupts
				return(SEND_ERR);
			}
			if(!CheckAckAIIC())
			{
 				StopAIIC();				
				INTCONbits.GIEH = 1;	//1 = Enables all high priority interrupts
				INTCONbits.GIEL = 1;	//1 = Enables all low priority peripheral interrupts
				return(SEND_ERR);
			}
		}
		IdleAIIC();				// test for idle condition
		StopAIIC();				
		INTCONbits.GIEH = 1;	//1 = Enables all high priority interrupts
		INTCONbits.GIEL = 1;	//1 = Enables all low priority peripheral interrupts
		return(ALL_OK);
	}
	StopAIIC();
	INTCONbits.GIEH = 1;		//1 = Enables all high priority interrupts
	INTCONbits.GIEL = 1;		//1 = Enables all low priority peripheral interrupts
	return(SEND_ERR);
}


BYTE ReadFromRTC(BYTE *pMsg, UCHAR ucAddr, UCHAR ucNum)
{
	UCHAR	i, RdRTCaddr, rdRTCnum;

	RdRTCaddr = ucAddr;
	rdRTCnum = ucNum;
	if(rdRTCnum < 1)
		return(OPERATE_ERR);
	//InitIIC();							// initiate I2C bus
	if(Master0ControlA(SLAWC))
	{
		if(!WriteAIIC(RdRTCaddr))		
		{
			StopAIIC();					//
			return(SEND_ERR);
		}
		if(!CheckAckAIIC())
		{
			StopAIIC();					//
			return(SEND_ERR);
		}
		if(!Master1ControlA(SLARC))
		{
			StopAIIC();					//
			return(SEND_ERR);
		}
			
		for(i=0; i<rdRTCnum; i++)
		{
			* pMsg ++ = ReadAIIC();			
			while ( SSPCON2bits.RCEN ); // check that receive sequence is over 
			if ( PIR2bits.BCLIF )       // test for bus collision
			{
				StopAIIC();				//
				return (SEND_ERR );		// return with Bus Collision error 
			}			
			if(i < (rdRTCnum - 1))
				AckAIIC();		//
			else
				NotAckAIIC();	//
		}
		IdleAIIC();				// test for idle condition
		StopAIIC();				//

	
		//DisableInterupt();	//
		//for(i=0;i<rdRTCnum;i++)
		//	 *(pMsg+i)= *(pRdBuf+i);
		//EnableInterupt();		//
		return(ALL_OK);
	}
	else
	{
		StopAIIC();			//
		return(BUS_ERR);
	}
}


BYTE WriteToFram(BYTE *pFrom, WORD ucAddr, UCHAR ucNum)
{
	UCHAR i,wraddr;
	UCHAR wr_num;
	WORD  icnum;
	TWO_BYTE_TO_WORD wtrdrtcaddr;

	wr_num = ucNum;
	wtrdrtcaddr.Word = ucAddr & 0x7fff;
	icnum = ucAddr & 0x8000;
	if(icnum)
	{
		wraddr = SLAWF2;
	}
	else
	{
		wraddr = SLAWF1;
	}
	

	//DisableInterupt();	
	//for(i=0; i<wr_num; i++)
		//*(pBuf + i) = * pFrom ++;
	//EnableInterupt();			

	//InitIIC();				// initiate I2C bus
	IdleAIIC();                  // test for idle condition
	INTCONbits.GIEH = 0;		//0 = disables all high priority interrupts
	INTCONbits.GIEL = 0;		//0 = disables all low priority peripheral interrupts
	if(Master0ControlA(wraddr))
	{
		if(!WriteAIIC(wtrdrtcaddr.Byte.h))	
		{
			StopAIIC();					
			return(SEND_ERR);
		}
		if(!CheckAckAIIC())
		{
			StopAIIC();					
			return(SEND_ERR);
		}
		if(!WriteAIIC(wtrdrtcaddr.Byte.l))
		{
			StopAIIC();					
			return(SEND_ERR);
		}
		if(!CheckAckAIIC())
		{
			StopAIIC();					
			return(SEND_ERR);
		}
		for(i=0; i<wr_num; i++)
		{
			if(!WriteAIIC(* pFrom++))	//writes data 
			{
				StopAIIC();			
				INTCONbits.GIEH = 1;	//1 = Enables all high priority interrupts
				INTCONbits.GIEL = 1;	//1 = Enables all low priority peripheral interrupts
				return(SEND_ERR);
			}
			if(!CheckAckAIIC())
			{
				StopAIIC();				
				INTCONbits.GIEH = 1;	//1 = Enables all high priority interrupts
				INTCONbits.GIEL = 1;	//1 = Enables all low priority peripheral interrupts
				return(SEND_ERR);
			}
		}
		IdleAIIC();				// test for idle condition
		StopAIIC();			
		INTCONbits.GIEH = 1;	//1 = Enables all high priority interrupts
		INTCONbits.GIEL = 1;	//1 = Enables all low priority peripheral interrupts
		return(ALL_OK);
	}
	StopAIIC();
	INTCONbits.GIEH = 1;		//1 = Enables all high priority interrupts
	INTCONbits.GIEL = 1;		//1 = Enables all low priority peripheral interrupts
	return(SEND_ERR);
}

BYTE ReadFromFram(BYTE *pMsg, WORD ucAddr, UCHAR ucNum)
{
	UCHAR	i, rdRTCnum,wraddr,rdaddr;
	WORD	icnum;
	TWO_BYTE_TO_WORD RdRTCaddr;

	RdRTCaddr.Word = ucAddr & 0x7fff;
	icnum = ucAddr & 0x8000;
	if(icnum)
	{
		wraddr = SLAWF2;
		rdaddr = SLARF2;
	}
	else
	{
		wraddr = SLAWF1;
		rdaddr = SLARF1;
	}
	rdRTCnum = ucNum;
	if(rdRTCnum < 1)
		return(OPERATE_ERR);
	//InitIIC();						// initiate I2C bus
	if(Master0ControlA(wraddr))
	{
		if(!WriteAIIC(RdRTCaddr.Byte.h))	
		{
			StopAIIC();					
			return(SEND_ERR);
		}
		if(!CheckAckAIIC())
		{
			StopAIIC();					
			return(SEND_ERR);
		}
		if(!WriteAIIC(RdRTCaddr.Byte.l))		
		{
			StopAIIC();					
			return(SEND_ERR);
		}
		if(!CheckAckAIIC())
		{
			StopAIIC();					
			return(SEND_ERR);
		}
		if(!Master1ControlA(rdaddr))
		{
			StopAIIC();				
			return(SEND_ERR);
		}
			
		for(i=0; i<rdRTCnum; i++)
		{
			* pMsg ++ = ReadAIIC();			
			while ( SSPCON2bits.RCEN ); // check that receive sequence is over 
			if ( PIR2bits.BCLIF )       // test for bus collision
			{
				StopAIIC();			
				return (SEND_ERR );		// return with Bus Collision error 
			}			
			if(i < (rdRTCnum - 1))
				AckAIIC();	
			else
				NotAckAIIC();	
		}
		IdleAIIC();				// test for idle condition
		StopAIIC();			

		
		//DisableInterupt();	
		//for(i=0;i<rdRTCnum;i++)
		//	 *(pMsg+i)= *(pRdBuf+i);
		//EnableInterupt();		
		return(ALL_OK);
	}
	else
	{
		StopAIIC();		
		return(BUS_ERR);
	}
}

⌨️ 快捷键说明

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