📄 f12x_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 / (8 * SMB_FREQUENCY));
SMB0ADR = MY_ADDR; // Set own slave address.
SMB0CN |= 0x40; // Enable SMBus;
SFRPAGE = SFRPAGE_SAVE; // Restore SFR page detector
}
//-----------------------------------------------------------------------------
// Timer3_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Timer3 configured for use by the SMBus low timeout detect feature as
// follows:
// - Timer3 in 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)
{
char SFRPAGE_SAVE = SFRPAGE; // Save Current SFR page
SFRPAGE = TMR3_PAGE;
TMR3CN = 0x00; // Timer3 external enable off;
// Timer3 in timer mode;
// Timer3 in auto-reload mode
TMR3CF = 0x00; // Timer3 uses SYSCLK/12
// Timer3 output not available
// Timer3 counts up
RCAP3 = -(SYSCLK/12/40); // Timer3 configured to overflow after
TMR3 = RCAP3; // ~25ms (for SMBus low timeout detect)
EIE2 |= 0x01; // Timer3 interrupt enable
TR3 = 1; // Start Timer3
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
}
//-----------------------------------------------------------------------------
// 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
{
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 Timer3 SFRPAGE
TF3 = 0; // Clear Timer3 interrupt-pending flag
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -