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

📄 smb_ex2.c

📁 c8051f020 i2c 源码。对其操作有详细描述。
💻 C
字号:
//------------------------------------------------------------------------------------
//
// Copyright 2001 Cygnal Integrated Products, Inc.
//
// FILE NAME      : SMB_Ex2.c
// TARGET DEVICE  : C8051F000
// CREATED ON     : 2/20/01
// CREATED BY     : JS
//
//
// Example code for interfacing a C8051F0xx to three EEPROMs via the SMBus.
// Code assumes that three 16-bit address space EEPROMs are connected
// on the SCL and SDA lines, and configured so that their slave addresses
// are as follows:
// CHIP_A = 1010000
// CHIP_B = 1010001
// CHIP_C = 1010010
//
// Slave and arbitration states are not defined.  Assume the CF000 is the only
// master in the system.
// Functions: SM_Send performs a 1-byte write to the specified EEPROM
// SM_Receive performs a 1-byte read of the specified EEPROM address (both include
// memory address references).
//
// Includes test code section.

//------------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------------
#include <c8051f000.h>              // SFR declarations

//------------------------------------------------------------------------------------
// Global CONSTANTS
//------------------------------------------------------------------------------------

#define WRITE 0x00                  // SMBus WRITE command
#define READ  0x01                  // SMBus READ command

// Device addresses (7 bits, lsb is a don't care)
#define CHIP_A 0xA0                 // Device address for chip A
#define CHIP_B 0xA2                 // Device address for chip B
#define CHIP_C 0xA4                 // Device address for chip C

// SMBus states:
// MT = Master Transmitter
// MR = Master Receiver
#define  SMB_BUS_ERROR  0x00        // (all modes) BUS ERROR
#define  SMB_START      0x08        // (MT & MR) START transmitted
#define  SMB_RP_START   0x10        // (MT & MR) repeated START
#define  SMB_MTADDACK   0x18        // (MT) Slave address + W transmitted;
                                    //  ACK received
#define  SMB_MTADDNACK  0x20        // (MT) Slave address + W transmitted;
                                    //  NACK received
#define  SMB_MTDBACK    0x28        // (MT) data byte transmitted; ACK rec'vd
#define  SMB_MTDBNACK   0x30        // (MT) data byte transmitted; NACK rec'vd
#define  SMB_MTARBLOST  0x38        // (MT) arbitration lost
#define  SMB_MRADDACK   0x40        // (MR) Slave address + R transmitted;
                                    //  ACK received
#define  SMB_MRADDNACK  0x48        // (MR) Slave address + R transmitted;
                                    //  NACK received
#define  SMB_MRDBACK    0x50        // (MR) data byte rec'vd; ACK transmitted
#define  SMB_MRDBNACK   0x58        // (MR) data byte rec'vd; NACK transmitted


//-----------------------------------------------------------------------------------
//Global VARIABLES
//-----------------------------------------------------------------------------------
char COMMAND;                       // Holds the slave address + R/W bit for
                                    // use in the SMBus ISR.

char WORD;                          // Holds data to be transmitted by the SMBus
                                    // OR data that has just been received.

char BYTE_NUMBER;                   // Used by ISR to check what data has just been
                                    // sent - High address byte, Low byte, or data
                                    // byte

unsigned char HIGH_ADD, LOW_ADD;    // High & Low byte for EEPROM memory address

bit SM_BUSY;                        // This bit is set when a send or receive
                                    // is started. It is cleared by the
                                    // ISR when the operation is finished.


//------------------------------------------------------------------------------------
// Function PROTOTYPES
//------------------------------------------------------------------------------------

void SMBus_ISR (void);
void SM_Send (char chip_select, unsigned int byte_address, char out_byte);
char SM_Receive (char chip_select, unsigned int byte_address);

//------------------------------------------------------------------------------------
// MAIN Routine
//------------------------------------------------------------------------------------
//
// Main routine configures the crossbar and SMBus, and tests
// the SMBus interface between the three EEPROMs
void main (void)
{
   unsigned char check;             // Used for testing purposes

   WDTCN = 0xde;                    // disable watchdog timer
   WDTCN = 0xad;

   OSCICN |= 0x03;                  // Set internal oscillator to highest setting
                                    // (16 MHz)

   XBR0 = 0x01;                     // Route SMBus to GPIO pins through crossbar
   XBR2 = 0x40;                     // Enable crossbar and weak pull-ups

   SMB0CN = 0x44;                   // Enable SMBus with ACKs on acknowledge 
                                    // cycle
   SMB0CR = -80;                    // SMBus clock rate = 100kHz.

   EIE1 |= 2;                       // SMBus interrupt enable
   EA = 1;                          // Global interrupt enable

   SM_BUSY = 0;                     // Free SMBus for first transfer.


// TEST CODE---------------------------------------------------------------------
   SM_Send(CHIP_A, 0x0088, 0x53);      // Send 0x53(data) to address 0x88 on CHIP_A
   SM_Send(CHIP_B, 0x0001, 0x66);      // Send 0x66(data) to address 0x01 on CHIP_B
   SM_Send(CHIP_C, 0x0010, 0x77);
   SM_Send(CHIP_B, 0x0333, 0xF0);
   SM_Send(CHIP_A, 0x0242, 0xF0);

   check = SM_Receive(CHIP_A, 0x0088); // Read address 0x88 on CHIP_A
   check = SM_Receive(CHIP_B, 0x0001); // Read address 0x01 on CHIP_B
   check = SM_Receive(CHIP_C, 0x0010);
   check = SM_Receive(CHIP_B, 0x0333);
   check = SM_Receive(CHIP_A, 0x0242);
// END TEST CODE-----------------------------------------------------------------

}


// SMBus byte write function-----------------------------------------------------
// Writes a single byte at the specified memory location.
//
// out_byte = data byte to be written
// byte_address = memory location to be written into (2 bytes)
// chip_select = device address of EEPROM chip to be written to
void SM_Send (char chip_select, unsigned int byte_address, char out_byte)
{
   while (SM_BUSY);                          // Wait for SMBus to be free.
   SM_BUSY = 1;                              // Occupy SMBus (set to busy)
   SMB0CN = 0x44;                            // SMBus enabled,
                                             // ACK on acknowledge cycle

   BYTE_NUMBER = 2;                          // 2 address bytes.
   COMMAND = (chip_select | WRITE);          // Chip select + WRITE

   HIGH_ADD = ((byte_address >> 8) & 0x00FF);// Upper 8 address bits
   LOW_ADD = (byte_address & 0x00FF);        // Lower 8 address bits

   WORD = out_byte;                          // Data to be writen
   
   STO = 0;
   STA = 1;                                  // Start transfer

}

// SMBus random read function------------------------------------------------------
// Reads 1 byte from the specified memory location.
//
// byte_address = memory address of byte to read
// chip_select = device address of EEPROM to be read from
char SM_Receive (char chip_select, unsigned int byte_address)
{
   while (SM_BUSY);                          // Wait for bus to be free.
   SM_BUSY = 1;                              // Occupy SMBus (set to busy)
   SMB0CN = 0x44;                            // SMBus enabled, ACK on acknowledge cycle

   BYTE_NUMBER = 2;                          // 2 address bytes
   COMMAND = (chip_select | READ);           // Chip select + READ

   HIGH_ADD = ((byte_address >> 8) & 0x00FF);// Upper 8 address bits
   LOW_ADD = (byte_address & 0x00FF);        // Lower 8 address bits
   
   STO = 0;
   STA = 1;                                  // Start transfer
   while (SM_BUSY);                          // Wait for transfer to finish
   return WORD;
}


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


// 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.
      // The R/W bit of the COMMAND word sent after this state will
      // always be a zero (W) because for both read and write,
      // the memory address must be written first.
      case SMB_START:
         SMB0DAT = (COMMAND & 0xFE);   // Load address of the slave to be accessed.
         STA = 0;                      // Manually clear START bit
         break;

      // Master Transmitter/Receiver: Repeated START condition transmitted.
      // This state should only occur during a read, after the memory address has been
      // sent and acknowledged.
      case SMB_RP_START:
         SMB0DAT = COMMAND;            // COMMAND should hold slave address + R.
         STA = 0;
         break;

      // Master Transmitter: Slave address + WRITE transmitted.  ACK received.
      case SMB_MTADDACK:
         SMB0DAT = HIGH_ADD;           // Load high byte of memory address
                                       // to be written.
         break;

      // Master Transmitter: Slave address + WRITE transmitted.  NACK received.
      // The slave is not responding.  Send a STOP followed by a START to try again.
      case SMB_MTADDNACK:
         STO = 1;
         STA = 1;
         break;

      // Master Transmitter: Data byte transmitted.  ACK received.
      // This state is used in both READ and WRITE operations.  Check BYTE_NUMBER
      // for memory address status - if only HIGH_ADD has been sent, load LOW_ADD.
      // If LOW_ADD has been sent, check COMMAND for R/W value to determine 
      // next state.
      case SMB_MTDBACK:
         switch (BYTE_NUMBER){
            case 2:                    // If BYTE_NUMBER=2, only HIGH_ADD
               SMB0DAT = LOW_ADD;      // has been sent.
               BYTE_NUMBER--;          // Decrement for next time around.
               break;
            case 1:                    // If BYTE_NUMBER=1, LOW_ADD was just sent.
               if (COMMAND & 0x01){    // If R/W=READ, sent repeated START.
                  STO = 0;
                  STA = 1;

               } else { 
                  SMB0DAT = WORD;      // If R/W=WRITE, load byte to write.
                  BYTE_NUMBER--;
               }
               break;
            default:                   // If BYTE_NUMBER=0, transfer is finished.
               STO = 1;
               SM_BUSY = 0;            // Free SMBus
            }
         break;


      // Master Transmitter: Data byte transmitted.  NACK received.
      // Slave not responding.  Send STOP followed by START to try again.
      case SMB_MTDBNACK:
         STO = 1;
         STA = 1;
         break;

      // Master Transmitter: Arbitration lost.
      // Should not occur.  If so, restart transfer.
      case SMB_MTARBLOST:
         STO = 1;
         STA = 1;
         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 on acknowledge cycle.
         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;
         break;

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

      // 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;                  // Free SMBus
         break;

      // All other status codes meaningless in this application. Reset communication.
      default:
         STO = 1;                      // Reset communication.
         SM_BUSY = 0;
         break;
      }

   SI=0;                               // clear interrupt flag
}

⌨️ 快捷键说明

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