?? f500_smbus_master.c
字號:
//-----------------------------------------------------------------------------
// F500_SMBus_Master.c
//-----------------------------------------------------------------------------
// Copyright 2008 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// Example software to demonstrate the C8051F500 SMBus interface in
// Master mode.
// - Interrupt-driven SMBus implementation
// - Only master states defined (no slave or arbitration)
// - 1-byte SMBus data holders used for each transmit and receive
// - Timer1 used as SMBus clock source
// - Timer3 used by SMBus for SCL low timeout detection
// - SCL frequency defined by <SMB_FREQUENCY> constant
// - ARBLOST support included
// - Pinout:
// P0.0 -> SDA (SMBus)
// P0.1 -> SCL (SMBus)
// P1.3 -> LED
//
// all other port pins unused
//
// How To Test:
//
// 1) Verify that J22 is not populated.
// 2) Download code to a 'F500 device that is connected to a SMBus slave.
// 3) Run the code:
// a) The test will indicate proper communication with the slave by
// toggling the LED on and off each time a value is sent and
// received.
// b) The best method to view the proper functionality is to run to
// the indicated line of code in the TEST CODE section of main and
// view the SMB_DATA_IN and SMB_DATA_OUT variables in the Watch
// Window.
//
//
// Target: C8051F500 (Side A of a C8051F500-TB)
// Tool chain: Keil C51 8.0 / Keil EVAL C51
// Command Line: None
//
// Release 1.0 / 07 JUL 2008 (GP)
// -Initial Revision
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <compiler_defs.h>
#include <C8051F500_defs.h> // SFR declarations
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define SYSCLK 24000000 // System clock frequency in Hz
#define SMB_FREQUENCY 10000 // Target SCL clock rate
// This example supports between 10kHz
// and 100kHz
#define WRITE 0x00 // SMBus WRITE command
#define READ 0x01 // SMBus READ command
// Device addresses (7 bits, LSB is a don't care)
#define SLAVE_ADDR 0xF0 // Device address for slave target
// Status vector - top 4 bits only
#define SMB_MTSTA 0xE0 // (MT) start transmitted
#define SMB_MTDB 0xC0 // (MT) data byte transmitted
#define SMB_MRDB 0x80 // (MR) data byte received
// End status vector definition
//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
U8 SMB_DATA_IN; // Global holder for SMBus data
// All receive data is written here
U8 SMB_DATA_OUT; // Global holder for SMBus data.
// All transmit data is read from here
U8 TARGET; // Target SMBus slave address
bit SMB_BUSY; // Software flag to indicate when the
// SMB_Read() or SMB_Write() functions
// have claimed the SMBus
bit SMB_RW; // Software flag to indicate the
// direction of the current transfer
U16 NUM_ERRORS; // Counter for the number of errors.
SBIT (LED, SFR_P1, 3); // LED==1 means ON
SBIT (SDA, SFR_P0, 0); // SMBus on P0.0
SBIT (SCL, SFR_P0, 1); // and P0.1
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
void SMBUS0_Init (void);
void TIMER1_Init (void);
void TIMER3_Init (void);
void PORT_Init (void);
INTERRUPT_PROTO (TIMER3_ISR, INTERRUPT_TIMER3);
INTERRUPT_PROTO (SMBUS0_ISR, INTERRUPT_SMBUS0);
void SMB_Write (void);
void SMB_Read (void);
void T0_Wait_ms (U8 ms);
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
//
// Main routine performs all configuration tasks, then loops forever sending
// and receiving SMBus data to the slave <SLAVE_ADDR>.
//
void main (void)
{
volatile U8 dat; // Test counter
U8 i; // Dummy variable counters
SFRPAGE = ACTIVE_PAGE; // Set SFR Page for PCA0
PCA0MD = 0x00; // Disable watchdog timer
SFRPAGE = CONFIG_PAGE; // Set SFR Page for XBR and port pins
OSCICN |= 0x07; // Set internal oscillator to 24 MHz
// If slave is holding SDA low because of an improper SMBus reset or error
while(!SDA)
{
// Provide clock pulses to allow the slave to advance out
// of its current state. This will allow it to release SDA.
XBR2 = 0x40; // Enable Crossbar
SCL = 0; // Drive the clock low
for(i = 0; i < 255; i++); // Hold the clock low
SCL = 1; // Release the clock
while(!SCL); // Wait for open-drain
// clock output to rise
for(i = 0; i < 10; i++); // Hold the clock high
XBR2 = 0x00; // Disable Crossbar
}
PORT_Init (); // Initialize Crossbar and GPIO
TIMER1_Init (); // Configure Timer1 for use as SMBus
// clock source
TIMER3_Init (); // Configure Timer3 for use with SMBus
// low timeout detect
SMBUS0_Init (); // Configure and enable SMBus
EIE1 |= 0x01; // Enable the SMBus interrupt
LED = 0;
EA = 1; // Global interrupt enable
// TEST CODE-------------------------------------------------------------------
dat = 0; // Output data counter
NUM_ERRORS = 0; // Error counter
while (1)
{
// SMBus Write Sequence
SMB_DATA_OUT = dat; // Define next outgoing byte
TARGET = SLAVE_ADDR; // Target the F3xx/Si8250 Slave for next
// SMBus transfer
SMB_Write(); // Initiate SMBus write
// SMBus Read Sequence
TARGET = SLAVE_ADDR; // Target the F3xx/Si8250 Slave for next
// SMBus transfer
SMB_Read();
// Check transfer data
if(SMB_DATA_IN != SMB_DATA_OUT) // Received data match transmit data?
{
NUM_ERRORS++; // Increment error counter if no match
}
// Indicate that an error has occurred (LED no longer lit)
if (NUM_ERRORS > 0)
{
LED = 0;
}
else
{
LED = !LED;
}
// Run to here to view the SMB_DATA_IN and SMB_DATA_OUT variables
dat++;
T0_Wait_ms (50); // Wait 50 ms until the next cycle
// so that LED blinks slow enough to see
}
// END TEST CODE---------------------------------------------------------------
}
//-----------------------------------------------------------------------------
// Initialization Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SMBUS0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// SMBus configured as follows:
// - SMBus enabled
// - Slave mode inhibited
// - Timer1 used as clock source. The maximum SCL frequency will be
// approximately 1/3 the Timer1 overflow rate
// - Setup and hold time extensions enabled
// - Bus Free and SCL Low timeout detection enabled
//
//-----------------------------------------------------------------------------
void SMBUS0_Init (void)
{
U8 SFRPAGE_save = SFRPAGE;
SFRPAGE = ACTIVE_PAGE;
SMB0CF = 0x5D; // Use Timer1 overflows as SMBus clock
// source;
// Disable slave mode;
// Enable setup & hold time
// extensions;
// Enable SMBus Free timeout detect;
// Enable SCL low timeout detect;
SMB0CF |= 0x80; // Enable SMBus;
SFRPAGE = SFRPAGE_save;
}
//-----------------------------------------------------------------------------
// TIMER1_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Timer1 configured as the SMBus clock source as follows:
// - Timer1 in 8-bit auto-reload mode
// - SYSCLK or SYSCLK / 4 as Timer1 clock source
// - Timer1 overflow rate => 3 * SMB_FREQUENCY
// - The resulting SCL clock rate will be ~1/3 the Timer1 overflow rate
// - Timer1 enabled
//
//-----------------------------------------------------------------------------
void TIMER1_Init (void)
{
U8 SFRPAGE_save = SFRPAGE;
SFRPAGE = ACTIVE_PAGE;
// Make sure the Timer can produce the appropriate frequency in 8-bit mode
// Supported SMBus Frequencies range from 10kHz to 100kHz. The CKCON register
// settings may need to change for frequencies outside this range.
#if ((SYSCLK/SMB_FREQUENCY/3) < 255)
#define SCALE 1
CKCON |= 0x08; // Timer1 clock source = SYSCLK
#elif ((SYSCLK/SMB_FREQUENCY/4/3) < 255)
#define SCALE 4
CKCON |= 0x01;
CKCON &= ~0x0A; // Timer1 clock source = SYSCLK / 4
#endif
TMOD = 0x20; // Timer1 in 8-bit auto-reload mode
// Timer1 configured to overflow at 1/3 the rate defined by SMB_FREQUENCY
TH1 = -(S8)(SYSCLK/SMB_FREQUENCY/SCALE/3);
TL1 = TH1; // Init Timer1
TR1 = 1; // Timer1 enabled
SFRPAGE = SFRPAGE_save;
}
//-----------------------------------------------------------------------------
// TIMER3_Init
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -