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

📄 wh.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) 2005 Teridian Semiconductor Corp. All Rights Reserved.    *
 ***************************************************************************/
//**************************************************************************
//  DESCRIPTION: 71M652x POWER METER - Accumulation Routines.
// 
//  AUTHOR:  RGV
//
//  HISTORY: See end of file.
//**************************************************************************
// File: WH.C
//               
#include "options.h"
#if WATT_ELEMENT
#include "mmath.h"
#include "meter.h"
#include "lcd.h"
#include "library.h"
#include "wh.h"    // test the fn prototypes
                                                                              
/*** External functions referenced by this module ***/

/*** External variables referenced by this module ***/
// Refer to "ce652x.h"  include file.

/*** Public variables declared within this module ***/
// None

/*** Private functions declared within this module ***/
#if VA_ELEMENT || NET_METER || AUTOCAL
void wh_sum_net (uint8x_t *s, int32p_t *w)
{
    add8_4 (s, (uint8p_t *) w);
}
#endif
#if ABS_VALUE
void wh_sum_abs (uint8x_t *s, int32p_t *w)
{
    if (*w < 0)
        sub8_4 (s, (uint8p_t *) w);
    else
        add8_4 (s, (uint8p_t *) w);
}
#endif
#if IMPORT
void wh_sum_import (uint8x_t *s, int32p_t *w)
{
    if (*w > 0)
       add8_4 (s, (uint8p_t *) w);
}
#endif // imported power
#if EXPORT
void wh_sum_export (uint8x_t *s, int32p_t *w)
{
    int32_t pdata nw;

    if (*w < 0)
    {
        nw = - *w;    
        add8_4 (s, (uint8p_t *) &nw);
    }
}
#endif // exported power

// Displays milliwatt hours.  Milliwatt hours are absurdly small for a
// real meter, but really very good for demonstrations.
// Most meters will have to change this code in any case.
// The constants have to round -down-, so as not to cheat
// the rate-payers!
#if M6520 || TRACE11
#define WHR_SCALE     1884L    // 6.6952E-12 * 2^48. (1884.53)
#elif TRACE13
#define WHR_SCALE     2647L    // 9.4045E-12 * 2^48. (2647.13)
#else
#error unhandled device type
#endif

#define ONE_MILLION 1000000L
uint32_t wh_to_long (uint8x_t *val)
{
    uint32_t pdata scale;
    uint8_t pdata t[10];
    uint8_t xdata x[13];                        // Need extra digit for divide.
    uint8_t xdata y[12];
    
    // scale = [Vmax * 10E+01] * [Imax * 10E+01].
    scale = (uint32_t) Vmax * (uint32_t) Imax;

    // y = w * Vmax * Imax * 10E+02.
    multiply_8_4 (y, val, (uint8p_t *) &scale);
    // [LSB * 2^48 * 10E+01]  (10E-03 Wh).
    scale = WHR_SCALE;
    // [x * 2^16] = [y / 2^32] * [LSB * 2^48] (mWh)..
    multiply_8_4 (x + 1, y, (uint8p_t *) &scale);
    //..dropped low-order 4-bytes of 'y'.
    *( uint32x_t *) y = ONE_MILLION;             // Modulo ONE_MILLION.
    divide (x + 1, 10, (uint8x_t *) y, 4, t);    // x / 1,000,000;
    x[7] = 0;                                    // Clear high order of 4-byte result.
    return (* (uint32x_t *) &x[7]);
}

static void wh_mission_to_lcd (uint32_t l)
{
    LCD_Number (l, 6, 3);   // Display up to six digits (x % 1,000,000).
    LCD_3DP ();             // Three decimal places.
    LCD_kWH ();
}

#if AUTOSLEEP
void wh_brownout_to_lcd (uint32_t l)
{
    LCD_Number (l, 6, 3);   // Display up to six digits (x % 1,000,000).
    LCD_3DP ();             // Three decimal places.
    LCD_AutoSleep ();
    LCD_kWH ();
}
#endif

void wh_lcd (uint8x_t *val)
{
    wh_mission_to_lcd (wh_to_long (val));
} 

#if DEMAND
// Displays mWATTs, mVARs or mVAs.
#if M6520 || TRACE11
#define WATT_SCALE   (6.6952E-12 * 3600.)
#elif TRACE13
#define WATT_SCALE   (9.4045E-12 * 3600.)
#else
#error unhandled device type
#endif

uint32_t w_to_long (uint32_t val)
{   
    return (lroundf ((float)(Vmax * Imax) * (float)(val) * WATT_SCALE));
}

static void w_mission_to_lcd (uint32_t l)
{
    LCD_Number (l, 6, 3);   // Display up to six digits.
    LCD_3DP ();             // Three decimal places.
    LCD_kW  ();
}

void w_lcd (uint32_t val)
{
   w_mission_to_lcd (w_to_long (val));          
}
#endif // DEMAND.

#ifdef EQUATION

#define PHASE_B_CALCULATED (PHASE_B_PRESENT || EQUATION == _1ELEMENT_3WIRE)

#define PHASE_C_CALCULATED (EQUATION == _2ELEMENT_4WIRE_DELTA || EQUATION == _3ELEMENT_4WIRE_WYE)

void wh_accumulate (void)
{
    int32_t pdata wh0, wh1;
    #if PHASE_C_CALCULATED
    int32_t pdata wh2;
    #endif

    #if !TAMPER_RESISTANT
    // no tampering
    wh0 = w0sum;
    wh1 = w1sum;
    #if PHASE_C_CALCULATED
    wh2 = w2sum;
    #endif
    #else
    if (!MAGNETIC_TAMPER)
    {
        if (!NEUTRAL_DETECTED)
        {
            // no tampering
            wh0 = w0sum;
            wh1 = w1sum;
            #if PHASE_C_CALCULATED
            wh2 = w2sum;
            #endif
        }
        else
        {
            // neutral current detected
            #if M6520 || TRACE11
            // 4.9e-5 is sqrt(6.6952e-13*3600)*10, from data sheet, def. Vcal
            float Vnom = ((float)Vcal) / (4.90945e-5 * (float)Vmax);
            #elif TRACE13
            // 5.82e-5 is sqrt(9.4045e-13*3600)*10, from data sheet, def. Vcal
            float Vnom = ((float)Vcal) / (5.81861e-5 * (float)Vmax);
            #else
            #error unknown device
            #endif
            #if PHASE_A_PRESENT
            wh0 = Irms_A * Vnom;
            #endif
            #if PHASE_B_CALCULATED
            wh1 = Irms_B * Vnom;
            #endif
            #if PHASE_C_CALCULATED
            wh2 = Irms_C * Vnom;
            #endif
        }
    }
    else
    {
        // Magnetic tampering detected
        #if M6520 || TRACE11
        int32_t Whnom = (int32_t)(
                ((float)Vcal * (float)Ical)
                / (6.6952e-13 * (float)Vmax * (float)Imax * 3600.879)
                );
        #elif TRACE13
        int32_t Whnom = (int32_t)(
                ((float)Vcal * (float)Ical)
                / (9.4045e-13 * (float)Vmax * (float)Imax * 3600.879)
                );
        #else
        #error unknown device
        #endif
        wh0 = Whnom;
        wh1 = Whnom;
        #if PHASE_C_CALCULATED
        wh2 = Whnom;
        #endif
    }

    #if DEMAND
    w0sum = wh0;                            // Tamper corrected values.
    w1sum = wh1;
    #if PHASE_C_CALCULATED
    w2sum = wh2;
    #endif
    #endif // DEMAND.
    #endif // tamper resistant

    // Calculate net metering (also used in calibration)
    #if NET_METER || AUTOCAL
    #if PHASE_A_PRESENT
    wh_sum_net (Whn_A, &wh0);             // Watt hours phase A. 
    #endif // element A
    #if PHASE_B_CALCULATED
    wh_sum_net (Whn_B, &wh1);             // Watt hours phase B. 
    #endif // element B

⌨️ 快捷键说明

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