📄 twi_lib.c
字号:
#include "config.h" /* system configuration */
#include "twi_lib.h"
#include "lib_mcu\lcd\lcd_drv.h"
#include <intrins.h>
#define IIC_BIT_BANG
#ifdef IIC_BIT_BANG
///////////////////////////////////////////////////////////////////
void Start_I2c()
{
SDA=1; /*发送起始条件的数据信号*/
_Nop();
SCL=1;
_Nop(); /*起始条件建立时间大于4.7us,延时*/
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0; /*发送起始信号*/
_Nop(); /* 起始条件锁定时间大于4*/
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0; /*钳住I2C总线,准备发送或接收数据 */
_Nop();
_Nop();
}
//////////////////////////////////////////////////////////////////////////
void Stop_I2c()
{
SDA=0; /*发送结束条件的数据信号*/
_Nop(); /*发送结束条件的时钟信号*/
SCL=1; /*结束条件建立时间大于4us*/
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SDA=1; /*发送I2C总线结束信号*/
_Nop();
_Nop();
_Nop();
_Nop();
}
/////////////////////////////////////////////////////////////////////////
bit SendByte(uchar c)
{
INT8U i;
bit bAck;
for(i=0; i<8; i++)
{
if((c << i) & 0x80)
SDA = 1;
else
SDA = 0;
_Nop();
SCL=1; /*置时钟线为高,通知被控器开始接收数据位*/
_Nop();
_Nop(); /*保证时钟高电平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0;
}
_Nop();
_Nop();
SDA=1; /*8位发送完后释放数据线,准备接收应答位*/
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA == 1)
bAck = 0;
else
bAck = 1; /*判断是否接收到应答信号*/
SCL=0;
_Nop();
_Nop();
return bAck;
}
//////////////////////////////////////////////////////////////////////////////////////////////
void IIC_init(void)
{
SCL=0;
Stop_I2c();
}
//////////////////////////////////////////////////////////////////////////////////////////////
bit iic_send(unsigned char slave_adr, bit rw, unsigned char nbbytes, unsigned char *info )
{
INT8U *cp;
bit rc = 0;
if(rw == I2C_WRITE)
{
Start_I2c();
if( (rc = SendByte(slave_adr << 1)) == 1) //ack received
{
lcd_print_string(0x40, "acked");
for(cp=info; nbbytes--; cp++)
{
if( (rc = SendByte(*cp)) == 0 )
break;
}
}
}
Stop_I2c();
return rc;
}
#endif
////////////////////////////////////////////////////////////////////////////
#ifndef IIC_BIT_BANG
volatile bit b_I2C_busy;
volatile unsigned char I2C_Err;
volatile unsigned char I2C_nb_transmited;
volatile unsigned char I2C_RecPtr;
volatile unsigned char xdata I2C_slave_data[I2C_NB_SLAVE_DATA];
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -