📄 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 + -