emeter-communication.c

来自「msp430F437三相电表DEMO(编译器 IAR 3.42A)」· C语言 代码 · 共 896 行 · 第 1/3 页

C
896
字号
}

void process_rx_message(serial_msg_t *rx_msg, int rx_len)
{
    int i;
    int32_t z;
    int32_t z1;
    #if !defined(SINGLE_PHASE)
    struct phase_parms_s *phase;
    #endif
    uint16_t *last_flash_loc;

    /* Messages with type 0x23 are custom messages we
      use for calibration, password protection, etc.
      All other message types go to a custom message
      handler (if available). */
    if (rx_msg->uint8[8] != 0x23)
    {
#if CUSTOM_SERIAL_MESSAGE_SUPPORT
        custom_serial_message_handler(&rx_msg, rx_msg_len);
#endif
        return;
    }
    if ((rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] & 0x80))
    {
        /* This looks like one of our own messages, which has echoed back
           to us */
        return;
    }

    /* Only process messages if the password has been given correctly
       (except for the password test message, of course). */
    if (!(meter_status & PASSWORD_OK)  &&  rx_msg->uint8[IEC1107_MSG_RX_START_BODY] != 0x60)
        return;

    switch (rx_msg->uint8[IEC1107_MSG_RX_START_BODY])
    {
    case HOST_CMD_GET_METER_CONFIGURATION:
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY];
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80;
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 2] = NUM_PHASES;
    #if defined(NEUTRAL_MONITOR_SUPPORT)
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 3] = 1;
    #else
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 3] = 0;
    #endif
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 4] = 0
    #if defined(LIMP_MODE_SUPPORT)
                                                    | 0x01
    #endif
    #if defined(PHASE_CORRECTION_SUPPORT)
                                                    | 0x02
    #endif
    #if defined(DYNAMIC_PHASE_CORRECTION_SUPPORT)
                                                    | 0x04
    #endif
    #if defined(RTC_SUPPORT)
                                                    | 0x08
    #endif
    #if defined(CORRECTED_RTC_SUPPORT)
                                                    | 0x10
    #endif
    #if defined(TEMPERATURE_SUPPORT)
                                                    | 0x20
    #endif
    #if SELF_TEST_SUPPORT
                                                    | 0x40
    #endif
    #if MULTI_RATE_SUPPORT
                                                    | 0x80
    #endif
                                                    ;
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 5] = 0x01
    #if REACTIVE_POWER_SUPPORT
                                                    | 0x02
    #endif
    #if defined(VA_POWER_SUPPORT)
                                                    | 0x04
    #endif
    #if defined(VRMS_SUPPORT)
                                                    | 0x08
    #endif
    #if defined(IRMS_SUPPORT)
                                                    | 0x10
    #endif
    #if defined(POWER_FACTOR_SUPPORT)
                                                    | 0x20
    #endif
    #if defined(MAINS_FREQUENCY_SUPPORT)
                                                    | 0x40
    #endif
                                                    ;
        prepare_tx_message(6);
        break;
    case HOST_CMD_SET_METER_CONSUMPTION:
        z = rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 1];
        z |= (int32_t) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 2] << 16;
        z1 = rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 3];
        z1 |= (int32_t) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 4] << 16;
        custom_set_consumption(z, z1);
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY];
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80;
        prepare_tx_message(2);
    case HOST_CMD_SET_RTC:
    #if defined(RTC_SUPPORT)
        rtc.year = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 2];
        rtc.month = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 3];
        rtc.day = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 4];
        rtc.hour = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 5];
        rtc.minute = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 6];
        rtc.second = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 7];
        set_rtc_sumcheck();
    #endif
    #if defined(CUSTOM_RTC_SUPPORT)
        custom_rtc_set(rx_msg->uint8);
    #endif
    #if defined(MULTI_RATE_SUPPORT)
        multirate_align_with_rtc();
    #endif
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY];
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80;
        prepare_tx_message(2);
        break;
    case HOST_CMD_GET_RTC:
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY];
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80;
    #if defined(RTC_SUPPORT)
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 2] = rtc.year;
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 3] = rtc.month;
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 4] = rtc.day;
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 5] = rtc.hour;
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 6] = rtc.minute;
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 7] = rtc.second;
    #endif
    #if defined(CUSTOM_RTC_SUPPORT)
        custom_rtc_retrieve(tx_msg.uint8);
    #endif
    #if defined(TEMPERATURE_SUPPORT)
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 4] = temperature;
    #endif
        prepare_tx_message(10);
        break;
    case HOST_CMD_SET_PASSWORD:
        /* Check the calibration password */
        if (rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 1] == SERIAL_CALIBRATION_PASSWORD_1
            &&
            rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 2] == SERIAL_CALIBRATION_PASSWORD_2
            &&
            rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 3] == SERIAL_CALIBRATION_PASSWORD_3
            &&
            rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 4] == SERIAL_CALIBRATION_PASSWORD_4)
        {
            meter_status |= PASSWORD_OK;
            tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY];
            tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80;
            prepare_tx_message(2);
        }
        else
        {
            /* Only respond to a bad password, if the password was good before. That lets
               us know we have unset the password OK, but doesn't give any information to
               people trying to attack the meter. */
            if ((meter_status & PASSWORD_OK))
            {
                tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY];
                tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80;
                prepare_tx_message(2);
            }
            meter_status &= ~PASSWORD_OK;
        }
        break;
    case HOST_CMD_GET_READINGS_PHASE_1:
    #if !defined(SINGLE_PHASE)
    case HOST_CMD_GET_READINGS_PHASE_2:
    case HOST_CMD_GET_READINGS_PHASE_3:
        /* Exchange voltage, current and power readings (neutral).
           frequency, power factor and reactive power readings. */
        phase = &chan[rx_msg->uint8[IEC1107_MSG_RX_START_BODY] - 0x61];
    #endif
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY];
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80;
    #if defined(VRMS_SUPPORT)
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = phase->V_rms;
    #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = 0;
    #endif
    #if defined(IRMS_SUPPORT)
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = phase->current.I_rms;
    #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = 0;
    #endif
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 3] = phase->current.power;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 4] = phase->current.power >> 16;
    #if defined(REACTIVE_POWER_SUPPORT)
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = phase->reactive_power;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = phase->reactive_power >> 16;
    #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = 0;
    #endif
    #if defined(VA_POWER_SUPPORT)
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = phase->VA_power;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 8] = phase->VA_power >> 16;
    #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 8] = 0;
    #endif

    #if defined(POWER_FACTOR_SUPPORT)
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 9] = phase->power_factor;
    #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 9] = 0;
    #endif
    #if defined(MAINS_FREQUENCY_SUPPORT)
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 10] = phase->frequency;
    #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 10] = 0;
    #endif
    #if defined(LIMP_MODE_SUPPORT)
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 11] = phase->V_dc_estimate[0];
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 12] = phase->V_dc_estimate[0] >> 16;
    #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 11] = phase->V_dc_estimate;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 12] = phase->V_dc_estimate >> 16;
    #endif
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 13] = phase->current.I_dc_estimate[0];
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 14] = phase->current.I_dc_estimate[0] >> 16;
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 30] = 0;
        prepare_tx_message(31);
        break;
    #if defined(NEUTRAL_MONITOR_SUPPORT)
    case HOST_CMD_GET_READINGS_NEUTRAL:
        /* Exchange voltage, current and power readings (neutral).
           frequency, power factor and reactive power readings. */
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY];
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 1] = rx_msg->uint8[IEC1107_MSG_RX_START_BODY + 1] | 0x80;
        #if defined(SINGLE_PHASE)
            #if defined(VRMS_SUPPORT)
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = phase->V_rms;
            #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = 0;
            #endif
            #if defined(IRMS_SUPPORT)
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = phase->neutral.I_rms;
            #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = 0;
            #endif
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 3] = phase->neutral.power;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 4] = phase->neutral.power >> 16;
            #if REACTIVE_POWER_SUPPORT
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = phase->reactive_power;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = phase->reactive_power >> 16;
            #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = 0;
            #endif
            #if VA_POWER_SUPPORT
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = phase->VA_power;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 8] = phase->VA_power >> 16;
            #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 8] = 0;
            #endif
            #if defined(POWER_FACTOR_SUPPORT)
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 9] = phase->power_factor;
            #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 9] = 0;
            #endif
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 10] = phase->frequency;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 11] = phase->V_dc_estimate[1];
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 12] = phase->V_dc_estimate[1] >> 16;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 13] = phase->neutral.I_dc_estimate;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 14] = phase->neutral.I_dc_estimate >> 16;
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 30] = 0;
        #else
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 1] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 2] = neutral.I_rms;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 3] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 4] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 5] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 6] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 7] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 8] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 9] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 10] = phase->frequency;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 11] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 12] = 0;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 13] = phase->current.I_dc_estimate;
        tx_msg.uint16[IEC1107_MSG_TX_START_BODY_W + 14] = phase->current.I_dc_estimate >> 16;
        tx_msg.uint8[IEC1107_MSG_TX_START_BODY + 30] = 0;
        #endif
        prepare_tx_message(31);
        break;
    #endif
    case HOST_CMD_ERASE_FLASH_SEGMENT:
        /* Initialise flash data download, by erasing the area to be used, and setting the
           write pointer. */
        /* There is no checking here to ensure we do not erase inappropriate places. */
        next_flash_loc = (uint16_t *) rx_msg->uint16[IEC1107_MSG_RX_START_BODY_W + 1];

⌨️ 快捷键说明

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