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

📄 bootloader_smbus.c

📁 用AVR453开发的电池保护板的C语言程序,希望对大家有用!
💻 C
📖 第 1 页 / 共 3 页
字号:
      break;

    case 1:
      BOOT_TEST_WF();
      testctr++;
      break;

    case 2:
      BOOT_TEST_PF();
      testctr++;
      break;

    case 3:
      BOOT_TEST_EF();
      testctr++;
      break;

    case 4:
      if(!LoopFlag)
      {
        BOOT_TEST_WE();
        testctr++;
      }
      break;

    case 5:
      if(!LoopFlag)
      {
        BOOT_TEST_EE();
        testctr++;
      }
      break;

    case 6:
      if(!LoopFlag)
      {
        BOOT_TEST_PE();
        testctr++;
      }
      break;

    case 7: //test the chained Initialize command
      BOOT_TEST_bigI();
      testctr++;
      break;

    case 8:
      BOOT_TEST_bigI32();
      testctr++;
      break;

    case 9:
      BOOT_TEST_bigI32();
      testctr++;
      break;

    case 10:
      BOOT_TEST_bigI32();
      testctr++;
      break;

    case 11:
      BOOT_TEST_bigI8();
      testctr++;
      break;

    case 12:
      break;

  }
}

#endif;承上#ifdef ENABLE_TESTCODE启此(#if&#else---#endif如同选择if和else)

/* ************************************************************* */
/* ************************************************************* */
/* ************************************************************* */


void main(void)
{
  init_boot();

  for(;;)
  {

#ifdef ENABLE_TESTCODE
    TestManager();
#endif

    if(TWCR & (1<<TWINT))			//TWI的控制寄存器Note that the TWI handler is POLLED in the BootLoader.中断启动
      TWI_handler();

    if(TWI_CmdFlags)
    {
      if(TWI_CmdFlags == SMB_SetUpReply)	/* Have Foreground set up TW_TxBuf[]. 显著TW_TXBUF位置已经设置*/
      {
        TWI_CmdFlags = 0;
        SMB_Reply();
      }
      else
      if(TWI_CmdFlags == SMB_GotCmdData)
      {
        TWI_CmdFlags = 0;
        SMB_CmdInterpreter();
      }
      else
      if(TWI_CmdFlags == SMB_GenBusTimeout)	/* Tell Foreground to generate a bus timeout, as we saw an error! */
      {
        TWI_CmdFlags = 0;
        SMB_BusTimeout();
      }
    }

    if(LoopFlag)				/* handle a repeated SLOW memory operation off-line */
      LoopMemory();
  }
}










/* *************************************************************************
 *
 *   Low-Level SMBus Communications State Machine状态
 *
 ************************************************************************* */

//unsigned char TW_state = TW_IDLE;	//state variable

//State Machine states
enum /*TW_State*/ {TW_IDLE=0, TW_Wait4Cmd, TW_Wait4RW, TW_Wait4Data, TW_ReplyData, TW_MSLA_W, TW_MCMD_W, TW_MDATA_W };

void TWI_handler(void)
{
  unsigned char Status;

  Status = TWSR & 0xF8;		//This identifies what caused the interrupt to fire.

  switch(TW_state)
  {
    default:
    case TW_IDLE:	//If not SLA_W or RSTOP, is an error!
      if(TWS_SLA_W == Status)	// saw Slave address match with a Write bit
      {
        TW_state = TW_Wait4Cmd;
      }
      else
      if(TWS_RSTOP == Status)	//Saw a Stop, possibly left over from previous cmd.
      {
         ;			//Everything is probably OK.  Take no action.
      }
      else //had some type of error!
      {
        TWI_CmdFlags = SMB_GenBusTimeout;	//Flag the error & stay in this state.
        TWCR = (1<<TWEA) | (1<<TWEN);         //disable int, and DON'T clear the TWINT flag!
        return;
      }
      TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);	//must re-enable ACKing
      break;


    //SLAVE-mode states follow.

    case TW_Wait4Cmd:	//upon entry, we've expect to have received a Cmd byte.
      if(TWS_RCMD == Status)		//It appears that we have received a Command byte now.
      {
        if(SMBV_Opt5 == TWDR)
        {
          TW_state = TW_Wait4RW;	//set up next state
          TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);	//enable ACKing
          return;
        }
      }
      //In all cases except those that 'return' (above), it's an error.
      TWI_CmdFlags = SMB_GenBusTimeout;	//Generate a bus timeout.
      TWCR = (1<<TWEA) | (1<<TWEN);     //disable int, and DON'T clear the TWINT flag!
      TW_state = TW_IDLE;		//Reset the state machine.
      break;


    case TW_Wait4RW:	//We will now find out if we will RX more, or we need to TX a reply instead.
      if(TWS_RDATA == Status)		//It is a WRITE-type command. Prep the RX buffer to accept more data.
      {	//NOTE: OptionalMfgFunction5 is a BLOCK command in both directions.
      	//Place all bytes of the transaction into the buffer so we can do a PEC on it if needed.
      	TW_RxBuf[0] = TWAR & 0xFE;	//PEC requires the slave address to be included.
      	TW_RxBuf[1] = SMBV_Opt5;	//store the previously-send Command.
        TW_RxBuf[2] = TWDR;		//THIS byte is the block byte count.
        TW_RxBufCnt = TWDR;
        TW_RxBufIndex = 3;		//the index to store data in the buffer
        TW_state = TW_Wait4Data;
        TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);	//enable ACKing
      }
      else
      if(TWS_REPEAT == Status)	//We saw a re-Start, so must be getting ready for a Read cmd.
      {	//Must now interpret previously-sent CurrentCmd & set up Reply data.
        TWI_CmdFlags = SMB_SetUpReply;		//Foreground routine will set up TWCR.
        TW_state = TW_ReplyData;		//Move to next state.
        TWCR = (1<<TWEA) | (1<<TWEN);           //disable int, and DON'T clear the TWINT flag!
        return;					
      }
      else  //some type of error!
      {
        TWI_CmdFlags = SMB_GenBusTimeout;	//Generate a bus timeout.
        TWCR = (1<<TWEA) | (1<<TWEN);           //disable int, and DON'T clear the TWINT flag!
        TW_state = TW_IDLE;		        //Reset the state machine.
      }
      break;


    case TW_Wait4Data:	//We are in Slave Receive operating mode.
      if(TWS_RDATA == Status)			//received a data byte
      {
        TW_RxBuf[TW_RxBufIndex++] = TWDR;	//store the byte
        if(0 == --TW_RxBufCnt)			//Have we received ALL expected data now?
        {
          TW_RxBufCnt = TW_RxBufIndex;		//re-use the Write Index's value as the Valid Byte Count.
          TW_RxBufIndex = 0;			//clear the index in preparation for interpreting it.
          TWI_CmdFlags = SMB_GotCmdData;	//tell Foreground to process this now.
          //The foreground code is now responsible for either flagging an error and resetting
          // the state to IDLE, or clearing TWINT to allow the transaction to finish with a STOP.
          //If the cmd is OK, the Foregound must also clear TW_RxBufCnt when done so that STOP works right.
          //The foreground code must reference the UsePEC flag to determine if PEC is included & is valid.
          TWCR = (1<<TWEA) | (1<<TWEN);         //disable int, and DON'T clear the TWINT flag!
          TW_state = TW_IDLE;		//Expecting a STOP next; just 'eat' it at TW_Idle.
          return;
        }
      }
      else
      if(TWS_RSTOP == Status)		//got a STOP; all done RXing data now.
      { //Note: if we get a STOP prematurely, then we simply ignore the command,
      	//  since it is too late to inform the Master of the error.
        TW_state = TW_IDLE;		//Reset the state machine in all cases.
      }
      else  //some type of error!
      {
        TWI_CmdFlags = SMB_GenBusTimeout;	//Generate a bus timeout.
        TWCR = (1<<TWEA) | (1<<TWEN);         //disable int, and DON'T clear the TWINT flag!
        TW_state = TW_IDLE;		//Reset the state machine.
        return;
      }
      TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);	//enable ACKing
      break;


    case TW_ReplyData:	//We are now in Slave Transmit operating mode.
      //Note: TW_TxBufCnt *always* includes the PEC byte! Since we don't
      // know whether the Master actually WANTS the PEC byte or not, we will
      // always TRY to send it, regardless of the state of the UsePEC flag.
      // If the Master does NOT want it, we will get a NAK while the PEC
      // byte is still in the buffer.  In the rare case where we send it all,
      // including the PEC byte, but we still get an ACK back, the TWI module
      // will be off-line anyway due to not setting the TWEA bit after sending PEC,
      // and we will therefore be unable to flag that an error has occurred.
      if((TWS_SLA_R == Status) || (TWS_RACK == Status))	//send out Reply data
      {
        TWDR = TW_TxBuf[TW_TxBufIndex++];	//send data out
        if(--TW_TxBufCnt == 0)			//Have we emptied the buffer, incl. PEC?
          TWCR = (1<<TWINT) | (1<<TWEN);		// Yes, so don't set TWEA.
        else
          TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);	// No, so assert TWEA.
      }
      else
      if(TWS_RNAK == Status)	//We may have gotten this validly or as an Error.
      {
        if(TW_TxBufCnt == 1)	//Not an error. Master didn't want PEC; clear UsePEC flag!
        {
          TW_TxBufCnt = 0;	//clear the buffer too.
          UsePEC = 0;
        }
        else
        if(TW_TxBufCnt == 0)	//Not an error. Master wanted PEC (and got it); assert UsePEC.
          UsePEC = 1;
        else			//some kind of error occurred; we got NAK too early!
        { //Note: the TWI module is now OFF-LINE, so we can't inform Host of this error!!
          ;
        }
        TW_state = TW_IDLE;			//In all cases, go back to IDLE.
        TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
      }
      else
//    if(TWS_FINAL == Status)	//ERROR: we got an ACK but we have no more data!
      { //Since the TWI module is now in "Not Addressed Slave" mode, we can't flag the error.
        TW_state = TW_IDLE;	//Reset the state machine.
        TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
      }
      break;

  } // end of switch(TW_state)
}










/* *************************************************************************
 *
 *   ISP-over-SMBus Command Interpreter
 *
 ************************************************************************* */


void SMB_BusTimeout(void)
{
  int i;

  for(i=7000; i!=0; i--);   //4 cycles per interation, 28,000 cycles

  SMB_RestoreBus();
}



void SMB_Reply(void)
{
  unsigned char temp;

  TWI_CmdFlags = 0;			//clear the flag that brought us here.
  TW_TxBufIndex = 0;			//initialize
  TW_TxBufCnt = 0;			//initialize

  //At this time, the only valid response is to send back 'Status'.
  TW_TxBuf[0] = 1;                      //SMBus 'block' byte count
  TW_TxBuf[1] = Status;                 //Status value
  TW_TxBufIndex = 0;                    //point back to the start
  TW_TxBufCnt = 2;                      // # of valid bytes in this buffer

  //Generate PEC now for the *entire* transaction, including the original request!
  temp = FastCRC(0, (TWAR & 0xFE));	//use the SLA+W address
  temp = FastCRC(temp, SMBV_Opt5);
  temp = FastCRC(temp, (TWAR | 1));	//use the SLA+R address

  do {temp = FastCRC(temp, TW_TxBuf[TW_TxBufIndex++]);}
    while(TW_TxBufIndex != TW_TxBufCnt);

  TW_TxBuf[TW_TxBufIndex] = temp;	//append the CRC value on the end.
  TW_TxBufCnt++;			//increase the byte count for the PEC.
  TW_TxBufIndex = 0;		        //Reset the buffer pointer.
  TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);	//have TWI continue from where it stalled.
}





unsigned char EEbusy(void)
{
  return (EECR & (1<<EEPE));
}



unsigned char EEget(unsigned int address)
{
  while(EECR & (1<<EEPE));
  EEAR = address;
  EECR |= (1<<EERE);
  return EEDR;
}

void EEerase(unsigned int address)
{
  while(EECR & (1<<EEPE));
  EEAR = address;
  EECR = (1<<EEPM0) | (1<<EEMPE);
  EECR = (1<<EEPM0) | (1<<EEMPE) | (1<<EEPE);
}

⌨️ 快捷键说明

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