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

📄 8051 smb.c

📁 SMBUS function by 8051 partI
💻 C
📖 第 1 页 / 共 2 页
字号:
      // WRITE_BUF OP_CODEs are received. Note that the SMBus is stalled until the
      // OP_CODE is decoded.
      switch (OP_CODE & 0x0F){            // Decode OP_CODE

         // OP_CODE = READ_ADC - Perform an ADC conversion, and place data in 
         // output buffer.
         // Read only ADC high byte.
         case READ_ADC:
            SI = 0;                       // Free the bus
            AA = 0;                       // Take slave 'offline'
            ADCINT = 0;                   // Clear ADC interrupt flag.
            ADBUSY = 1;                   // Start conversion.
            while (!ADCINT);              // Wait for conversion to finish.
            WORD = ADC0H;                 // Put data in output buffer.
            AA = 1;                       // Put slave back 'online'
            VALID_OP = 0;                 // Look for a new OP_CODE
            break;

         // OP_CODE = WRITE_DAC - Wait for a valid data byte, and write it to high
         // byte of DAC0.
         case WRITE_DAC:
            SI = 0;                       // Free the bus
            DATA_READY = 0;               // Wait for valid data.
            while (!DATA_READY);          //
            DAC0L = 0;                    // DAC low byte
            DAC0H = WORD;                 // DAC high byte
            VALID_OP = 0;                 // Look for new OP_CODE
            SI = 0;                       // Free bus when finished.
            break;

         // OP_CODE = WRITE_BUF - Wait for valid data byte, then place data in 
         // DATA_BUF array.  Index data according to upper 4 bits of OP_CODE.
         case WRITE_BUF:
            SI = 0;                       // Free the bus
            index = (OP_CODE & 0xF0);     // Use upper 4 bits as array index.
            DATA_READY = 0;               // Wait for valid data.
            while (!DATA_READY);          //
            DATA_BUF[index] = WORD;       // Store data in array.
            VALID_OP = 0;                 // Look for new OP_CODE
            SI = 0;                       // Free the bus when finished.
            break;

         // OP_CODE = READ_BUF - Read DATA_BUF array and place byte in output buffer.
         // Array index determined by upper 4 bits of OP_CODE.
         case READ_BUF:
            index = (OP_CODE & 0xF0);     // Use upper 4 bits as array index.
            WORD = DATA_BUF[index];       // Place indexed data in output buffer.
            VALID_OP = 0;                 // Look for new OP_CODE
            SI = 0;                       // Free the bus when finished.
            break;
         }

      if (LOST){                          // If LOST is set, the device has recently
         COMMAND = LOST_COMMAND;          // lost an arbitration.  Load saved values
         WORD = LOST_WORD;                // back into transfer variables, and retry
         OP_CODE = LOST_CODE;             // transfer.
         LOST = 0;
         STO = 0;
         STA = 1;
         }
   }
}



//------------------------------------------------------------------------------------
// SMBus Interrupt Service Routine
//------------------------------------------------------------------------------------

void SMBUS_ISR (void) interrupt 7
{
   switch (SMB0STA){                      // Status code for the SMBus 
                                          // (SMB0STA register)

      // Master Transmitter/Receiver: START condition transmitted.
      // Load SMB0DAT with slave device address.  Mask out R/W bit since all transfers
      // start with an OP_CODE write.
      case SMB_START:
         SMB0DAT = (COMMAND & 0xFE);      // Load address of the slave to be accessed.
                                          // Mask out R/W bit because first transfer
                                          // will always be a write of the OP_CODE.
         STA = 0;                         // Manually clear STA bit
         SI = 0;                          // Clear interrupt flag
         break;

      // Master Transmitter/Receiver: Repeated START condition transmitted.
      // This state only occurs during a READ, after the OP_CODE has been sent.  Load
      // device address + READ into SMB0DAT.
      case SMB_RP_START:
         SMB0DAT = COMMAND;
         STA = 0;                         // Manually clear START bit.
         SI = 0;
         break;

      // Master Transmitter: Slave address + WRITE transmitted.  ACK received.
      // Load OP_CODE into SMB0DAT.
      case SMB_MTADDACK:
         SMB0DAT = OP_CODE;
         SI = 0;                          // Clear interrupt flag
         break;

      // Master Transmitter: Slave address + WRITE transmitted.  NACK received.
      // The slave is not responding.  Use ACK polling to retry.
      case SMB_MTADDNACK:
         STO = 1;
         STA = 1;
         SI = 0;                          // Clear interrupt flag
         break;

      // Master Transmitter: Data byte transmitted.  ACK received.
      // Check OP_CODE - If it is a READ code, send repeated START to begin
      // read.  If it is a WRITE code, load WORD into SMB0DAT for transfer.
      // If it is not a valid code, then either 1) data has been transmitted
      // and the transfer is finished, or 2) there is an error.  In either case,
      // send STOP and end transfer.
      case SMB_MTDBACK:
         switch (OP_CODE & 0x0F){         // Check only lower 4 bits.

            // OP_CODE is a READ.  Send repeated START.
            case READ_BUF:
            case READ_ADC:
               OP_CODE = 0;               // Current OP_CODE no longer useful
               STO = 0;
               STA = 1;
               break;

            // OP_CODE is a WRITE.  Load output data into SMB0DAT.
            case WRITE_BUF:
            case WRITE_DAC:
               SMB0DAT = WORD;
               OP_CODE = 0;               // Clear OP_CODE so transfer ends the next
               break;                     // time this state occurs 
                                          // (after data is sent).

            default:                      // No valid OP_CODE.  End transfer.
               STO = 1;
               SM_BUSY = 0;
               break;
         }
         SI = 0;
         break;

      // Master Transmitter: Data byte transmitter.  NACK received.
      // Use ACK polling to retry transfer.
      case SMB_MTDBNACK:
         STO = 1;
         STA = 1;
         SI = 0;                          // Clear interrupt flag
         break;

      // Master Transmitter: Arbitration lost.
      case SMB_MTARBLOST:
         LOST_COMMAND = COMMAND;          //
         LOST_WORD = WORD;                // Store variables for use when bus is free.
         LOST_CODE = OP_CODE;             //

         LOST = 1;                        // Set flag to retry transfer
                                          // when bus is free.
         SI = 0;                          // Clear interrupt flag
         break;

      // Master Receiver: Slave address + READ transmitted.  ACK received.
      // Set to transmit NACK after next transfer since it will be the 
      // last (only) byte.
      case SMB_MRADDACK:
         AA = 0;                          // NACK sent during acknowledge cycle.
         SI = 0;
         break;

      // Master Receiver: Slave address + READ transmitted.  NACK received.
      // Slave not responding. Send repeated START to try again.
      case SMB_MRADDNACK:
         STO = 0;
         STA = 1;
         SI = 0;
         break;

      // Master Receiver: Data byte received.  ACK transmitted.
      // State should not occur because AA is cleared in previous state.
      // Send STOP if state does occur.
      case SMB_MRDBACK:
         STO = 1;
         SM_BUSY = 0;
         SI = 0;
         break;

      // Master Receiver: Data byte received.  NACK transmitted.
      // Read operation has completed.  Read data register and send STOP.
      case SMB_MRDBNACK:
         WORD = SMB0DAT;
         STO = 1;
         SM_BUSY = 0;
         AA = 1;                          // Set AA for next transfer
         SI = 0;
         break;

      // Slave Receiver: Arbitration lost, general call address received.
      // Set LOST flag to retry transfer when bus is free.  Fall through.
      case SMB_SRGARBLOST:

      // Slave Receiver: Arbitration lost, own slave address + WRITE received.
      // Set LOST flag to retry transfer when bus is free.
      // Set STO bit to get out of master mode.
      case SMB_SROARBLOST:
         LOST_COMMAND = COMMAND;          //
         LOST_WORD = WORD;                // Store variables for use when bus is free.
         LOST_CODE = OP_CODE;             //
         LOST = 1;                        // Retry transfer when bus is free.
         SI = 0;
         break;

      // Slave Receiver: Slave address + WRITE received.  ACK transmitted. 
      // Fall through.
      case SMB_SROADACK:

      // Slave Receiver: General call address received.  ACK transmitted.
      case SMB_SRGADACK:
         SI = 0;
         break;

      // Slave Receiver: Data byte received after addressed by general
      // call address + WRITE.
      // ACK transmitted.  Fall through.
      case SMB_SRGDBACK:

      // Slave Receiver: Data byte received after addressed by own 
      // slave address + WRITE.
      // ACK transmitted.
      // Take action depending on OP_CODE or data received.
      case SMB_SRODBACK:
         if (!VALID_OP){                  // if VALID_OP=0, this byte is an OP_CODE.
            OP_CODE = SMB0DAT;            // Store OP_CODE
            VALID_OP = 1;                 // Next byte is not an OP_CODE
         } else {
            DATA_READY = 1;               // Valid data has been received.  Process 
                                          // in OP_CODE handler.
            WORD = SMB0DAT;               
            SI = 0;
         }
         break;

      // Slave Receiver: Data byte received while addressed as slave.  
      // NACK transmitted. Should not occur since AA will not be cleared
      // as slave.  Fall through to next state.
      case SMB_SRODBNACK:

      // Slave Receiver: Data byte received while addressed by general call.
      //  NACK transmitted.
      // Should not occur since AA will not be cleared as slave.
      case SMB_SRGDBNACK:
         AA = 1;
         SI = 0;
         break;

      // Slave Receiver: STOP or repeated START received while addressed as slave.
      case SMB_SRSTOP:
         SI = 0;
         break;

      // Slave Transmitter: Own slave address + READ received.  ACK transmitted.
      // Load SMB0DAT with data to be output.
      case SMB_STOADACK:
         SMB0DAT = WORD;
         SI = 0;
         break;

      // Slave Transmitter: Arbitration lost as master. Own address + READ received.
      // ACK transmitted.
      case SMB_STOARBLOST:
         LOST_COMMAND = COMMAND;          //
         LOST_WORD = WORD;                // Store variables for use when bus 
         LOST_CODE = OP_CODE;             // is free.
         LOST = 1;                        // Retry when bus is free.

         SI = 0;
         break;

      // Slave Transmitter: Data byte transmitted.  ACK received.  Fall through.
      case SMB_STDBACK:

      // Slave Transmitter: Data byte transmitted.  NACK received. Fall through.
      case SMB_STDBNACK:

      // Slave Transmitter: Last data byte transmitted.  ACK received.
      // No action necessary.
      case SMB_STDBLAST:
         SI = 0;
         break;

      // All other status codes invalid.  Reset communication.
      default:
         STO = 1;
         SM_BUSY = 0;
         break;
      }

}

⌨️ 快捷键说明

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