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

📄 spi_ee_int1.c

📁 c8051f020开发板的所有参考程序
💻 C
📖 第 1 页 / 共 2 页
字号:

//-----------------------------------------------------------------------------
// EE_Read
//-----------------------------------------------------------------------------
//
// This routine reads and returns a single EEPROM byte whose address is
// given in <Addr>.
//
unsigned char EE_Read (unsigned Addr)
{
   while (EE_Ready == FALSE);          // wait for EEPROM available

   EE_Ready = FALSE;                   // claim EEPROM

   EE_Addr = Addr;                     // initialize EEPROM address
   EE_WR = FALSE;                      // set up for READ operation

   SPIF = 1;                           // initiate EEPROM operation

   while (EE_Ready == FALSE);          // wait for operation complete

   return EE_Data;                     // return data
}

//-----------------------------------------------------------------------------
// EE_Write
//-----------------------------------------------------------------------------
//
// This routine writes a single EEPROM byte <value> to address <Addr>.  Here
// we implement pre-write polling.
//
void EE_Write (unsigned Addr, unsigned char value)
{
   while (EE_Ready == FALSE);          // wait for EEPROM available

   EE_Ready = FALSE;                   // claim EEPROM

   EE_Addr = Addr;                     // initialize EEPROM address
   EE_Data = value;                    // initialize EEPROM data
   EE_WR = TRUE;                       // set up for WRITE operation

   SPIF = 1;                           // initiate EEPROM operation
}

//-----------------------------------------------------------------------------
// Timer0_ISR
//-----------------------------------------------------------------------------
//
// Timer0 implements a delay which is used by the SPI0_ISR to manage setup
// and hold requirements on the EE_CS line.  This ISR initiates a SPI0 
// interrupt when called, and stops Timer0.
//
void Timer0_ISR (void) interrupt 1 using 3
{
   TR0 = 0;                            // STOP Timer0
   SPIF = 1;                           // initiate SPI0 interrupt
}

//-----------------------------------------------------------------------------
// SPI0_ISR
//-----------------------------------------------------------------------------
//
// This ISR implements a state machine which handles byte-level read and
// write operations to an attached EEPROM.
//
void SPI0_ISR (void) interrupt 6 using 3
{
   enum SPI0_state { RESET, RD_S0, RD_S1, RD_S2, RD_S3, RD_S4, RD_S5, RD_S6,
                     RD_S7, WR_S0, WR_S1, WR_S2, WR_S3, WR_S4, WR_S5, WR_S6,
                     WR_S7, WR_S8, WR_S9, WR_S10, WR_S11, WR_S12, WR_S13,
                     WR_S14, WR_S15};

   static enum SPI0_state state = RESET;

   SPIF = 0;                           // clear SPI interrupt flag

   switch (state) {
      case RESET: // assert EE_CS; set Timer0 to cause SPI0 interrupt in
                  // 250ns (CS setup time); decode EE_WR to determine 
                  // whether next state is RD_S0 (read) or WR_S0 (write).
         EE_CS = 0;                    // assert CS signal on EEPROM

         // set Timer0 to interrupt 250ns from now
         ET0 = 0;                      // disable Timer0 interrupts
         TCON &= ~0x30;                // STOP Timer0 and clear overflow flag
         TH0 = (-SYSCLK/4000000) >> 8; // set Timer0 to overflow in 250ns
         TL0 = -SYSCLK/4000000;
         ET0 = 1;                      // enable Timer0 interrupts
         TR0 = 1;                      // START Timer0

         // decode EE_Write flag to determine whether operation is a read
         // or a write
         if (EE_WR == TRUE) {
            state = WR_S0;             // set up for a write
         } else {
            state = RD_S0;             // set up for a read
         }
         break;

      case RD_S0: // transmit READ op-code
         SPI0DAT = EE_READ;            // transmit READ opcode
         state = RD_S1;                // advance to next state
         break;

      case RD_S1: // transmit MSB of Address
         SPI0DAT = EE_Addr >> 8;       // transmit MSB of Address
         state = RD_S2;                // advance to next state
         break;

      case RD_S2: // transmit LSB of Address
         SPI0DAT = EE_Addr;            // transmit LSB of Address
         state = RD_S3;                // advance to next state
         break;

      case RD_S3: // transmit dummy read to get data from EEPROM
         SPI0DAT = 0;                  // transmit dummy read
         state = RD_S4;                // advance to next state
         break;

      case RD_S4: // wait 250ns (EEPROM CS hold time)

         // set Timer0 to interrupt 250ns from now
         ET0 = 0;                      // disable Timer0 interrupts
         TCON &= ~0x30;                // STOP Timer0 and clear overflow flag
         TH0 = (-SYSCLK/4000000) >> 8; // set Timer0 to overflow in 250ns
         TL0 = -SYSCLK/4000000;
         ET0 = 1;                      // enable Timer0 interrupts
         TR0 = 1;                      // START Timer0
         state = RD_S5;                // advance to next state
         break;

      case RD_S5: // raise CS and wait 500ns (EEPROM CS disable time)
         EE_CS = 1;                    // de-assert EEPROM CS

         // set Timer0 to interrupt 500ns from now
         ET0 = 0;                      // disable Timer0 interrupts
         TCON &= ~0x30;                // STOP Timer0 and clear overflow flag
         TH0 = (-SYSCLK/2000000) >> 8; // set Timer0 to overflow in 500ns
         TL0 = -SYSCLK/2000000;
         ET0 = 1;                      // enable Timer0 interrupts
         TR0 = 1;                      // START Timer0

         state = RD_S6;                // advance to next state
         break;

      case RD_S6: // read data from SPI0 and post EEPROM ready
         EE_Data = SPI0DAT;            // read EEPROM data from SPI0
         EE_Ready = TRUE;              // indicate EEPROM ready for
                                       // next operation
         state = RESET;                // reset state variable
         break;

      case WR_S0: // transmit WRITE ENABLE opcode
         SPI0DAT = EE_WREN;            // transmit WREN opcode
         state = WR_S1;                // advance to next state
         break;

      case WR_S1: // wait at least 250ns (CS hold time)
         // set Timer0 to interrupt 250ns from now
         ET0 = 0;                      // disable Timer0 interrupts
         TCON &= ~0x30;                // STOP Timer0 and clear overflow flag
         TH0 = (-SYSCLK/4000000) >> 8; // set Timer0 to overflow in 250ns
         TL0 = -SYSCLK/4000000;
         ET0 = 1;                      // enable Timer0 interrupts
         TR0 = 1;                      // START Timer0

         state = WR_S2;                // advance to next state
         break;

      case WR_S2: // raise CS and wait 500ns (CS disable time)
         EE_CS = 1;                    // deassert CS

         // set Timer0 to interrupt 500ns from now
         ET0 = 0;                      // disable Timer0 interrupts
         TCON &= ~0x30;                // STOP Timer0 and clear overflow flag
         TH0 = (-SYSCLK/2000000) >> 8; // set Timer0 to overflow in 500ns
         TL0 = -SYSCLK/2000000;
         ET0 = 1;                      // enable Timer0 interrupts
         TR0 = 1;                      // START Timer0

         state = WR_S3;                // advance to next state
         break;

      case WR_S3: // assert CS and wait 250ns (CS setup time)
         EE_CS = 0;                    // assert CS

         // set Timer0 to interrupt 250ns from now
         ET0 = 0;                      // disable Timer0 interrupts
         TCON &= ~0x30;                // STOP Timer0 and clear overflow flag
         TH0 = (-SYSCLK/4000000) >> 8; // set Timer0 to overflow in 250ns
         TL0 = -SYSCLK/4000000;
         ET0 = 1;                      // enable Timer0 interrupts
         TR0 = 1;                      // START Timer0

         state = WR_S4;                // advance to next state
         break;

      case WR_S4: // transmit WRITE opcode
         SPI0DAT = EE_WRITE;           // transmit WRITE opcode
         state = WR_S5;                // advance to next state
         break;

      case WR_S5: // transmit MSB of Address
         SPI0DAT = EE_Addr >> 8;       // transmit MSB of Address
         state = WR_S6;                // advance to next state
         break;

      case WR_S6: // transmit LSB of Address
         SPI0DAT = EE_Addr;            // transmit LSB of Address
         state = WR_S7;                // advance to next state
         break;

      case WR_S7: // transmit DATA
         SPI0DAT = EE_Data;            // transmit DATA
         state = WR_S8;                // advance to next state
         break;

      case WR_S8: // wait 250ns (CS hold time)
         // set Timer0 to interrupt 250ns from now
         ET0 = 0;                      // disable Timer0 interrupts
         TCON &= ~0x30;                // STOP Timer0 and clear overflow flag
         TH0 = (-SYSCLK/4000000) >> 8; // set Timer0 to overflow in 250ns
         TL0 = -SYSCLK/4000000;
         ET0 = 1;                      // enable Timer0 interrupts
         TR0 = 1;                      // START Timer0

         state = WR_S9;                // advance to next state
         break;

      case WR_S9: // deassert CS and wait 500ns (CS disable time)
         EE_CS = 1;                    // deassert CS

         // set Timer0 to interrupt 500ns from now
         ET0 = 0;                      // disable Timer0 interrupts
         TCON &= ~0x30;                // STOP Timer0 and clear overflow flag
         TH0 = (-SYSCLK/2000000) >> 8; // set Timer0 to overflow in 500ns
         TL0 = -SYSCLK/2000000;
         ET0 = 1;                      // enable Timer0 interrupts
         TR0 = 1;                      // START Timer0

         state = WR_S10;               // advance to next state
         break;

      case WR_S10: // assert CS and wait 250ns (begin polling RDSR)
         EE_CS = 0;                    // assert CS

         // set Timer0 to interrupt 250ns from now
         ET0 = 0;                      // disable Timer0 interrupts
         TCON &= ~0x30;                // STOP Timer0 and clear overflow flag
         TH0 = (-SYSCLK/4000000) >> 8; // set Timer0 to overflow in 250ns
         TL0 = -SYSCLK/4000000;
         ET0 = 1;                      // enable Timer0 interrupts
         TR0 = 1;                      // START Timer0

         state = WR_S11;               // advance to next state
         break;

      case WR_S11: // transmit Read Status Register opcode
         SPI0DAT = EE_RDSR;            // transmit RDSR opcode
         state = WR_S12;               // advance to next state
         break;

      case WR_S12: // transmit dummy write to read Status Register
         SPI0DAT = 0;                  // dummy write (after this completes,
                                       // SPI0DAT will contain Read Status
                                       // Register contents, which are decoded
                                       // in WR_S15 below)
         state = WR_S13;               // advance to next state
         break;

      case WR_S13: // wait 250ns (CS hold time)
         // set Timer0 to interrupt 250ns from now
         ET0 = 0;                      // disable Timer0 interrupts
         TCON &= ~0x30;                // STOP Timer0 and clear overflow flag
         TH0 = (-SYSCLK/4000000) >> 8; // set Timer0 to overflow in 250ns
         TL0 = -SYSCLK/4000000;
         ET0 = 1;                      // enable Timer0 interrupts
         TR0 = 1;                      // START Timer0

         state = WR_S14;               // advance to next state
         break;

      case WR_S14: // deassert CS and wait 500ns (CS disable time)
         EE_CS = 1;                    // deassert CS

         // set Timer0 to interrupt 500ns from now
         ET0 = 0;                      // disable Timer0 interrupts
         TCON &= ~0x30;                // STOP Timer0 and clear overflow flag
         TH0 = (-SYSCLK/2000000) >> 8; // set Timer0 to overflow in 500ns
         TL0 = -SYSCLK/2000000;
         ET0 = 1;                      // enable Timer0 interrupts
         TR0 = 1;                      // START Timer0

         state = WR_S15;               // advance to next state
         break;

      case WR_S15: // check WIP bit (LSB of RDSR): if '1', then poll again;
                   // otherwise, RESET and post Write Complete
         if (SPI0DAT & 0x01) {         // TRUE if write in progress
            state = WR_S10;            // poll RDSR again
            SPIF = 1;                  // initiate new polling operation
         } else {                      // we're done. clean up.
            EE_Ready = TRUE;           // indicate EEPROM available
            state = RESET;             // reset state variable
         }
         break;

      default:
         while (1);                    // error
   }
}

⌨️ 快捷键说明

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