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

📄 twi_lib.c

📁 atmel at89c51snd1c mp3芯片方案源码
💻 C
📖 第 1 页 / 共 2 页
字号:

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