📄 f02x_smbus_multimaster.c
字号:
//
// Return Value : None
// Parameters : None
//
// Timer0 is configured to blink the LED.
//
void Timer0_Init (void)
{
TMOD = 0x02; // Timer0 in 8-bit auto-reload mode
CKCON = 0x02; // Timer0 uses SYSCLK/48
TH0 = 0x00; // Make Timer0 wait the longest time
// between LED blinks.
TL0 = TH0; // Init Timer0
// Keeper Timer0 off until the switch on the other multimaster device is
// pushed
}
//-----------------------------------------------------------------------------
// Timer3_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Timer3 configured for use by the SMBus low timeout detect feature as
// follows:
// - 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)
{
TMR3CN = 0x00; // Timer3 uses SYSCLK/12
TMR3RL = -(SYSCLK/12/40); // Timer3 configured to overflow after
TMR3 = TMR3RL; // ~25ms (for SMBus low timeout detect)
EIE2 |= 0x01; // Timer3 interrupt enable
TMR3CN |= 0x04; // Start Timer3
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Timer0 Interrupt Service Routine (ISR)
//-----------------------------------------------------------------------------
//
// Timer0 blinks the LED when instructed by the other multimaster.
//
void Timer0_ISR (void) interrupt 1
{
static unsigned char count = 0; // Count up to 256 Timer0 interrupts
// before switching the LED
// Otherwise, it won't be visible to
// the eye.
if (count == 255)
{
LED = ~LED; // Turn the LED on and off
count = 0;
}
else
{
count++;
}
}
//-----------------------------------------------------------------------------
// SMBus Interrupt Service Routine (ISR)
//-----------------------------------------------------------------------------
//
// SMBus ISR state machine
// - Master only implementation - no slave 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
// Status code for the SMBus (SMB0STA register)
switch (SMB0STA)
{
// Master States --------------------------------------------------------
// Master Transmitter/Receiver: START condition transmitted.
// Load SMB0DAT with slave device (EEPROM) address.
case SMB_START:
// Master Transmitter/Receiver: repeated START condition transmitted.
// Load SMB0DAT with slave device address
case SMB_RP_START:
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
break;
// Master Transmitter: Slave address + WRITE transmitted. ACK received.
case SMB_MTADDACK:
// send data byte
SMB0DAT = SMB_DATA_OUT_MASTER;
break;
// Master Transmitter: Slave address + WRITE transmitted. NACK received.
// Restart the transfer.
case SMB_MTADDNACK:
STA = 1; // Restart transfer
break;
// Master Transmitter: Data byte transmitted. ACK received.
// For a READ: N/A
//
// For a WRITE: Data byte was sent, so stop the transfer.
case SMB_MTDBACK:
STO = 1; // Set STO to terminte transfer
SMB_BUSY = 0; // Clear software busy flag
break;
// Master Transmitter: Data byte transmitted. NACK received.
// Restart the transfer.
case SMB_MTDBNACK:
STA = 1; // Restart transfer
break;
// Master Receiver: Slave address + READ transmitted. ACK received.
// For a READ: set the NACK after the data byte is received to end the
// transfer.
//
// For a WRITE: N/A
case SMB_MRADDACK:
AA = 0; // Only one byte in this transfer,
// send NACK after byte is received
break;
// Master Receiver: Slave address + READ transmitted. NACK received.
// Restart the transfer.
case SMB_MRADDNACK:
STA = 1; // Restart transfer
break;
// Master Receiver: Data byte received. ACK transmitted.
// For a READ: Read operation has completed. Read data register and
// send STOP.
//
// For a WRITE: N/A
case SMB_MRDBNACK:
SMB_DATA_IN_MASTER = SMB0DAT; // Store received byte
STO = 1;
SMB_BUSY = 0;
AA = 1; // Set AA for next transfer
break;
// Master Transmitter: Arbitration lost. (bus error)
case SMB_MTARBLOST:
FAIL = 1; // Indicate failed transfer
// and handle at end of ISR
break;
// Slave States ---------------------------------------------------------
// Slave Receiver: Slave address + WRITE received. ACK transmitted.
// Fall through.
case SMB_SROADACK:
// Slave Receiver: General call address received. ACK transmitted.
case SMB_SRGADACK:
break;
// Slave Receiver: Data byte received after addressed by general
// call address + WRITE.
// ACK transmitted. Fall through.
case SMB_SRGDBACK:
// Slave Receiver: Data byte received after addressed by own
// slave address + WRITE.
// ACK transmitted.
case SMB_SRODBACK:
SMB_DATA_IN_SLAVE = SMB0DAT; // Store incoming data
DATA_READY = 1; // Indicate new data received
break;
// Slave Receiver: Data byte received while addressed as slave.
// NACK transmitted. Should not occur since AA will not be cleared
// as slave. Fall through to next state.
case SMB_SRODBNACK:
// Slave Receiver: Data byte received while addressed by general call.
// NACK transmitted.
// Should not occur since AA will not be cleared as slave.
case SMB_SRGDBNACK:
AA = 1;
break;
// Slave Receiver: STOP or repeated START received while addressed as
// slave.
case SMB_SRSTOP:
break;
// Slave Transmitter: Own slave address + READ received. ACK
// transmitted.
// Load SMB0DAT with data to be output.
case SMB_STOADACK:
SMB0DAT = SMB_DATA_OUT_SLAVE;
break;
// Slave Transmitter: Data byte transmitted. ACK received. Fall
// through.
case SMB_STDBACK:
// Slave Transmitter: Data byte transmitted. NACK received. Fall
// through.
case SMB_STDBNACK:
// Slave Transmitter: Last data byte transmitted. ACK received.
// No action necessary.
case SMB_STDBLAST:
break;
// Slave Receiver: Arbitration lost, general call address received.
// ACK transmitted.
// Fall through.
case SMB_SRGARBLOST:
// Slave Receiver: Arbitration lost, own slave address + WRITE received.
// ACK transmitted.
// Fall through.
case SMB_SROARBLOST:
// Slave Transmitter: Arbitration lost as master. Own address + READ
// received.
// ACK transmitted.
// Set STA bit to retry the transfer when the bus is free.
case SMB_STOARBLOST:
STA = 1; // Retry transfer when bus is free.
break;
// SCL High Timeout: SCL detected high longer than calculated SMB0CR
// time.
// No action necessary. Bus is now free.
case SMB_SCLHIGHTO:
break;
// All other status codes invalid. Reset communication.
default:
FAIL = 1;
break;
}
if (FAIL) // If the transfer failed,
{
SMB0CN &= ~0x40; // Reset communication
SMB0CN |= 0x40;
STA = 0;
STO = 0;
AA = 0;
SMB_BUSY = 0; // Free SMBus
FAIL = 0;
}
SI = 0; // Clear interrupt flag
}
//-----------------------------------------------------------------------------
// Timer3 Interrupt Service Routine (ISR)
//-----------------------------------------------------------------------------
//
// A Timer3 interrupt indicates an SMBus SCL low timeout.
// The SMBus is disabled and re-enabled if a timeout occurs.
//
void Timer3_ISR (void) interrupt 14
{
SMB0CN &= ~0x40; // Disable SMBus
SMB0CN |= 0x40; // Re-enable SMBus
TMR3CN &= ~0x80; // Clear Timer3 interrupt-pending flag
SMB_BUSY = 0; // Free bus
}
//-----------------------------------------------------------------------------
// Support Functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// 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
}
//-----------------------------------------------------------------------------
// Blink_LED
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Starts the LED blinking.
//
void Blink_LED (void)
{
TR0 = 1;
}
//-----------------------------------------------------------------------------
// Stop_LED
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Stops the LED from blinking.
//
void Stop_LED (void)
{
TR0 = 0;
LED = 0; // Turn the LED off when it's not
// blinking
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -