📄 twi_lib.c
字号:
/*C**************************************************************************
* NAME: twi_lib.c
*----------------------------------------------------------------------------
* Copyright (c) 2003 Atmel.
*----------------------------------------------------------------------------
* RELEASE: snd1c-refd-nf-4_0_3
* REVISION: 1.3
*----------------------------------------------------------------------------
* PURPOSE:
* This file provides all minimal functionnal access to the I2C interface
*****************************************************************************/
/*_____ I N C L U D E S ____________________________________________________*/
#include "config.h" /* system configuration */
/*_____ M A C R O S ________________________________________________________*/
/*_____ D E F I N I T I O N ________________________________________________*/
volatile bit b_I2C_busy;
volatile unsigned char I2C_Err;
volatile unsigned char I2C_nb_transmited;
volatile unsigned char I2C_RecPtr;
/*_____ D E C L A R A T I O N ______________________________________________*/
/*V**************************************************************************
* NAME: I2C_slave_data[I2C_NB_SLAVE_DATA]
*----------------------------------------------------------------------------
* PURPOSE:
* Global public Variable for I2C message in slave mode
*****************************************************************************/
volatile unsigned char xdata I2C_slave_data[I2C_NB_SLAVE_DATA];
/*V**************************************************************************
* NAME: I2C_message
*----------------------------------------------------------------------------
* PURPOSE:
* Global public Variable for I2C message in master mode
*****************************************************************************/
volatile I2C_type_message xdata I2C_message;
/*F**************************************************************************
* NAME: i2c_baud_rate
*----------------------------------------------------------------------------
* PARAMS:
* return: value for CR2..CR0
*----------------------------------------------------------------------------
* PURPOSE:
* returns correct value for CR2..CR0.
*----------------------------------------------------------------------------
* EXAMPLE:
* SSCON |= i2c_baud_rate(256);
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
unsigned char i2C_baud_rate (unsigned int ratio)
{
switch ( ratio )
{
case 256:
return I2C_RATIO_256;
break;
case 224:
return I2C_RATIO_224;
break;
case 192:
return I2C_RATIO_192;
break;
case 160:
return I2C_RATIO_160;
break;
case 960:
return I2C_RATIO_960;
break;
case 120:
return I2C_RATIO_120;
break;
case 60:
return I2C_RATIO_60;
break;
}
}
/*F**************************************************************************
* NAME: I2C_decode_status
*----------------------------------------------------------------------------
* PARAMS:
* return: none
*----------------------------------------------------------------------------
* PURPOSE:
* main processing state machine for I2C message reception transmission
* in slave or master mode.
* This function is called when an event occured on the I2C interface.
* Can be used both in polling or interrupt mode.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
void I2C_decode_status (void)
{
switch (SSSTA)
{
// STATE 00h: Bus Error has occurred
// ACTION: Enter not addressed SLV mode and release bus
case 0x00 :
b_I2C_busy = FALSE;
I2C_Err = BusError;
break;
//STATE 08h: A start condition has been sent
//ACTION: SLR+R/W are transmitted, ACK bit received
case 0x08 :
I2C_CLEAR_START;
SSDAT = I2C_message.address<<1;
if ( I2C_message.rw == I2C_READ ) SSDAT++; // Add 1 for Read bit in AdrWord
I2C_SET_AA;
//from here to 0x18 transmit or 0x40 receive
break;
//STATE 10h: A repeated start condition has been sent
//ACTION: SLR+R/W are transmitted, ACK bit received
case 0x10 :
I2C_CLEAR_START; // Reset STA bit in SSCON
SSDAT = I2C_message.address<<1;
if ( I2C_message.rw == I2C_READ ) SSDAT++; // Add 1 for Read bit in AdrWord
I2C_SET_AA; //wait on ACK bit
break;
//STATE 18h: SLR+W was transmitted, ACK bit received
//ACTION: Transmit data byte, ACK bit received
//PREVIOUS STATE: 0x08 or 0x10
case 0x18 : //master transmit, after sending
I2C_nb_transmited=0; //slave address, now load data
SSDAT = *(I2C_message.buf); //byte and send it
I2C_SET_AA; //wait on ACK bit
break;
//STATE 20h: SLR+W was transmitted, NOT ACK bit received
//ACTION: Transmit STOP
case 0x20 :
I2C_SET_STOP;
b_I2C_busy = FALSE;
I2C_Err = NoHostAdrAck;
break;
//STATE 28h: DATA was transmitted, ACK bit received
//ACTION: If last byte, send STOP, else send more data bytes
case 0x28 : //master transmit, after sending
//data byte, ACK received
I2C_nb_transmited++; // inc nb data transmit on message
I2C_message.buf++; // inc pointer ti data to be transmited
if ( I2C_nb_transmited < I2C_message.nbbytes ) //if there are still bytes to send
{
SSDAT = *(I2C_message.buf);
I2C_SET_AA; //wait on ACK bit
}
else
{ //run out of data, send stop,
I2C_SET_STOP;
I2C_Err = Tranfer_OK;
b_I2C_busy = FALSE; //transfer complete, clear b_I2C_busy
}
break;
//STATE 30h: DATA was transmitted, NOT ACK bit received
//ACTION: Transmit STOP
case 0x30 :
I2C_SET_STOP;
b_I2C_busy = FALSE;
I2C_Err = NoHostDataAck;
break;
//STATE 38h: Arbitration lost in SLA+W or DATA.
//ACTION: Release bus, enter not addressed SLV mode
// Wait for bus lines to be free
case 0x38 :
b_I2C_busy = FALSE;
I2C_Err = ArbitrationLost;
/*
#ifdef USER_I2C_FCT_ARBITRATION_LOST_IN_SLA+W_OR_DATA
I2C_fct_arb_lostinSLAorDATA();
#endif
*/
break;
//MASTER RECEIVER MODE FOLLOWS
//STATE 40h: SLA+R transmitted, ACK received
//ACTION: Receive DATA, ACK to be returned
//PREVIOS STATE: 0x08 or 0x10
case 0x40 : //master receive, after sending
if ( I2C_message.nbbytes == 1 )
{
I2C_CLEAR_AA; // only one data to receive, noACK to be send after the fisrt incoming data
}
else
{
I2C_SET_AA; //wait on ACK bit
I2C_nb_transmited=0; //data byte to be received, NOT ACK bit to follow --> 0x58
}
break;
//STATE 48h: SLA+R transmitted, NOT ACK received
//ACTION: Transmit STOP
case 0x48 :
I2C_SET_STOP;
b_I2C_busy = FALSE;
I2C_Err = NoHostAdrAck;
break;
//STATE 50h: Data has been received, ACK returned
//ACTION: Read DATA. If expecting more continue else STOP
case 0x50 : //master receive, received data
//byte and ACK, copy it into
*(I2C_message.buf+I2C_nb_transmited) = SSDAT; //buffer
I2C_nb_transmited++;
if ( I2C_nb_transmited < I2C_message.nbbytes )
{
I2C_SET_AA; //get more bytes
}
else
{
I2C_CLEAR_AA; //only one more byte to come
}
break;
//STATE 58h: Data has been received, NOT ACK returned
//ACTION: Read DATA. Generate STOP
case 0x58 :
*(I2C_message.buf+I2C_nb_transmited) = SSDAT;
I2C_SET_STOP;
b_I2C_busy = FALSE;
I2C_Err = Tranfer_OK;
break;
//STATE 60h: Own SLA+W has been received,ACK returned
//ACTION: Read DATA. return ACK
case 0x60 :
I2C_SET_AA;
b_I2C_busy = TRUE;
I2C_RecPtr=0;
break;
//STATE 68h: Arbitration lost in SLA and R/W as MASTER. Own SLA
// +W has been received. ACK returned
//ACTION: Read DATA. return ACK
// re-start MASTER,
case 0x68 :
I2C_SET_START;
break;
//STATE 70h: General call received, ACK returned
//ACTION: Receive DATA. return ACK
case 0x70 :
I2C_SET_AA;
b_I2C_busy = TRUE;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -