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

📄 smbus_slave_f30x.c

📁 c8051f的IIC读取eeprom,有很好的程序结构
💻 C
字号:
//------------------------------------------------------------------------------------
//
// Copyright 2003 Cygnal Integrated Products, Inc.
//
// FILE NAME      : SMBus_Slave_F30x.c
// TARGET DEVICE  : C8051F300
// CREATED ON     : 01/02
// CREATED BY     : JS
//
// Revision 1.1 (11/18/02)
//
// Example software to demonstrate the C8051F30x SMBus interface in Slave mode
// - Interrupt-driven SMBus implementation
// - Only slave states defined
// - 1-byte SMBus data holder used for both transmit and receive
// - Timer1 used as SMBus clock rate (used only for free timeout detection)
// - Timer2 used by SMBus for SCL low timeout detection
// - Pinout:
//    P0.0 -> SDA (SMBus)
//    P0.1 -> SCL (SMBus)
//    P0.2 -> unused
//    P0.3 -> SW2
//    P0.4 -> unused
//    P0.5 -> unused
//    P0.6 -> unused
//    P0.7 -> C2D (debug interface)
//
//------------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------------
#include <c8051f300.h>                       // SFR declarations
#include <stdio.h>

//------------------------------------------------------------------------------------
// Global Constants
//------------------------------------------------------------------------------------
#define  SYSCLK         24500000             // System clock frequency
#define  SMB_FREQUENCY  50000                // Target SMBus frequency

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

#define  SLA_ADD        0xF0                 // Device addresses (7 bits, lsb is a
                                             // don't care)

// Status vector - top 4 bits only
#define  SMB_SRADD      0x20                 // (SR) slave address received
                                             // (also could be a lost arbitration)
#define  SMB_SRSTO      0x10                 // (SR) STOP detected, or lost
                                             // arbitration
#define  SMB_SRDB       0x00                 // (SR) data byte received, or lost
                                             // arbitration
#define  SMB_STDB       0x40                 // (ST) data byte transmitted
#define  SMB_STSTO      0x50                 // (ST) STOP detected


//-----------------------------------------------------------------------------------
//Global VARIABLES
//-----------------------------------------------------------------------------------
unsigned char SMB_DATA;                      // Global holder for SMBus data.
                                             // All receive data is written here;
                                             // all transmit data is read from here

bit DATA_READY;                              // Set to '1' by the SMBus ISR when
                                             // a new data byte has been received.

// 16-bit SFR declarations
sfr16    TMR2RL   = 0xca;                    // Timer2 reload registers
sfr16    TMR2     = 0xcc;                    // Timer2 counter registers

sbit  LED = P0^2;

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

void SMBus_Init (void);
void Timer1_Init (void);
void Timer2_Init (void);
void Port_Init (void);
void SMBus_ISR (void);
void Timer2_ISR (void);

//-----------------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------------
//
// Main routine performs all configuration tasks, then waits for SMBus communication.
void main (void)
{
   PCA0MD &= ~0x40;                          // WDTE = 0 (Disable watchdog timer)

   OSCICN |= 0x03;                           // Set internal oscillator to highest
                                             // setting
   Port_Init ();                             // Initialize Crossbar and GPIO
   Timer1_Init();                            // Configure Timer1 for use with SMBus
                                             // free timeout detect

   Timer2_Init ();                           // Configure Timer2 for use with SMBus
                                             // low timeout detect

   SMBus_Init ();                            // Configure and enable SMBus

   EIE1 |= 1;                                // SMBus interrupt enable
   IE |= 0x20;                               // Timer2 interrupt enable
   EA = 1;                                   // Global interrupt enable

   SMB_DATA = 0xFD;                          // Initialize SMBus data holder

   while(1)
   {
      while(!DATA_READY);                    // New SMBus data received?
      DATA_READY = 0;
   }
}

//------------------------------------------------------------------------------------
// Initialization Routines
//------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------
// SMBus_Init()
//------------------------------------------------------------------------------------
//
// SMBus configured as follows:
// - SMBus enabled
// - Slave mode enabled
// - Setup and hold time extensions enabled
// - Free and SCL low timeout detection enabled
//
void SMBus_Init (void)
{
   SMB0CF = 0x1D;                            // Use Timer1 overflows as SMBus clock
                                             // source
                                             // Enable slave mode
                                             // Enable setup & hold time extensions
                                             // Enable SMBus Free timeout detect
                                             // Enable SCL low timeout detect

   SMB0CF |= 0x80;                           // Enable SMBus;
}

//------------------------------------------------------------------------------------
// Timer2_Init()
//------------------------------------------------------------------------------------
//
// Timer2 configured for use by the SMBus low timeout detect feature as follows:
// - Timer2 in 16-bit auto-reload mode
// - SYSCLK/12 as Timer2 clock source
// - Timer2 reload registers loaded for a 25ms overflow period
// - Timer2 pre-loaded to overflow after 25ms
// - Timer2 enabled
//
void Timer2_Init (void)
{
   TMR2CN = 0x00;                            // Timer2 configured for 16-bit
                                             // auto-reload, low-byte interrupt
                                             // disabled

   TMR2 = -(SYSCLK/12/40);                   // Timer2 configured to overflow after
   TMR2RL = -(SYSCLK/12/40);                 // ~25ms (for SMBus low timeout detect)

   CKCON &= ~0x20;                           // Timer2 uses SYSCLK/12
   TR2 = 1;                                  // Start Timer2
}

//------------------------------------------------------------------------------------
// Timer1_Init()
//------------------------------------------------------------------------------------
//
// Timer1 configured as the SMBus clock source (for free timeout detection):
// - Timer1 in 8-bit auto-reload mode
// - SYSCLK / 12 as Timer1 clock source
// - Timer1 overflow rate => 3 * SMB_FREQUENCY
// - Free timeout period will be ~10 * Timer1 overflow rate
// - Timer1 enabled
//
void Timer1_Init (void)
{
   CKCON &= ~0x13;                           // Timer1 clock source = SYSCLK / 12
   TMOD = 0x02;                              // Timer1 in 8-bit auto-reload mode

   TH1 = -(SYSCLK/SMB_FREQUENCY/12/3);       // Timer1 configured to overflow at 1/3
                                             // the rate defined by SMB_FREQUENCY

   TL1 = -(SYSCLK/SMB_FREQUENCY/12/3);       // Timer1 preloaded to overflow at the
                                             // rate defined by SMB_FREQUENCY

   TR1 = 1;                                  // Timer1 enabled
}

//------------------------------------------------------------------------------------
// PORT_Init
//------------------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports.
// P0.0 - SDA
// P0.1 - SCL
// P0.2 -
// P0.3 -
// P0.4 -
// P0.5 -
// P0.6 -
// P0.7 - C2D
//
void Port_Init (void)
{
   XBR0 = 0x00;                              // No pins skipped
   XBR1 = 0x04;                              // Enable SMBus pins
   XBR2 = 0x40;                              // Enable crossbar and weak pull-ups

   P0MDIN = 0xFF;                            // All P0 pins digital input

   P0MDOUT = 0x00;                           // All P0 pins open-drain output
   P0 = 0xFF;                                //
}

//------------------------------------------------------------------------------------
// Interrupt Service Routines
//------------------------------------------------------------------------------------

//------------------------------------------------------------------------------------
// SMBus Interrupt Service Routine (ISR)
//------------------------------------------------------------------------------------
//
// SMBus ISR state machine
// - Slave only implementation - no master states defined
// - All incoming data is written to global variable <SMB_DATA>
// - All outgoing data is read from global variable <SMB_DATA>
//
void SMBUS_ISR (void) interrupt 6
{
   bit RXTX;                                 // Software flag for slave
                                             // receiver-to-transmitter transition

   switch (SMB0CN & 0xF0)                    // Decode the SMBus status vector
   {
      // Slave Receiver: Start+Address received
      case  SMB_SRADD:
         if((SMB0DAT&0xFE) == SLA_ADD)       // Decode address
         {                                   // If the received address matches,
            STA = 0;                         // Clear STA bit
            ACK = 1;                         // ACK the received slave address
            if(SMB0DAT&0x01==READ)           // If the transfer is a master READ,
            {
               SMB0DAT = SMB_DATA;           // Prepare outgoing byte
               if(!(SMB0DAT&0x80))           // If data byte MSB = '0',
               {
                  STO = 1;                   // Set STO to force outgoing MSB => '0'
                  RXTX = 1;                  // Set receiver-to-transmitter flag
               }
            }
         }
         else                                // If received slave address does not
         {                                   // match,
            ACK = 0;                         // NACK received address
         }
         break;

      // Slave Receiver: Data received
      case  SMB_SRDB:
         SMB_DATA = SMB0DAT;                 // Store incoming data
         DATA_READY = 1;                     // Indicate new data received
         ACK = 1;                            // ACK received data
         break;

      // Slave Receiver: Stop received
      case  SMB_SRSTO:
         STO = 0;                            // STO must be cleared by software when
                                             // a STOP is detected as a slave
         break;

      // Slave Transmitter: Data byte transmitted
      case  SMB_STDB:
                                             // No action required;
                                             // one-byte transfers
                                             // only for this example
         break;

      // Slave Transmitter: Arbitration lost, Stop detected
      case  SMB_STSTO:
         break;                              // No action required

      // Default: all other cases undefined
      default:
         SMB0CN &= ~0x40;                    // Reset communication.
         SMB0CN |= 0x40;
         break;
      }
   SI=0;                                     // Clear SMBus interrupt flag

  if (RXTX)                                  // If RXTX flag is set, the last state
  {                                          // was a receiver-to-transmitter
                                             // transition;
      while(!TXMODE);                        // Wait for slave to enter transmit mode,
      STO = 0;                               // Clear the STO bit and the RXTX flag
      RXTX = 0;
   }
}

//-----------------------------------------------------------------------------------
// Timer2 Interrupt Service Routine (ISR)
//-----------------------------------------------------------------------------------
//
// A Timer2 interrupt indicates an SMBus SCL low timeout.
// The SMBus is disabled and re-enabled here
//
void Timer2_ISR (void) interrupt 5
{
   SMB0CN &= ~0x40;                          // Disable SMBus
   SMB0CN |= 0x40;                           // Re-enable SMBus
   TF2H = 0;                                 // Clear Timer2 interrupt-pending flag
}

⌨️ 快捷键说明

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