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

📄 eeprom.c

📁 TDK 6521 SOC 芯片 DEMO程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************
 * This code and information is provided "as is" without warranty of any   *
 * kind, either expressed or implied, including but not limited to the     *
 * implied warranties of merchantability and/or fitness for a particular   *
 * purpose.                                                                *
 *                                                                         *
 * Copyright (C) 2004 Teridian SemiConductor, Corporation.                 *
 * All Rights Reserved.                                                    *
 *                                                                         *
 ***************************************************************************/
//**************************************************************************
//  DESCRIPTION: 71M652x POWER METER - Serial EEPROM Routines. 
// 
//  AUTHOR:  MTF
//
//  HISTORY: See end of file.
//**************************************************************************
// File: EEPROM.C
//
#include "options.h"
#if EEPROM && I2C_INT
#include "mmath.h"
#include "stm.h"
#include "wd.h"
#include "eeprom.h"

/*** External functions used within this module ***/
// software timers, software watchdog

/*** External variables used within this module ***/
// None.

/*** Public functions declared within this module ***/
// See include file "eeprom.h".

/*** Public variables declared within this module ***/
// See include file "eeprom.h".

/*** Private functions declared within this module ***/
static void issue_START (void) small reentrant;

/*** Private variables declared within this module ***/
//
#define WRITE 0xA0                     // EEPROM write to I2C device A0.
#define READ  0xA1                     // EEPROM read from I2C device A0.
#define START_DELAY   0x800            // Minimum allowable is 0x6A8.   

static volatile void (* xdata eeprom_proc) (void);

// EEPROM interface definitions.
enum STATE_t {
    IDLE, 
    WAIT_STOP,
    START_WRITE, 
    WAIT_WRITE_ACK, 
    WAIT_MSB_ADDR_ACK, 
    WAIT_LSB_ADDR_ACK, 
    WAIT_DATA_ACK,
    WAIT_CLEAR_ACK,
    START_READ, 
    WAIT_READ_ACK, 
    WAIT_DATA
 };

static volatile uint8_t mode;
#define READ_MODE 0
#define WRITE_MODE 1
#define CLEAR_MODE 2
static volatile uint16i_t page_fill;          // Count of bytes to fill page.
static volatile uint32i_t cnt;                // Count of bytes to still send or receive.
static volatile uint8_16_32_t idata addr;
static volatile uint8x_t * idata ptr;         // Pointer to string XMT'd/RCV'd to/from EEPROM.
static volatile enum EEPROM_RC data status;   // status of TX/RX of EEPROM.
static volatile enum STATE_t data state;
static volatile bool done;
static volatile uint16i_t page_mask;
static volatile uint16i_t write_tick_cnt;     // Time to write a page of EEPROM.

static const uint16r_t mask[] = { 0x0000, 
    0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
    0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };

void EEProm_Config (bool access, uint16_t page_size, uint8_t msWr)
{                                    // Enable control pins to access EEPROM, set page size and write time.
    if (access)
    {
       page_mask = mask[ log2 (page_size) ];
       write_tick_cnt = milliseconds(msWr);  // convert milliseconds to ticks.
       EX_EEPROM  = FALSE;                                 // Disable EEPROM non-busy interrupt.
       done = TRUE;
        
       DIO = (DIO & ~DIO_EEX) | DIO_EEX_2W;                // Connect to 2-Wire external EEPROM.
       EX_EEPROM  = TRUE;            // Enable EEPROM non-busy interrupt.
    }                                
    else
    {
       EX_EEPROM  = FALSE;           // Disable EEPROM non-busy interrupt.
       DIO &= ~DIO_EEX;              // Disconnect from external EEPROM.
    }    
}

#pragma save
#pragma NOAREGS
void EEProm_isr (void) small reentrant interrupt EEPROM_IV
{
    if (EECTRL & EE_ERROR)
    {
       status = _ERR_NACK;
       state = IDLE;
       return;
    }

    #ifdef WD_EEPROM
    wd_reset ( WD_EEPROM );
    #endif
 
    switch (state)
    {                                
       case IDLE:
          break;                        // Just ignore interrupts.
                                     
       case START_WRITE:                // Start of 'Page Write' or 'Sequential Read'.
          EEDATA = (addr.c[ HI_LO ] << 1) | WRITE; // Real or "dummy" write.
          EECTRL = EE_TX;               // issue_TRANSMIT ();
          state = WAIT_WRITE_ACK;
          break;

       case WAIT_WRITE_ACK:
          EEDATA = addr.c[ LO_HI ];     // Send MSB of address.
          EECTRL = EE_TX;               // issue_TRANSMIT ();
          state = WAIT_MSB_ADDR_ACK;
          break;

       case WAIT_MSB_ADDR_ACK:
          EEDATA = addr.c[ LO_LO ];     // Send LSB of address.
          EECTRL = EE_TX;               // Finish step-up of read/write of next page.
          state = WAIT_LSB_ADDR_ACK;
          break;

       case WAIT_LSB_ADDR_ACK: 
          switch(mode)
          {                           
          case READ_MODE:               // Do 'Sequential Read'. 
             EECTRL = EE_START;
             state = START_READ;
             break;
          case WRITE_MODE:              // Do 'Page Write'. 
             EEDATA = *(ptr++);         // Fetch character to send to EEPROM.
             EECTRL = EE_TX;            // issue_TRANSMIT ();
             page_fill = min (PAGE_SIZE - (addr.i[ LO ] & page_mask), cnt);
             cnt -= (uint32_t)page_fill;
             state = WAIT_DATA_ACK;
             break;
          case CLEAR_MODE:              // Do clear of device. 
             EEDATA = 0xFF;             // Fetch character to send to EEPROM.
             EECTRL = EE_TX;            // issue_TRANSMIT ();
             page_fill = PAGE_SIZE;
             cnt -= (uint32_t)page_fill;
             state = WAIT_CLEAR_ACK;
             break;
          }
          break;

       case WAIT_DATA_ACK: 
          if (--page_fill)              
          {
             EEDATA = *(ptr++);         // Fetch character to send to EEPROM.
             EECTRL = EE_TX;            // issue_TRANSMIT ();
          }
          else                          // Transmit to EEPROM.      
          {                             // Page full.
             if (0 == cnt)
                status = _OK;           // All done.

             EECTRL = EE_STOP;          // Do STOP.
             state = WAIT_STOP;
          }
          break;

       case WAIT_CLEAR_ACK: 
          if (--page_fill)              
          {
             EEDATA = 0xFF;             // Character to send to EEPROM.
             EECTRL = EE_TX;            // issue_TRANSMIT ();
          }
          else                          // Transmit to EEPROM.      
          {                             // Page full.
             if (0 == cnt)
                status = _OK;           // All done.

             EECTRL = EE_STOP;          // Do STOP.
             state = WAIT_STOP;
          }
          break;

       case WAIT_STOP: 
          if (cnt)
          {
             uint16x_t *pstm;
                                       // Align on page boundary.
             addr.i[ LO ] &= ~page_mask;
             addr.l += PAGE_SIZE;       // Next page.
             state = START_WRITE;       // Delay 'msWr' msec before next START.
             pstm = stm_start(write_tick_cnt, 0, issue_START);
             if (NULL == pstm)
                status = _ERR_OVERRUN;
          }
          else   
          {
             done = TRUE;
             status = _OK;
             state = IDLE;              // Done w/ READ or WRITE.
          }
          break;

////////////////////////////////////////////////////////////////////////////

       case START_READ:
          EEDATA = (addr.c[ HI_LO ] << 1) | READ;
          EECTRL = EE_TX;               // issue_TRANSMIT ();
          state = WAIT_READ_ACK;
          break;

       case WAIT_READ_ACK:
          if (1 == cnt)
             EECTRL = EE_RCV;           // Receive last byte (NO ACK).
          else
             EECTRL = EE_RCV_ACK;       // Receive and ACK byte.

          state = WAIT_DATA;
          break;

       case WAIT_DATA:                  // ACK has been sent.
          *(ptr++) = EEDATA;            // Store character received from EEPROM.

          if (--cnt)
          {
             if (1 == cnt)
                EECTRL = EE_RCV;        // Receive last byte (NO ACK).
             else
                EECTRL = EE_RCV_ACK;    // Receive and ACK byte.
          }
          else
          {
             EECTRL = EE_STOP;
             state = WAIT_STOP;         // Done w/ READ.
          }
          break;
    }
}
#pragma restore

#pragma save
#pragma NOAREGS
static void issue_START (void) small reentrant
{
    EECTRL = EE_START;
}
#pragma restore

⌨️ 快捷键说明

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