📄 f06x_smbus_slave.c
字号:
P0MDOUT = 0x00; // All P0 pins open-drain output
P1MDOUT |= 0x40; // Make the LED (P1.6) a push-pull
// output
XBR0 = 0x01; // Enable SMBus on the crossbar
XBR2 = 0x40; // Enable crossbar and weak pull-ups
P0 = 0xFF;
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page detector
}
//-----------------------------------------------------------------------------
// SMBus_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// The SMBus peripheral is configured as follows:
// - SMBus enabled
// - Assert Acknowledge low (AA bit = 1b)
// - Free and SCL low timeout detection enabled
//
void SMBus_Init (void)
{
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = SMB0_PAGE;
SMB0CN = 0x07; // Assert Acknowledge low (AA bit = 1b);
// Enable SMBus Free timeout detect;
// Enable SCL low timeout detect
// SMBus clock rate (derived approximation from the Tlow and Thigh equations
// in the SMB0CR register description)
SMB0CR = 257 - (SYSCLK / (2 * SMB_FREQUENCY));
SMB0ADR = MY_ADDR; // Set own slave address.
SMB0CN |= 0x40; // Enable SMBus;
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page detector
}
//-----------------------------------------------------------------------------
// Timer4_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Timer4 configured for use by the SMBus low timeout detect feature as
// follows:
// - Timer4 in auto-reload mode
// - SYSCLK/12 as Timer4 clock source
// - Timer4 reload registers loaded for a 25ms overflow period
// - Timer4 pre-loaded to overflow after 25ms
// - Timer4 enabled
//
void Timer4_Init (void)
{
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = TMR4_PAGE;
TMR4CN = 0x00; // Timer4 external enable off;
// Timer4 in timer mode;
// Timer4 in auto-reload mode
TMR4CF = 0x00; // Timer4 uses SYSCLK/12
// Timer4 output not available
// Timer4 counts up
RCAP4 = -(SYSCLK/12/40); // Timer4 configured to overflow after
TMR4 = RCAP4; // ~25ms (for SMBus low timeout detect)
EIE2 |= 0x04; // Timer4 interrupt enable
TR4 = 1; // Start Timer4
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page detector
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// SMBus Interrupt Service Routine (ISR)
//-----------------------------------------------------------------------------
//
// SMBus ISR state machine
// - Slave only implementation - no master states defined
// - All incoming data is written to global variable <SMB_DATA>
// - All outgoing data is read from global variable <SMB_DATA>
//
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)
{
// 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 = 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;
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;
// 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 = 1;
FAIL = 0;
}
SI = 0; // Clear interrupt flag
}
//-----------------------------------------------------------------------------
// Timer4 Interrupt Service Routine (ISR)
//-----------------------------------------------------------------------------
//
// A Timer4 interrupt indicates an SMBus SCL low timeout.
// The SMBus is disabled and re-enabled if a timeout occurs.
//
void Timer4_ISR (void) interrupt 16
{
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = SMB0_PAGE;
SMB0CN &= ~0x40; // Disable SMBus
SMB0CN |= 0x40; // Re-enable SMBus
SFRPAGE = SFRPAGE_SAVE; // Switch back to the Timer4 SFRPAGE
TF4 = 0; // Clear Timer4 interrupt-pending flag
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -