📄 f36x_smbus_eeprom.c
字号:
// sent
for (i = 0; i < sizeof(in_buff); i++)
{
if (in_buff[i] != out_buff[i])
{
error_flag = 1;
}
}
// Indicate communication is good
if (error_flag == 0)
{
// LED = ON indicates that the test passed
LED = 1;
}
while(1);
}
//-----------------------------------------------------------------------------
// Initialization Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SMBus_Init()
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// The SMBus peripheral is configured as follows:
// - SMBus enabled
// - Slave mode disabled
// - Timer1 used as clock source. The maximum SCL frequency will be
// approximately 1/3 the Timer1 overflow rate
// - Setup and hold time extensions enabled
// - Free and SCL low timeout detection enabled
//
void SMBus_Init (void)
{
unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE
SFRPAGE = CONFIG_PAGE; // Switch to the necessary SFRPAGE
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; // Restore the SFRPAGE
}
//-----------------------------------------------------------------------------
// Timer1_Init()
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Timer1 is configured as the SMBus clock source as follows:
// - Timer1 in 8-bit auto-reload mode
// - SYSCLK / 12 as Timer1 clock source
// - Timer1 overflow rate => 3 * SMB_FREQUENCY
// - The maximum SCL clock rate will be ~1/3 the Timer1 overflow rate
// - Timer1 enabled
//
void Timer1_Init (void)
{
unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE
SFRPAGE = CONFIG_PAGE; // Switch to the necessary SFRPAGE
// 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
#elif ((SYSCLK/SMB_FREQUENCY/12/3) < 255)
#define SCALE 8
CKCON &= ~0x0B; // Timer1 clock source = SYSCLK / 12
#elif ((SYSCLK/SMB_FREQUENCY/48/3) < 255)
#define SCALE 4
CKCON |= 0x02;
CKCON &= ~0x09; // Timer1 clock source = SYSCLK / 48
#else
#error "Error: Timer1 cannot produce the desired SMBus frequency"
#endif
TMOD = 0x20; // 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 = TH1; // Init Timer1
TR1 = 1; // Timer1 enabled
SFRPAGE = SFRPAGE_save; // Restore the SFRPAGE
}
//-----------------------------------------------------------------------------
// Timer3_Init()
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Timer3 configured for use by the SMBus low timeout detect feature as
// follows:
// - Timer3 in 16-bit auto-reload mode
// - SYSCLK/12 as Timer3 clock source
// - Timer3 reload registers loaded for a 25ms overflow period
// - Timer3 pre-loaded to overflow after 25ms
// - Timer3 enabled
//
void Timer3_Init (void)
{
unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE
SFRPAGE = CONFIG_PAGE; // Switch to the necessary SFRPAGE
TMR3CN = 0x00; // Timer3 configured for 16-bit auto-
// reload, low-byte interrupt disabled
CKCON &= ~0x40; // Timer3 uses SYSCLK/12
TMR3RL = -(SYSCLK/12/40); // Timer3 configured to overflow after
TMR3 = TMR3RL; // ~25ms (for SMBus low timeout detect)
EIE1 |= 0x80; // Timer3 interrupt enable
TMR3CN |= 0x04; // Start Timer3
SFRPAGE = SFRPAGE_save; // Restore the SFRPAGE
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure the Crossbar and GPIO ports.
//
// P0.0 digital open-drain SMBus SDA
// P0.1 digital open-drain SMBus SCL
//
// P3.2 digital push-pull LED
//
// all other port pins unused
//
// Note: If the SMBus is moved, the SCL and SDA sbit declarations must also
// be adjusted.
//
void PORT_Init (void)
{
unsigned char SFRPAGE_save = SFRPAGE; // Save the current SFRPAGE
SFRPAGE = CONFIG_PAGE; // Switch to the necessary SFRPAGE
P0MDOUT = 0x00; // All P0 pins open-drain output
P3MDOUT |= 0x04; // Make the LED (P3.2) a push-pull
// output
XBR0 = 0x04; // Enable SMBus pins
XBR1 = 0x40; // Enable crossbar and weak pull-ups
P0 = 0xFF;
SFRPAGE = SFRPAGE_save; // Restore the SFRPAGE
}
//-----------------------------------------------------------------------------
// SMBus Interrupt Service Routine (ISR)
//-----------------------------------------------------------------------------
//
// SMBus ISR state machine
// - Master only implementation - no slave or arbitration states defined
// - All incoming data is written starting at the global pointer <pSMB_DATA_IN>
// - All outgoing data is read from the global pointer <pSMB_DATA_OUT>
//
void SMBus_ISR (void) interrupt 7
{
bit FAIL = 0; // Used by the ISR to flag failed
// transfers
static char i; // Used by the ISR to count the
// number of data bytes sent or
// received
static bit SEND_START = 0; // Send a start
switch (SMB0CN & 0xF0) // Status vector
{
// Master Transmitter/Receiver: START condition transmitted.
case SMB_MTSTA:
SMB0DAT = TARGET; // Load address of the target slave
SMB0DAT &= 0xFE; // Clear the LSB of the address for the
// R/W bit
SMB0DAT |= SMB_RW; // Load R/W bit
STA = 0; // Manually clear START bit
i = 0; // Reset data byte counter
break;
// Master Transmitter: Data byte (or Slave Address) transmitted
case SMB_MTDB:
if (ACK) // Slave Address or Data Byte
{ // Acknowledged?
if (SEND_START)
{
STA = 1;
SEND_START = 0;
break;
}
if(SMB_SENDWORDADDR) // Are we sending the word address?
{
SMB_SENDWORDADDR = 0; // Clear flag
SMB0DAT = WORD_ADDR; // Send word address
if (SMB_RANDOMREAD)
{
SEND_START = 1; // Send a START after the next ACK cycle
SMB_RW = READ;
}
break;
}
if (SMB_RW==WRITE) // Is this transfer a WRITE?
{
if (i < SMB_DATA_LEN) // Is there data to send?
{
// send data byte
SMB0DAT = *pSMB_DATA_OUT;
// increment data out pointer
pSMB_DATA_OUT++;
// increment number of bytes sent
i++;
}
else
{
STO = 1; // Set STO to terminte transfer
SMB_BUSY = 0; // Clear software busy flag
}
}
else {} // If this transfer is a READ,
// then take no action. Slave
// address was transmitted. A
// separate 'case' is defined
// for data byte recieved.
}
else // If slave NACK,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -