📄 f0xx_smbus_slave_multibyte.c
字号:
XBR2 = 0x40; // Enable crossbar and weak pull-ups
P0 = 0xFF;
}
//-----------------------------------------------------------------------------
// 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)
{
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;
}
//-----------------------------------------------------------------------------
// 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
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// 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_IN> array
// - All outgoing data is read from global variable <SMB_DATA_OUT> array
//
void SMBUS_ISR (void) interrupt 7
{
bit FAIL = 0; // Used by the ISR to flag failed
// transfers
static unsigned char sent_byte_counter;
static unsigned char rec_byte_counter;
// 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:
sent_byte_counter = 1; // Reinitialize the data counters
rec_byte_counter = 1;
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.
// Receive each byte from the master.
case SMB_SRODBACK:
if (rec_byte_counter < NUM_BYTES_WR)
{
// Store incoming data
SMB_DATA_IN[rec_byte_counter-1] = SMB0DAT;
rec_byte_counter++;
AA = 1; // ACK received data
}
else
{
// Store incoming data
SMB_DATA_IN[rec_byte_counter-1] = SMB0DAT;
DATA_READY = 1; // Indicate new data fully received
AA = 1; // ACK received data
}
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[sent_byte_counter-1];
sent_byte_counter++;
break;
// Slave Transmitter: Data byte transmitted. ACK received.
// Send each requested byte to the master.
case SMB_STDBACK:
if (sent_byte_counter <= NUM_BYTES_RD)
{
// Prepare next outgoing byte
SMB0DAT = SMB_DATA_OUT[sent_byte_counter-1];
sent_byte_counter++;
}
break;
// Slave Transmitter: Data byte transmitted. NACK received.
// Resend the previous byte.
case SMB_STDBNACK:
sent_byte_counter--;
SMB0DAT = SMB_DATA_OUT[sent_byte_counter-1];
sent_byte_counter++;
break;
// 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
{
SMB0CN &= ~0x40; // Disable SMBus
SMB0CN |= 0x40; // Re-enable SMBus
TMR3CN &= ~0x80; // Clear Timer3 interrupt-pending flag
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -