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

📄 8051 smb.c

📁 SMBUS function by 8051 partI
💻 C
📖 第 1 页 / 共 2 页
字号:
//------------------------------------------------------------------------------------
//
// Copyright 2001 Cygnal Integrated Products, Inc.
//
// FILE NAME      : SMB_Ex3.c
// TARGET DEVICE  : C8051F000
// CREATED ON     : 2/20/01
// CREATED BY     : JS
//
// Example code to demonstrate the use of the SMBus interface between two CF000 devices.
// The devices operate in a peer-to-peer configuration.
//
// Demonstration includes use of op codes for each device to command the other to:
//
// 1) Write a byte to DAC0
// 2) Write a byte to a data buffer
// 3) Perform an ADC conversion
// 4) Read a byte from a data buffer
//
// These op codes are can be tested easily if each chip has DAC0 routed to AIN0.
// With this configuration, a READ_ADC command can be used to test the output
// of a WRITE_DAC command.
//
// Code assumes that two CF0xx devices are connected via SCL and SDA, with
// slave addresses (held by register SMB0ADR)
// CHIP_A = 1111000
// CHIP_B = 1110000
//
// Test code is included.  For testing purposes, the test code should be omitted
// in one device, and run in the other.  This can be accomplished by commenting
// the OP_CODE_HANDLER() call before the test code in the device that will assume
// the master role.
//
// PLEASE NOTE that the constant MY_ADD must correspond with the
// current device - change it to CHIP_B when downloading code to CHIP_B.
//
//------------------------------------------------------------------------------------


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

#define  WRITE       0x00                 // WRITE direction bit
#define  READ        0x01                 // READ direction bit

// Device addresses
#define  CHIP_A      0xF0
#define  CHIP_B      0xE0
#define  MY_ADD      CHIP_A               // Corresponds to the chip currently
                                          // being programmed.

// Peer-to-Peer OP_CODEs
#define  READ_ADC    0x01                 // OP_CODE to read from slave ADC
#define  WRITE_DAC   0x02                 // OP_CODE to write to slave DAC
#define  WRITE_BUF   0x03                 // OP_CODE to write to slave buffer
#define  READ_BUF    0x04                 // OP_CODE to read from slave buffer

//SMBus states:
// MT = Master Transmitter
// MR = Master Receiver
// ST = Slave Transmitter
// SR = Slave 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
#define  SMB_SROADACK   0x60              // (SR) SMB's own slave address + W rec'vd;
                                          //  ACK transmitted
#define  SMB_SROARBLOST 0x68              // (SR) SMB's own slave address + W rec'vd;
                                          //  arbitration lost
#define  SMB_SRGADACK   0x70              // (SR) general call address rec'vd;
                                          //  ACK transmitted
#define  SMB_SRGARBLOST 0x78              // (SR) arbitration lost when transmitting
                                          //  slave addr + R/W as master; general
                                          //  call address rec'vd; ACK transmitted
#define  SMB_SRODBACK   0x80              // (SR) data byte received under own slave
                                          //  address; ACK returned
#define  SMB_SRODBNACK  0x88              // (SR) data byte received under own slave
                                          //  address; NACK returned
#define  SMB_SRGDBACK   0x90              // (SR) data byte received under general
                                          //  call address; ACK returned
#define  SMB_SRGDBNACK  0x98              // (SR) data byte received under general
                                          //  call address; NACK returned
#define  SMB_SRSTOP     0xa0              // (SR) STOP or repeated START received
                                          //  while addressed as a slave
#define  SMB_STOADACK   0xa8              // (ST) SMB's own slave address + R rec'vd;
                                          //  ACK transmitted
#define  SMB_STOARBLOST 0xb0              // (ST) arbitration lost in transmitting
                                          //  slave address + R/W as master; own
                                          //  slave address rec'vd; ACK transmitted
#define  SMB_STDBACK    0xb8              // (ST) data byte transmitted; ACK rec'ed
#define  SMB_STDBNACK   0xc0              // (ST) data byte transmitted; NACK rec'ed
#define  SMB_STDBLAST   0xc8              // (ST) last data byte transmitted (AA=0);
                                          //  ACK received
#define  SMB_SCLHIGHTO  0xd0              // (ST & SR) SCL clock high timer per
                                          //  SMB0CR timed out (FTE=1)
#define  SMB_IDLE       0xf8              // (all modes) Idle


//-----------------------------------------------------------------------------------
//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 OP_CODE;                             // Holds an op code to be sent or one
                                          // that has just been received.

char LOST_COMMAND, LOST_WORD, LOST_CODE;  // Used to hold relevant data after a
                                          // lost arbitration.

char DATA_BUF[16];                        // Data buffer accessed by OP_CODE_HANDLER

bit LOST;                                 // Arbitration lost flag, set when
                                          // arbitration is lost while in master mode.
                                          // Used to resume a failed transfer.

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.

bit VALID_OP;                             // Flag used to determine if byte received
                                          // as a slave is an OP_CODE or data.

bit DATA_READY;                           // Used by OP_CODE handler to flag when
                                          // valid data has been received from the
                                          // master

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

void SMBUS_ISR (void);
char SLA_READ(char chip_select, char out_op);
void SLA_SEND(char chip_select, char out_op, char out_data);
void OP_CODE_HANDLER(void);

//------------------------------------------------------------------------------------
// MAIN Routine
//------------------------------------------------------------------------------------

void MAIN (void)
{
   char i, check_1, check_2;              // Variables used for testing purposes only.

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

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

   SMB0CN = 0x44;                         // Enable SMBus with acknowledge low (AA = 1)
   SMB0CR = -80;                          // SMBus clock rate = 100 kHz
   SMB0ADR = MY_ADD;                      // Set own slave address.

   ADC0CN = 0x80;                         // Enable ADC, conversions to start with 
                                          // write to ADBUSY.

   ADC0CN |= 0x01;                        // ADC data registers left-justified.

   DAC0CN = 0x84;                         // enable DAC0, with left justified data
                                          // registers.

   REF0CN = 0x03;                         // reference voltage enabled.

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

   SM_BUSY = 0;                           // Free bus for first transfer.
   SI = 0;                                //

// OP_CODE_HANDLER();                     // This line should be commented in only
                                          // one of the two peer devices.  It is
                                          // for testing purposes only.
                                          // In a normal setup, the OP_CODE_HANDLER 
                                          // would be running at all times in order
                                          // to react to OP_CODES being sent to the
                                          // device.

// TEST CODE--------------------------------------------------------------------------
// This code is used only to test the interface between the two devices. If
// the above OP_CODE_HANDLER line is commented out, this device assumes the master 
// role. The other device should be running the OP_CODE_HANDLER at all times, to 
// respond to the OP_CODEs below.

   SLA_SEND(CHIP_B, (0x40 | WRITE_BUF), 0x24);     // Write to index 4
                                                   // in the data buffer
   SLA_SEND(CHIP_B, (0x60 | WRITE_BUF), 0x25);     // Write to index 6
   SLA_SEND(CHIP_B, (0x80 | WRITE_BUF), 0x26);     // Write to index 8
   SLA_SEND(CHIP_B, (0x10 | WRITE_BUF), 0x27);     // Write to index 1

   check_1 = SLA_READ(CHIP_B, (0x40 | READ_BUF));  // Read index 4 from the buffer
   check_1 = SLA_READ(CHIP_B, (0x60 | READ_BUF));  // Read index 6
   check_1 = SLA_READ(CHIP_B, (0x80 | READ_BUF));  // Read index 8
   check_1 = SLA_READ(CHIP_B, (0x10 | READ_BUF));  // Read index 1


// Loop to continuously increase the DAC output on CHIP_B, and read its
// ADC each round. DAC output on CHIP_B should ramp.

   for (i=0;i<50;i++){
      SLA_SEND(CHIP_B, WRITE_DAC, 2*i);            // Write 2*i to DAC0 on CHIP_B
      check_1 = SLA_READ(CHIP_B, READ_ADC);        // Read AIN0 on CHIP_B
      check_2 = 2*i;}                              // check_1 should be approximately
                                                   // the same as check_2.
// END TEST CODE----------------------------------------------------------------------

}

//------------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------------

// Send to slave.
// The send function transmits two bytes to the slave device: an op code, and a data
// byte.  There are two op code choices for sending data: WRITE_DAC and WRITE_BUF.
// If the op code is WRITE_BUF, then the upper 4 bits of the op code should contain
// the buffer index.  For example, to write to index 2 of the data buffer, the
// op_code parameter should be (0x20 | WRITE_BUF).
//
// chip_select = address of slave device.
// out_op = OP_CODE to be sent.
// out_data = data byte to be sent.
void SLA_SEND(char chip_select, char out_op, char out_data){

   while(SM_BUSY);                        // Wait while SMBus is busy.
   SM_BUSY = 1;                           // SMBus busy flag set.
   SMB0CN = 0x44;                         // SMBus enabled, ACK low.
   COMMAND = (chip_select | WRITE);       // COMMAND = 7 address bits + WRITE.
   OP_CODE = out_op;                      // WORD = OP_CODE to be transmitted.
   WORD = out_data;                       // DATA = data to be transmitted.
   STO = 0;
   STA = 1;                               // Start transfer.

}

// Read from slave.
// The read function transmits a 1-byte op code, then issues a repeated start
// to request a 1-byte read.  The two op code choices are READ_ADC and READ_BUF.
// If the op code is READ_BUF, then the upper 4 bits of the op code should
// contain the buffer index.  For example, to read index 5 of the data buffer,
// the op code should be (0x50 | READ_BUF).
//
// chip_select = address of slave device.
// out_op = OP_CODE to be sent.
char SLA_READ(char chip_select, char out_op){

   while(SM_BUSY);                        // Wait while SMBus is busy.
   SM_BUSY = 1;                           // Set busy flag.
   SMB0CN = 0x44;                         // Enable SMBus, ACK low.
   COMMAND = (chip_select | READ);        // COMMAND = 7 address bits + READ
   OP_CODE = out_op;
   STO = 0;
   STA = 1;                               // Start transfer.
   while(SM_BUSY);                        // Wait for transfer to finish.
   return WORD;                           // Return received word.

}


// OP_CODE handler.
// Decodes incoming op codes and performs tasks according to those op codes.
// A call to this function runs forever.
//
// The VALID_OP bit flags when a valid op code has been received.  Upon receipt,
// the handler decodes the op code, performs the task, then clears
// VALID_OP to wait for another code.
void OP_CODE_HANDLER(void){

   char index;                            // data buffer index
   while (1){                             // run forever
      VALID_OP = 0;                       // Wait for a valid OP_CODE
      while (!VALID_OP);                  //

      // The lower 4 bits of the OP_CODE are used to determine the action, while the
      // upper 4 bits are used to index the DATA_BUF array when the READ_BUF or

⌨️ 快捷键说明

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