📄 f500_smbus_eeprom.c
字号:
//-----------------------------------------------------------------------------
// F500_SMBus_EEPROM.c
//-----------------------------------------------------------------------------
// Copyright 2008 Silicon Laboratories, Inc.
// http://www.silabs.com
//
// Program Description:
//
// This example demonstrates how the C8051F500 SMBus interface can communicate
// with a 256 byte I2C Serial EEPROM (Microchip 24LC02B).
// - Interrupt-driven SMBus implementation
// - Only master states defined (no slave or arbitration)
// - Timer1 used as SMBus clock source
// - Timer2 used by SMBus for SCL low timeout detection
// - SCL frequency defined by <SMB_FREQUENCY> constant
// - 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 24LC02B serial
// EEPROM (see the EEPROM datasheet for the pinout information).
// 3) Run the code:
// a) the test will indicate proper communication with the EEPROM by
// turning on the LED at the end the end of the test
// b) the test can also be verified by running to the if statements
// in main and checking the sent and received values by adding
// the variables to 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 / 04 MAR 2008 (GP)
// -Initial Revision
//
//-----------------------------------------------------------------------------
// Includes and Device-Specific Parameters
//-----------------------------------------------------------------------------
#include <compiler_defs.h>
#include <C8051F500_defs.h> // SFR declarations
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define SYSCLK 24000000 // System clock frequency in Hz
#define SMB_FREQUENCY 50000 // 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 EEPROM_ADDR 0xA0 // Device address for slave target
// Note: This address is specified
// in the Microchip 24LC02B
// datasheet.
// SMBus Buffer Size
#define SMB_BUFF_SIZE 0x08 // Defines the maximum number of bytes
// that can be sent or received in a
// single transfer
// 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* pSMB_DATA_IN; // Global pointer for SMBus data
// All receive data is written here
U8 SMB_SINGLEBYTE_OUT; // Global holder for single byte writes.
U8* pSMB_DATA_OUT; // Global pointer for SMBus data.
// All transmit data is read from here
U8 SMB_DATA_LEN; // Global holder for number of bytes
// to send or receive in the current
// SMBus transfer.
U8 WORD_ADDR; // Global holder for the EEPROM word
// address that will be accessed in
// the next transfer
U8 TARGET; // Target SMBus slave address
bit SMB_BUSY = 0; // Software flag to indicate when the
// EEPROM_ByteRead() or
// EEPROM_ByteWrite()
// functions have claimed the SMBus
bit SMB_RW; // Software flag to indicate the
// direction of the current transfer
bit SMB_SENDWORDADDR; // When set, this flag causes the ISR
// to send the 8-bit <WORD_ADDR>
// after sending the slave address.
bit SMB_RANDOMREAD; // When set, this flag causes the ISR
// to send a START signal after sending
// the word address.
// For the 24LC02B EEPROM, a random read
// (a read from a particular address in
// memory) starts as a write then
// changes to a read after the repeated
// start is sent. The ISR handles this
// switchover if the <SMB_RANDOMREAD>
// bit is set.
bit SMB_ACKPOLL; // When set, this flag causes the ISR
// to send a repeated START until the
// slave has acknowledged its address
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 EEPROM_ByteWrite(U8 addr, U8 dat);
void EEPROM_WriteArray(U8 dest_addr, U8* src_addr, U8 len);
U8 EEPROM_ByteRead(U8 addr);
void EEPROM_ReadArray(U8* dest_addr, U8 src_addr, U8 len);
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
//
// Main routine performs all configuration tasks, then loops forever sending
// and receiving SMBus data to the slave EEPROM.
//
//-----------------------------------------------------------------------------
void main (void)
{
U8 in_buff[8] = {0}; // Incoming data buffer
U8 out_buff[8] = "ABCDEFG"; // Outgoing data buffer
U8 temp_char; // Temporary variable
bit error_flag = 0; // Flag for checking EEPROM contents
U8 i; // Temporary counter variable
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
LED = 0; // Turn off the LED before the test
// starts
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
EA = 1; // Global interrupt enable
// Read and write some bytes to the EEPROM and check for proper
// communication
// Write the value 0xAA to location 0x25 in the EEPROM
EEPROM_ByteWrite(0x25, 0xAA);
// Read the value at location 0x25 in the EEPROM
temp_char = EEPROM_ByteRead(0x25);
// Check that the data was read properly
if (temp_char != 0xAA)
{
error_flag = 1;
}
// Write the value 0xBB to location 0x25 in the EEPROM
EEPROM_ByteWrite(0x25, 0xBB);
// Write the value 0xCC to location 0x38 in the EEPROM
EEPROM_ByteWrite(0x38, 0xCC);
// Read the value at location 0x25 in the EEPROM
temp_char = EEPROM_ByteRead(0x25);
// Check that the data was read properly
if (temp_char != 0xBB)
{
error_flag = 1;
}
// Read the value at location 0x38 in the EEPROM
temp_char = EEPROM_ByteRead(0x38);
// Check that the data was read properly
if (temp_char != 0xCC)
{
error_flag = 1;
}
// Store the outgoing data buffer at EEPROM address 0x50
EEPROM_WriteArray(0x50, out_buff, sizeof(out_buff));
// Fill the incoming data buffer with data starting at EEPROM address 0x50
EEPROM_ReadArray(in_buff, 0x50, sizeof(in_buff));
// Check that the data that came from the EEPROM is the same as what was
// sent
for (i = 0; i < sizeof(in_buff); i++)
{
if (in_buff[i] != out_buff[i])
{
error_flag = 1;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -