//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <C8051F020.h> // SFR declarations
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define SYSCLK 4000000L // System clock frequency in Hz
#define SMB_FREQUENCY 10000L // Target SCL clock rate
// This example supports between 10kHz
// and 100kHz
#define WRITE 0x00 // WRITE direction bit
#define READ 0x01 // READ direction bit
// Device addresses (7 bits, lsb is a don't care)
#define SLAVE_ADDR 0x10 // Device address for slave target
#define MY_ADDR 0x02 // Address of this SMBus device
// (dummy value since this device does
// not have any defined slave states)
#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
//-----------------------------------------------------------------------------
unsigned char SMB_DATA_OUT; // Global holder for SMBus data.
// All transmit data is read from here
unsigned char 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
unsigned long NUM_ERRORS; // Counter for the number of errors.
// 16-bit SFR declarations
sfr16 TMR3RL = 0x92; // Timer3 reload registers
sfr16 TMR3 = 0x94; // Timer3 counter registers
sbit LED = P2^3; // LED on P1.6
sbit SDA = P0^0; // SMBus on P0.0
sbit SCL = P0^1; // and P0.1
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
void Port_Init(void);
void SMBus_Init(void);
void Timer3_Init(void);
void SMBus_ISR(void);
void Timer3_ISR(void);
void SMB_Write (void);
void T0_Wait_ms (unsigned char ms);
//-----------------------------------------------------------------------------
// SMB_Write
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Writes a single byte to the slave with address specified by the <TARGET>
// variable.
// Calling sequence:
// 1) Write target slave address to the <TARGET> variable
// 2) Write outgoing data to the <SMB_DATA_OUT> variable
// 3) Call SMB_Write()
//
void SMB_Write (void)
{
while (SMB_BUSY); // Wait for SMBus to be free.
SMB_BUSY = 1; // Claim SMBus (set to busy)
SMB_RW = 0; // Mark this transfer as a WRITE
STA = 1; // Start transfer
T0_Wait_ms (20);
}
//-----------------------------------------------------------------------------
void delay1ms(int time)
{
int i,j;
for(i=0;i<time;i++)
{
WDTCN = 0xa5;
for(j=0;j<100;j++);
}
}
void wrram(unsigned char wadr,unsigned char wdata)
{
SMB0CN = 0xc1;
STA = 1;
WAIT08H:if((SMB0STA!=0x08)&&(SMB0STA!=0x10)) goto WAIT08H;
SMB0DAT = 0xa1;
SMB0CN = 0xc1;
WAIT20H:if(SMB0STA!=0x20) goto WAIT20H;
SMB0DAT = wadr;
SMB0CN = 0xc1;
WAIT18H:if(SMB0STA!=0x28) goto WAIT18H;
SMB0DAT = wdata;
SMB0CN = 0xc1;
delay1ms(30);
WAIT18H1:if(SMB0STA!=0x28) goto WAIT18H1;
STO = 1;
SI = 0;
delay1ms(50);
}
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void MAIN (void)
{
unsigned char i; // Dummy variable counters
WDTCN = 0xde; // Disable watchdog timer
WDTCN = 0xad;
OSCICN = 0x05; // Set internal oscillator to run
// at 4 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.
XBR1 = 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
XBR1 = 0x00; // Disable Crossbar
}
Port_Init (); // Initialize Crossbar and GPIO
// Turn off the LED before the test starts
LED = 1;
SMBus_Init (); // Configure and enable SMBus
Timer3_Init (); // Configure and enable Timer3
EIE1 |= 0x02; // Enable the SMBus interrupt
EA = 1; // Global interrupt enable
SI = 0;
SMB_DATA_OUT = 34;
TARGET = 0x10;
SMB_Write();
T0_Wait_ms (1);
SMB_DATA_OUT = 12;
TARGET = 0x20;
SMB_Write();
T0_Wait_ms (1);
}
//-----------------------------------------------------------------------------
// Initialization Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
//