⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 f04x_smbus_eeprom.c

📁 8051F040的EEPROM程序
💻 C
📖 第 1 页 / 共 3 页
字号:
// Parameters   : None
//
// This routine initializes the system clock to use the internal oscillator
// at 3.0625 MHz (24.5 / 8 MHz).
//
void SYSCLK_Init (void)
{
   char SFRPAGE_SAVE = SFRPAGE;        // Save Current SFR page

   SFRPAGE = CONFIG_PAGE;              // Set SFR page

   OSCICN = 0x80;                      // Set internal oscillator to run
                                       // at 1/8 its maximum frequency

   CLKSEL = 0x00;                      // Select the internal osc. as
                                       // the SYSCLK source

   SFRPAGE = SFRPAGE_SAVE;             // Restore SFR page
                                       // detector
}

//-----------------------------------------------------------------------------
// 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
//
// P1.6   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)
{
   char SFRPAGE_SAVE = SFRPAGE;        // Save Current SFR page

   SFRPAGE = CONFIG_PAGE;

   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
// - 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

   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

   // Status code for the SMBus (SMB0STA register)
   switch (SMB0STA)
   {
      // Master Transmitter/Receiver: START condition transmitted.
      // Load SMB0DAT with slave device (EEPROM) address.
      case SMB_START:
         SMB0DAT = TARGET;             // Load address of the 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 STA bit
         i = 0;                        // reset data byte counter

         break;

      // Master Transmitter/Receiver: Repeated START condition transmitted.
      // For a READ: This state only occurs during an EEPROM read operation
      //  for the EEPROM's "random read", where a write operation with the
      //  data address must be done before the read operation.
      //
      // For a WRITE: N/A
      case SMB_RP_START:
         SMB0DAT = TARGET;             // Load address of the slave.
         SMB0DAT |= SMB_RW;            // Load R/W bit
         STA = 0;                      // Manually clear START bit.
         i = 0;                        // reset data byte counter

         break;

      // Master Transmitter: Slave address + WRITE transmitted.  ACK received.
      // For a READ or WRITE: the word (data) address in the EEPROM must now
      //  be sent after the slave address
      case SMB_MTADDACK:

         SMB0DAT = WORD_ADDR;          // Send word address

         if (SMB_RANDOMREAD)
         {
            SEND_START = 1;            // Send a START after the next ACK cycle
            SMB_RW = READ;
         }

         break;

      // Master Transmitter: Slave address + WRITE transmitted.  NACK received.
      // If the EEPROM should be polled, restart the transfer.
      // Otherwise, reset the SMBus
      case SMB_MTADDNACK:
         if(SMB_ACKPOLL)
         {
            STA = 1;                   // Restart transfer
         }
         else
         {
            FAIL = 1;                  // Indicate failed transfer
         }                             // and handle at end of ISR

         break;

      // Master Transmitter: Data byte transmitted.  ACK received.
      // For a READ: the word address has been trasmitted, and a repeated
      //  start should be generated.
      //
      // For a WRITE: each data word should be sent
      case SMB_MTDBACK:

         if (SEND_START)
         {
            STA = 1;
            SEND_START = 0;
            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, as a repeated
                                       // start will be generated for the
                                       // read operation

         break;

      // Master Transmitter: Data byte transmitted.  NACK received.
      // If the EEPROM should be polled, restart the transfer.
      // Otherwise, reset the SMBus
      case SMB_MTDBNACK:
         if(SMB_ACKPOLL)
         {
            STA = 1;                   // Restart transfer
         }
         else
         {
            FAIL = 1;                  // Indicate failed transfer
         }                             // and handle at end of ISR

         break;

      // Master Transmitter: Arbitration lost.
      case SMB_MTARBLOST:

         FAIL = 1;                     // Indicate failed transfer
                                       // and handle at end of ISR

         break;

      // Master Receiver: Slave address + READ transmitted.  ACK received.
      // For a READ: check if this is a one-byte transfer. if so, set the
      //  NACK after the data byte is received to end the transfer. if not,
      //  set the ACK and receive the other data bytes.
      //
      // For a WRITE: N/A
      case SMB_MRADDACK:
         if (i == SMB_DATA_LEN)
         {
            AA = 0;                    // Only one byte in this transfer,
                                       // send NACK after byte is received
         }
         else
         {
            AA = 1;                    // More than one byte in this transfer,
                                       // send ACK after byte is received
         }
         break;

      // Master Receiver: Slave address + READ transmitted.  NACK received.
      // If the EEPROM should be polled, restart the transfer.
      // Otherwise, reset the SMBus
      case SMB_MRADDNACK:
         if(SMB_ACKPOLL)
         {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -