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

📄 meter.c

📁 TDK 6521 SOC 芯片 DEMO程序
💻 C
📖 第 1 页 / 共 4 页
字号:
        else
            Status &= ~CREEP;

        #elif EQUATION == _3ELEMENT_4WIRE_WYE
        bool creepA = FALSE, creepB = FALSE, creepC = FALSE;

        if (Vrms_A > VThrshld)
        {
            Status &= ~MINVA;
            if(Irms_A < IThrshld)
                creepA = TRUE;
        }
        else
        {
            Status |= MINVA;
            creepA = TRUE;
            Vrms_A = v0sqsum = 0;
        }
        if (Vrms_B > VThrshld)
        {
            Status &= ~MINVB;
            if(Irms_B < IThrshld)
                creepB = TRUE;
        }
        else
        {
            Status |= MINVB;
            creepB = TRUE;
            Vrms_B = v1sqsum = 0;
        }
        if (Vrms_C > VThrshld)
        {
            Status &= ~MINVC;
            if(Irms_C < IThrshld)
                creepC = TRUE;
        }
        else
        {
            Status |= MINVC;
            creepC = TRUE;
            Vrms_C = v2sqsum = 0;
        }
        if (creepA)
        {
            Irms_A = w0sum = var0sum = i0sqsum = 0;  
        }
        if (creepB)
        {
            Irms_B = w1sum = var1sum = i1sqsum = 0;  
        }
        if (creepC)
        {
            Irms_C = w2sum = var2sum = i2sqsum = 0;  
        }
        if (creepA && creepB && creepC)
        {
            Status |= CREEP;
            #if TRACE13
            memset_ce (&wsum_accum, 0xC0000000L); 
            memset_ce (&vsum_accum, 0xC0000000L); 
            #else
            #error unknown device
            #endif
        }
        else
            Status &= ~CREEP;

        #else
        #error missing combination of equation and device
        #endif
    }
}

// Adjust the values for the second IMAX
#if IMAX2
// It's tempting to reuse the values that record the CE values,
// but they could be overwritten in real time, so that unscaled
// and scaled values would appear and disappear.
int32p_t w1sum, var1sum, i1sqsum;
static void RescalePhaseB(void)
{
    if (0 == Imax2)
    {
        Imax2 = Imax;
    }

    if (Imax == Imax2)
    {
        // if they're the same, no scaling is needed
        w1sum = w1sum_ce;
        var1sum = var1sum_ce;
        i1sqsum = i1sqsum_ce;
    }
    else
    {
        float rescale;
        // The object is to scale phase B to use the same units as Imax.
        // This is normally done because phase B has an alternate current
        // sensor, such as a shunt.
        // By putting everything in the same units, all the other math
        // in the meter remains in terms of Imax, simplifying it.
        // Precision: at the highest powers, two bits of precision
        // are lost.  This is less than 0.000007% error, 2 orders of 
        // magnitude less than the quantization error in the 
        // calibration (0.003%).  At half power, one bit is lost.
        // Below a quarter power, no precision is lost.
        rescale = ((float)Imax2)/((float)Imax);
        w1sum = (int32_t)(rescale * (float)w1sum_ce);
        var1sum = (int32_t)(rescale * (float)var1sum_ce);
        i1sqsum = (int32_t)((rescale*rescale) * (float)i1sqsum_ce);
    }
}
#endif

// This speeds and slows the meter based on temperature.
static void Gain_Compensation (void)
{
       float gain, dt;

       // Algebraic simplification of formula in datasheets.
       // temp_x = (Temp_Nom - Temp_Raw_X) * degscale
       // deltaT (aka Temp_X) always less than 2^11.
       // DEG_SCALE is a constant defined in ce652x.h, or ce651x.h
       dt = DEG_SCALE * (float)(temp_nom - temp_raw);
       deltaT = dt; // temperature for display by M1; LSB = 0.1C

       // Algebraic simplification of formula in datasheets.
       gain = ((float)ppmc2 * dt)/(512.);  // squared term
       gain = ((gain + (float)ppmc1) * (float)dt)/(16384.); // linear term
       gain += 16385.; // constant term

       // The gain is a signed 16-bit number. Prevent out-of-range values.
       // The arithmetic permits negative gains, but negative gains 
       // are not physically possible.
       gain = min(32767., max(gain, 0.));

       memset_ce (&gain_adj, (int32_t)gain); // set gain for all channels
}


//===========================================================================//
#if FLAG
// The whole object of this routine is so that FLAG and the meter communicate
// safely in real time.  The meter updates its data about once per second.
// The FLAG interface runs from a serial interrupt that can occur at any
// instant.  This routine implements a synchronous "rendezvous" operation.
// When FLAG reads the data, 99% of the time, it gets a snapshot that makes sense,
// because this routine copies the data to FLAG's private copy of the data registers.
// Likewise, when FLAG writes the data, FLAG's setup is set all at once from
// FLAG's private registers.
// But, what if a FLAG read or write request happens during the copy?
// The "register available" boolean tells the FLAG interrupt that
// the data is not available during the copy operation.  FLAG then returns a 
// NAK to the hand-held unit, then the hand-held unit retries the request, 
// and by then the private copy of the data is complete and the request finishes.
// This all really works.  If one watches a continuous series of data requests
// on a serial monitor, occasionally one sees a NAK and a short flurry of retries.
void Update_register (void)          // copy flag data to registers
{
    register_available = FALSE;

    if (register_write)
    {
        memcpy_xx ((uint8x_t *) &Totals, (uint8x_t *)&Registers, sizeof(struct Totals_t));
        #if CONSTANTS_DBG
        get_ce_constants ();         // The meter configuration readable by ICE.
        #endif
        #if REAL_TIME_DATE
        RTClk_Write ();            // Set the clock from the revised totals.
        #endif
       register_write = FALSE;
    }
    else
        memcpy_xx ((uint8x_t *)&Registers, (uint8x_t *)&Totals, sizeof(struct Totals_t));

    register_available = TRUE;
}
#endif

#if TEMPERATURE
static void temperature_lcd (void)
{
    LCD_Number (deltaT, 6, 1);  // Display upto six digits.
    LCD_1DP ();                 // One (1) decimal place.
}
#endif

//--------------------------------------------------//
void meter_lcd (void)            // Meter display.
{
    #if CE_OFF && REAL_TIME_DATE
    if (!CE_ACTIVE && RTC_Tic ())
    {
       LCD_CE_Off ();
       return;
    }
    #endif /* CE_OFF and REAL_TIME_DATE. */

    if (ce_totals_ready)
    {                                // Outputs updated, display.
        ce_totals_ready = FALSE;

        #if SCROLL_METER
        scroll_meter ();
        #endif

        meter_totals (select_total, select_phase);     

        #if HEART_BEAT
        LCD_Heart_Beat ();
        #endif
    }

    #if BROWNOUT_BATMODE
    if (batmode_is_brownout ())
        LCD_Brownout ();
    #endif
}

#if AUTOSLEEP
// gets and displays the brownout data
// This runs in the brownout mode logic, with a (very slow) 32kHz clock,
// so the size of EEPROM data read is intentionally as small as possible.
// That's also why the number is precalculated, and the validity
// test is so simple.
// 
// If this routine is modified to use hardware other than the eeprom and
// LCD, please update batmode_display() in main\batmodes.c to initialize
// the needed hardware.
void meter_brownout_lcd (void)
{
    // get a valid value for the brownout LCD value
    // Is the current RAM image of the brownout cache valid?
    if (brownout_cache_valid != YES) 
    {
        enum EEPROM_RC data *pstatus;
        // no, so try the first eeprom image, in Acc
        pstatus = memcpy_xpr (
           (uint8x_t*)&brownout_cache, 
           (EEPROM_REGISTERS + brownout_cache_offset), 
           brownout_cache_len);
        if (!eeprom_ok (pstatus) || brownout_cache_valid != YES) 
        {
            // no, so try the second eeprom image, in AccB
            // Perhaps the mains sagged while it was being calculated.
            // In that case, the second copy will be ok.
            pstatus = memcpy_xpr (
               (uint8x_t*)&brownout_cache, 
               (EEPROM_REGISTERS 
                   + brownout_cache_offset 
                   + sizeof(struct Accumulators_t)), 
               brownout_cache_len);
            if (!eeprom_ok (pstatus) || brownout_cache_valid != YES) 
            {
                // no, so the EEPROM is bad, the value not set or 
                // the value is overwritten by bad data; substitute
                // a default.
                brownout_cache = 0L;
                brownout_cache_valid = YES;
                #if MODE_DISPLAY
                brownout_cache_mode = M_WH;
                #endif
            }
        }
    }

    // display it
    wh_brownout_to_lcd (brownout_cache); // watts, total, all phases
    #if  MODE_DISPLAY
    LCD_Mode (brownout_cache_mode);
    #endif
}
#endif // autosleep



// Data sources for the LCD; replace entries with nulls to disable
// entries.  The table is fixed-size so meanings of the indices do 
// not change.
const uint8x_t * code LcdSrc[] =
{
    // Note: The register names route the data from the calculations,
    // to the revenue registers.  "Wh" is the name of the revenue 
    // registers, however they are calculated.  For example, meter.h
    // may define Totals.Acc.Whr.a as "Whi", so that it is calculated
    // as "imported watt-hours".  Then, it defines "Wh" as Totals.Acc.Whr.a
    // so that the default display will be the same.  Other calculations
    // can be used, therefore, such as VAh or absolute-value watt-hours.
    (uint8x_t *) &Wh[0],     (uint8x_t *) &Wh_A[0],    (uint8x_t *) &Wh_B[0],    (uint8x_t *) &Wh_C[0],      // 12-15
    (uint8x_t *) &Whe[0],    (uint8x_t *) &Whe_A[0],   (uint8x_t *) &Whe_B[0],   (uint8x_t *) &Whe_C[0],     // 24-27
    (uint8x_t *) &VARhi[0],  (uint8x_t *) &VARhi_A[0], (uint8x_t *) &VARhi_B[0], (uint8x_t *) &VARhi_C[0],   // 16-19
    (uint8x_t *) &VARhe[0],  (uint8x_t *) &VARhe_A[0], (uint8x_t *) &VARhe_B[0], (uint8x_t *) &VARhe_C[0],   // 28-31
    (uint8x_t *) &VAh[0],    (uint8x_t *) &VAh_A[0],   (uint8x_t *) &VAh_B[0],   (uint8x_t *) &VAh_C[0],     //  8-11
};

#if DEMAND
#if PHASE_C_PRESENT
const uint32x_t * code LcdSrcP[] =
{
    &wsum,      &w0sum,     &w1sum,     &w2sum,        
    &varsum,    &var0sum,   &var1sum,   &var2sum,
    &vasum,     &va0sum,    &va1sum,    &va2sum
};
#define NUM_SUMS 4
#else
const uint32x_t * code LcdSrcP[] =
{
    &w0sum,     &w1sum,
    &var0sum,   &var1sum,
    &va0sum,    &va1sum
};
#define NUM_SUMS 2
#endif
#endif // DEMAND.

void meter_totals (uint8_t select, uint8_t phase)
{
    #if  MODE_DISPLAY
    bool show_mode = TRUE;
    #endif

    switch (select)
    {
       // default case is wh, phase0, below
       #if TEMPERATURE
       case M_TEMP:  // Temperature.
          temperature_lcd ();
          break;                
       #endif

       #if  FREQUENCY
       case M_FREQ:  // Frequency.
          frequency_lcd ();
          break;                
       #endif
 
       #if  POWER_FACTOR
       case M_PF: 
          power_factor_lcd (phase);          
          break;
       #endif // POWER_FACTOR.

       #if  PHASE_ANGLES
       case M_VI_ANGLE: // V/I Phase angle.
          phase_angle_lcd (phase);          
          break;                
       #endif // PHASE_ANGLES.
 
       #if  VOLTAGE_PHASES
       case M_VPHASE: 
          voltage_phase_lcd (phase);          
          break;
       #endif // VOLTAGE_PHASES.
 
       #if  OPERATING_TIME
       case M_HOURS:  // Operating Hours.
          operating_lcd ();
          break;                
       #endif

       #if  REAL_TIME_DATE
       case M_TIME:  // Time.
          time_lcd ();
          break;

       case M_DATE:  // Date.
         date_lcd ();
         #if  MODE_DISPLAY
         show_mode = FALSE;
         #endif
         break;
       #endif  // REAL TIME/DATE.

       #if  MAIN_EDGE_COUNT  
       case M_EDGE_CNT: 
          main_edge_cnt_lcd (phase); 
          break;
       #endif // MAIN_EDGE_COUNT.

       #if PULSE_CNT
       case M_PULSE: 
          pulse_cnt_lcd (select_pulse, select_interval); 
          break;
       #endif

       #if WATT_ELEMENT
       case M_NONE:  // Commanded to display nothing.
       default:
          phase = 0;

⌨️ 快捷键说明

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