新增 docs/电源流程.md,记录电源各阶段指令流向 更新多个源文件的版本号从 V1.1.24 到对应版本 修改 chrg_rel.c 注释补充继电器包含类型 修改 chrg_source.c、chrg_lcd.c 中部分子命令定义
591 lines
20 KiB
C
591 lines
20 KiB
C
/****************************************************************************
|
||
文件名称 : chrg_eload.c
|
||
完成日期 :
|
||
主要功能 : 源载命令数据解析,封装,读写请求。
|
||
版本历史 : 创建原始版本
|
||
说明 :
|
||
******************************************************************************/
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <rtthread.h>
|
||
#include "chrg_roll_sou.h"
|
||
#include "chrg_north.h"
|
||
#include "chrg_eload.h"
|
||
#include "chrg_lcd.h"
|
||
#include "chrg_regs.h"
|
||
#include "chrg_utils.h"
|
||
#include "chrg_south.h"
|
||
|
||
#define ELOAD_VALID_VOLTAGE_MIN_MV 2000U
|
||
#define DPDM_HOST_READ_SCALE 10U
|
||
|
||
static rt_uint16_t chrg_eload_dpdm_host_value(rt_uint16_t value)
|
||
{
|
||
rt_uint32_t scaled_value = (rt_uint32_t)value * DPDM_HOST_READ_SCALE;
|
||
|
||
return (scaled_value > 0xFFFFU) ? 0xFFFFU : (rt_uint16_t)scaled_value;
|
||
}
|
||
|
||
extern void LCD_SHOW(rt_uint8_t idx, struct eload_p1_t *pP1, struct chrg_eload_t *pLOAD, struct chrg_switch_t *pSW, rt_uint8_t online);
|
||
|
||
/* 每通道P1量测更新序号;32位读写在STM32F405上为原子访问。 */
|
||
static volatile rt_uint32_t g_eload_sample_seq[TOTAL_SOU_CHS] = {0};
|
||
|
||
/*****************************************************************
|
||
函数名称: chrg_eload_get_sample_seq
|
||
函数描述: 获取指定南向通道P1量测数据的更新序号
|
||
输入参数: idx:南向功率板通道
|
||
输出参数: -
|
||
返回说明: 当前通道量测序号,通道非法时返回0
|
||
其它说明: 卸载确认记录命令下发前序号,只接受序号变化后的新量测
|
||
*****************************************************************/
|
||
rt_uint32_t chrg_eload_get_sample_seq(rt_uint8_t idx)
|
||
{
|
||
if (idx >= TOTAL_SOU_CHS) {
|
||
return 0;
|
||
}
|
||
return g_eload_sample_seq[idx];
|
||
}
|
||
typedef struct {
|
||
rt_uint16_t samples[RIPPLE_MEDIAN_WINDOW_SIZE];
|
||
rt_uint16_t filtered_value;
|
||
rt_uint8_t sample_count;
|
||
rt_uint8_t sample_next;
|
||
rt_uint8_t ignore_count;
|
||
rt_uint8_t ignore_total;
|
||
rt_tick_t relay_start_tick;
|
||
rt_uint32_t frame_count;
|
||
rt_bool_t relay_started;
|
||
} chrg_ripple_filter_t;
|
||
|
||
static chrg_ripple_filter_t g_ripple_filter[TOTAL_SOU_CHS] = {0};
|
||
|
||
static rt_uint16_t chrg_eload_ripple_median(rt_uint16_t value0,
|
||
rt_uint16_t value1, rt_uint16_t value2)
|
||
{
|
||
if (value0 > value1) {
|
||
rt_uint16_t temp = value0;
|
||
value0 = value1;
|
||
value1 = temp;
|
||
}
|
||
if (value1 > value2) {
|
||
rt_uint16_t temp = value1;
|
||
value1 = value2;
|
||
value2 = temp;
|
||
}
|
||
if (value0 > value1) {
|
||
value1 = value0;
|
||
}
|
||
return value1;
|
||
}
|
||
|
||
static rt_uint16_t chrg_eload_ripple_filter_update(rt_uint8_t idx,
|
||
rt_uint16_t raw_value)
|
||
{
|
||
chrg_ripple_filter_t *pFilter = &g_ripple_filter[idx];
|
||
|
||
pFilter->frame_count++;
|
||
|
||
if (pFilter->ignore_count > 0U) {
|
||
pFilter->ignore_count--;
|
||
return pFilter->filtered_value;
|
||
}
|
||
pFilter->samples[pFilter->sample_next] = raw_value;
|
||
pFilter->sample_next = (pFilter->sample_next + 1U) % RIPPLE_MEDIAN_WINDOW_SIZE;
|
||
if (pFilter->sample_count < RIPPLE_MEDIAN_WINDOW_SIZE) {
|
||
pFilter->sample_count++;
|
||
}
|
||
if (pFilter->sample_count < RIPPLE_MEDIAN_WINDOW_SIZE) {
|
||
pFilter->filtered_value = raw_value;
|
||
} else {
|
||
pFilter->filtered_value = chrg_eload_ripple_median(
|
||
pFilter->samples[0], pFilter->samples[1], pFilter->samples[2]);
|
||
}
|
||
return pFilter->filtered_value;
|
||
}
|
||
|
||
void chrg_eload_ripple_filter_reset(rt_uint8_t idx)
|
||
{
|
||
chrg_ripple_filter_t *pFilter;
|
||
|
||
if (idx >= TOTAL_SOU_CHS) {
|
||
return;
|
||
}
|
||
pFilter = &g_ripple_filter[idx];
|
||
pFilter->sample_count = 0U;
|
||
pFilter->sample_next = 0U;
|
||
pFilter->ignore_count = (rt_uint8_t)RIPPLE_RELAY_IGNORE_P1_COUNT;
|
||
pFilter->ignore_total = pFilter->ignore_count;
|
||
}
|
||
|
||
void chrg_eload_ripple_filter_relay_start(rt_uint8_t idx)
|
||
{
|
||
chrg_ripple_filter_t *pFilter;
|
||
|
||
if (idx >= TOTAL_SOU_CHS) {
|
||
return;
|
||
}
|
||
pFilter = &g_ripple_filter[idx];
|
||
chrg_eload_ripple_filter_reset(idx);
|
||
pFilter->relay_start_tick = rt_tick_get();
|
||
pFilter->frame_count = 0U;
|
||
pFilter->relay_started = RT_TRUE;
|
||
}
|
||
|
||
void chrg_eload_ripple_filter_relay_stop(rt_uint8_t idx)
|
||
{
|
||
chrg_ripple_filter_t *pFilter;
|
||
|
||
if (idx >= TOTAL_SOU_CHS) {
|
||
return;
|
||
}
|
||
pFilter = &g_ripple_filter[idx];
|
||
pFilter->relay_started = RT_FALSE;
|
||
pFilter->relay_start_tick = 0U;
|
||
pFilter->frame_count = 0U;
|
||
}
|
||
|
||
/* ======================== Ymodem 升级应答缓存 ======================== */
|
||
static rt_uint8_t g_eload_ymodem_resp = 0; // 南向返回的ymodem应答字节(0=无应答)
|
||
static rt_uint8_t g_eload_ymodem_ready = 0; // 应答就绪标志(1=有新应答待取)
|
||
|
||
/*****************************************************************
|
||
函数名称: chrg_eload_set_ymodem_resp
|
||
函数描述: 存储南向板返回的ymodem应答字节(由chrg_roll_sou在RUN_UPDATA调用)
|
||
输入参数: resp: 南向ymodem应答 (ACK=0x06 / NAK=0x15 / 'C'=0x43)
|
||
*****************************************************************/
|
||
#define ELOAD_YMODEM_RESP_DEPTH 8
|
||
static rt_uint8_t g_ymodem_resp_queue[ELOAD_YMODEM_RESP_DEPTH];
|
||
static rt_uint8_t g_ymodem_resp_read = 0;
|
||
static rt_uint8_t g_ymodem_resp_write = 0;
|
||
static rt_uint8_t g_ymodem_resp_count = 0;
|
||
|
||
void chrg_eload_set_ymodem_resp(rt_uint8_t resp)
|
||
{
|
||
rt_base_t level = rt_hw_interrupt_disable();
|
||
|
||
/* 队列已满时丢弃周期性的C,保留更关键的ACK/NAK/CAN。 */
|
||
if (g_ymodem_resp_count >= ELOAD_YMODEM_RESP_DEPTH) {
|
||
if (resp == ACK_C) {
|
||
rt_hw_interrupt_enable(level);
|
||
return;
|
||
}
|
||
g_ymodem_resp_read = (g_ymodem_resp_read + 1) % ELOAD_YMODEM_RESP_DEPTH;
|
||
g_ymodem_resp_count--;
|
||
}
|
||
g_ymodem_resp_queue[g_ymodem_resp_write] = resp;
|
||
g_ymodem_resp_write = (g_ymodem_resp_write + 1) % ELOAD_YMODEM_RESP_DEPTH;
|
||
g_ymodem_resp_count++;
|
||
g_eload_ymodem_resp = resp;
|
||
g_eload_ymodem_ready = 1;
|
||
rt_hw_interrupt_enable(level);
|
||
}
|
||
|
||
/*****************************************************************
|
||
函数名称: chrg_eload_get_ymodem_resp
|
||
函数描述: 读取南向ymodem应答字节(由chrg_comm的ymodem_send调用),读取后自动清除
|
||
返回说明: 南向应答字节,0表示无新应答
|
||
*****************************************************************/
|
||
rt_uint8_t chrg_eload_get_ymodem_resp(void)
|
||
{
|
||
rt_uint8_t resp = 0;
|
||
rt_base_t level = rt_hw_interrupt_disable();
|
||
|
||
if (g_ymodem_resp_count > 0) {
|
||
resp = g_ymodem_resp_queue[g_ymodem_resp_read];
|
||
g_ymodem_resp_read = (g_ymodem_resp_read + 1) % ELOAD_YMODEM_RESP_DEPTH;
|
||
g_ymodem_resp_count--;
|
||
}
|
||
g_eload_ymodem_ready = (g_ymodem_resp_count > 0);
|
||
g_eload_ymodem_resp = g_eload_ymodem_ready ?
|
||
g_ymodem_resp_queue[g_ymodem_resp_read] : 0;
|
||
rt_hw_interrupt_enable(level);
|
||
return resp;
|
||
}
|
||
|
||
/*****************************************************************
|
||
函数名称: chrg_eload_clear_ymodem_resp
|
||
函数描述: 清除ymodem应答缓存(状态切换时调用)
|
||
*****************************************************************/
|
||
void chrg_eload_clear_ymodem_resp(void)
|
||
{
|
||
rt_base_t level = rt_hw_interrupt_disable();
|
||
|
||
g_ymodem_resp_read = 0;
|
||
g_ymodem_resp_write = 0;
|
||
g_ymodem_resp_count = 0;
|
||
g_eload_ymodem_resp = 0;
|
||
g_eload_ymodem_ready = 0;
|
||
rt_memset(g_ymodem_resp_queue, 0, sizeof(g_ymodem_resp_queue));
|
||
rt_hw_interrupt_enable(level);
|
||
}
|
||
|
||
static int memcmp_8bytes(const rt_uint8_t *buf1, const rt_uint8_t *buf2)
|
||
{
|
||
for (int i = 0; i < 8; i++) {
|
||
if (buf1[i] != buf2[i]) {
|
||
return -1;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*****************************************************************
|
||
函数名称: chrg_eload_read_regs
|
||
函数描述: 向南向发送读取寄存器
|
||
输入参数: addr:地址 reg:寄存器起始地址 len:寄存器个数
|
||
输出参数: -
|
||
返回说明: <0: 错误 >0:发送数据长度
|
||
其它说明: -
|
||
*****************************************************************/
|
||
int chrg_eload_read_regs (rt_uint8_t addr, rt_uint16_t reg, rt_uint16_t len)
|
||
{
|
||
rt_uint8_t buf[8] = {0};
|
||
rt_uint16_t crc = 0;
|
||
|
||
buf[0] = addr;
|
||
buf[1] = MB_REGISTER_RD;
|
||
u16_to_u8v(reg, &buf[2]);
|
||
u16_to_u8v(len, &buf[4]);
|
||
crc = mb_crc16(buf, 6);
|
||
u16_to_u8v(swap_u16(crc), &buf[6]);
|
||
|
||
return chrg_south_send(buf, 8);
|
||
}
|
||
|
||
/*****************************************************************
|
||
函数名称: chrg_eload_write_reg
|
||
函数描述: 向南向发送写单个寄存器
|
||
输入参数: addr:地址 reg:寄存器地址 value:写入值
|
||
输出参数: -
|
||
返回说明: <0: 错误 >0:发送数据长度
|
||
其它说明: -
|
||
*****************************************************************/
|
||
|
||
int chrg_eload_write_reg (rt_uint8_t addr, rt_uint16_t reg, rt_uint16_t value)
|
||
{
|
||
rt_uint8_t buf[8] = {0};
|
||
rt_uint16_t crc = 0;
|
||
buf[0] = addr;
|
||
buf[1] = MB_REGISTER_WR;
|
||
u16_to_u8v(reg, &buf[2]);
|
||
u16_to_u8v(value, &buf[4]);
|
||
crc = mb_crc16(buf, 6);
|
||
u16_to_u8v(swap_u16(crc), &buf[6]);
|
||
#if SOUTH_COMMAND_DEBUG
|
||
rt_kprintf("south write: addr=%d reg=0x%04x value=0x%04x\n",
|
||
addr, reg, value);
|
||
#endif
|
||
return chrg_south_send(buf, 8);
|
||
}
|
||
|
||
/* Read the version first so a newly powered south board is not queried with
|
||
* the long measurement frame before its Modbus interface is ready. */
|
||
int chrg_eload_read_version (rt_uint8_t addr)
|
||
{
|
||
return chrg_eload_read_regs(addr, MODBUSRTU_SW_VERSION_REG,
|
||
MODBUSRTU_SW_VERSION_LEN);
|
||
}
|
||
|
||
/*****************************************************************
|
||
函数名称: chrg_eload_send_ymodem_data
|
||
函数描述: 向南向发送ymodem协议升级数据
|
||
输入参数: buf:数据缓冲区 leng:数据长度
|
||
输出参数: -
|
||
返回说明: <0: 错误 >0:发送数据长度
|
||
其它说明: -
|
||
*****************************************************************/
|
||
|
||
int chrg_eload_send_ymodem_data (rt_uint8_t *buf, rt_uint16_t leng)
|
||
{
|
||
if(NULL == buf){
|
||
return 0;
|
||
}
|
||
return chrg_south_send(buf, leng);
|
||
}
|
||
|
||
/**
|
||
|
||
*/
|
||
int chrg_eload_write_More_reg(rt_uint8_t addr,
|
||
rt_uint16_t reg_start,
|
||
rt_uint16_t reg_num,
|
||
const rt_uint16_t *data_buf)
|
||
{
|
||
rt_uint16_t total_len = 7 + (reg_num * 2) + 2;
|
||
rt_uint8_t buf[20] = {0};
|
||
rt_uint16_t idx = 0;
|
||
// 填充Modbus指令帧
|
||
buf[0] = addr; // 0: 设备地址
|
||
// rt_kprintf("addr=%d\r\n", addr);
|
||
buf[1] = MB_REGISTER_MORE_WR; // 1: 功能码(固定0x10)
|
||
idx += 2;
|
||
u16_to_u8v(reg_start, &buf[idx]); // 2-3: 起始地址(idx从2开始)
|
||
idx += 2;
|
||
u16_to_u8v(reg_num, &buf[idx]); // 4-5: 寄存器数量
|
||
idx += 2;
|
||
buf[idx++] = reg_num * 2; // 6: 数据字节数
|
||
// 填充多组数据
|
||
for (rt_uint16_t i = 0; i < reg_num; i++) {
|
||
u16_to_u8v(data_buf[i], &buf[idx]); // 逐个填充数据的高低8位
|
||
idx += 2;
|
||
}
|
||
//计算并填充CRC16校验
|
||
rt_uint16_t crc = mb_crc16(buf, idx); // 计算CRC
|
||
u16_to_u8v(swap_u16(crc), &buf[idx]); // CRC字节序交换后填充
|
||
idx += 2;
|
||
// 发送指令
|
||
return chrg_south_send(buf, idx);
|
||
// 7. 释放动态缓冲区
|
||
|
||
}
|
||
|
||
void chrg_write_cv(rt_uint16_t curr,rt_uint16_t volt)
|
||
{
|
||
rt_uint16_t cv_value[4] = {0};
|
||
cv_value[0] = 0x00;
|
||
cv_value[1] = curr;
|
||
cv_value[2] = 0x00;
|
||
cv_value[3] = volt;
|
||
chrg_eload_write_More_reg(ID_ELOAD, REG_CV, 4,cv_value);
|
||
}
|
||
|
||
rt_uint8_t ret = 0;
|
||
int chrg_eload_send_relay(rt_uint8_t cmd_type)
|
||
{
|
||
rt_uint8_t relay_cmd[8] = {0};
|
||
rt_memcpy(relay_cmd, EXTRA_CMD_SOURCE, 8);
|
||
switch (cmd_type) {
|
||
case 0: // 停止(关闭俩个继电器)
|
||
relay_cmd[5] = 0x00;
|
||
relay_cmd[6] = 0xD9;
|
||
relay_cmd[7] = 0xE8;
|
||
break;
|
||
case 1: // 电源模式(打开主继电器,同时关闭滤波继电器)
|
||
break;
|
||
case 2: // 打开滤波继电器,关闭主继电器
|
||
relay_cmd[5] = 0x02;
|
||
relay_cmd[6] = 0x58;
|
||
relay_cmd[7] = 0x29;
|
||
break;
|
||
case 3: //打开俩个继电器
|
||
relay_cmd[5] = 0x03;
|
||
relay_cmd[6] = 0x99;
|
||
relay_cmd[7] = 0xE9;
|
||
break;
|
||
default:
|
||
return -1; // 无效命令类型
|
||
}
|
||
return chrg_south_send(relay_cmd, 8);
|
||
}
|
||
|
||
/*****************************************************************
|
||
函数名称: chrg_eload_refresh
|
||
函数描述: 分段请求读取寄存器表
|
||
输入参数: addr:地址 part:分段
|
||
输出参数: -
|
||
返回说明: <0: 错误 >0:发送数据长度
|
||
其它说明: 实际运行过程只需要读取前13个寄存器即可,即分段0
|
||
*****************************************************************/
|
||
int chrg_eload_refresh (rt_uint8_t addr, rt_uint8_t part)
|
||
{
|
||
int ret = 0;
|
||
|
||
if (0 == part) {
|
||
chrg_eload_read_regs(addr, REG_STA1, SIZE_P1_RD); // reg 0~18
|
||
} else if (1 == part) {
|
||
chrg_eload_read_regs(addr, REG_POWER, SIZE_P2_RD); // reg 20~39
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
int chrg_eload_parse_version (rt_uint8_t idx, rt_uint8_t *data, rt_uint16_t len)
|
||
{
|
||
rt_uint16_t version;
|
||
|
||
if ((idx >= TOTAL_SOU_CHS) || (data == RT_NULL) ||
|
||
(len != (MODBUSRTU_SW_VERSION_LEN * 2U + 5U)) ||
|
||
(data[0] != ID_ELOAD) || (data[1] != MB_REGISTER_RD) ||
|
||
(data[2] != 2U) || (mb_crc16(data, len) != 0U)) {
|
||
return -1;
|
||
}
|
||
|
||
version = u8v_to_u16(&data[3]);
|
||
|
||
usRegHoldBuf[HOLD_REG_CH0_VERSION + idx * TOTAL_HOLD_CH_REGS] = version;
|
||
return 0;
|
||
}
|
||
|
||
/*****************************************************************
|
||
函数名称: chrg_eload_parse
|
||
函数描述: 解析源载返回数据
|
||
输入参数: idx:通道 pt:分段0 *data:数据区 len:数据长度
|
||
输出参数: -
|
||
返回说明: <0: 错误 0:正确
|
||
其它说明: -
|
||
*****************************************************************/
|
||
int chrg_eload_parse (rt_uint8_t idx, rt_uint8_t pt, rt_uint8_t *data, rt_uint16_t len)
|
||
{
|
||
rt_uint8_t pro = 0;
|
||
if (idx >= TOTAL_SOU_CHS) {
|
||
return -1;
|
||
}
|
||
struct chrg_north_t *pNOR = &chrgnorth;
|
||
struct chrg_south_t *pSOU = &chrgsouth;
|
||
struct chrg_switch_t *pSW = &chrgnorth.sw[idx];
|
||
struct chrg_eload_t *pLOAD = &chrgsouth.eload[idx];
|
||
if ((SIZE_P1_RD*2+5) != len) {
|
||
return -1;
|
||
}
|
||
struct eload_p1_t *pP1 = (struct eload_p1_t *)&data[3];
|
||
|
||
pLOAD->status1 = pP1->status1;
|
||
pLOAD->status2 = pP1->status2;
|
||
pLOAD->fault1 = pP1->fault1;
|
||
pLOAD->fault2 = (rt_uint8_t)pP1->fault2;
|
||
pLOAD->eload = swap_u16(pP1->eload);
|
||
pLOAD->work = (rt_uint8_t)pP1->work_cmd;
|
||
pLOAD->mode = (rt_uint8_t)pP1->work_mode;
|
||
pLOAD->voltage = swap_u32(pP1->voltage);
|
||
pLOAD->current = swap_u32(pP1->current);
|
||
if (pLOAD->current < ELOAD_CURRENT_ZERO_THRESHOLD_MA) {
|
||
pLOAD->current = 0U;
|
||
}
|
||
pLOAD->SHORT_volt = swap_u16(pP1->SHORT_volt);
|
||
pLOAD->SHORT_curr = swap_u16(pP1->SHORT_curr);
|
||
pLOAD->OCP_volt = swap_u16(pP1->OCP_volt);
|
||
pLOAD->OCP_curr = swap_u16(pP1->OCP_curr);
|
||
pLOAD->OCP_volt = swap_u16(pP1->OCP_volt);
|
||
pLOAD->vpkp = swap_u16(pP1->Vpkp);
|
||
pLOAD->vpkn = swap_u16(pP1->Vpkn);
|
||
pLOAD->vpp = swap_u16(pP1->Vpp);
|
||
pLOAD->Ripple = chrg_eload_ripple_filter_update(idx,
|
||
swap_u16(pP1->Ripple));
|
||
// if(idx == IDX_CH3)
|
||
// rt_kprintf("-----Ripple = %d-------\n",pLOAD->Ripple);
|
||
/* 保留功率板返回的真实电流,供卸载保护判断使用。 */
|
||
pSW->Now_current = pLOAD->current;
|
||
/*
|
||
* 低于2V时直接清零量测结果。只清理量测字段,保留工作状态、
|
||
* 故障、模式及测试结果,避免影响通道状态判断。
|
||
*/
|
||
if (pLOAD->voltage < ELOAD_VALID_VOLTAGE_MIN_MV) {
|
||
pLOAD->voltage = 0;
|
||
pLOAD->current = 0;
|
||
pLOAD->vpkp = 0;
|
||
pLOAD->vpkn = 0;
|
||
pLOAD->vpp = 0;
|
||
pLOAD->Ripple = 0;
|
||
chrg_eload_ripple_filter_reset(idx);
|
||
pSW->VZ = 0;
|
||
pSW->VF = 0;
|
||
}
|
||
pSW->Now_voltage = pLOAD->voltage;
|
||
/* 电压、电流均更新完成后再发布序号,避免状态机读取到半更新数据。 */
|
||
g_eload_sample_seq[idx]++;
|
||
#if LCD_OPEN
|
||
if(pNOR->free_flag==0x01){
|
||
LCD_SHOW(idx, pP1, pLOAD, pSW, pSOU->online[idx]);
|
||
}
|
||
#endif
|
||
usRegInBuf[INPUT_REG_CH0_STA1+idx*TOTAL_INPUT_CH_REGS] = pLOAD->status1;
|
||
usRegInBuf[INPUT_REG_CH0_STA2+idx*TOTAL_INPUT_CH_REGS] = pLOAD->status2;
|
||
usRegInBuf[INPUT_REG_CH0_FAULT1+idx*TOTAL_INPUT_CH_REGS] = pLOAD->fault1;
|
||
usRegInBuf[INPUT_REG_CH0_FAULT2+idx*TOTAL_INPUT_CH_REGS] = pLOAD->fault2;
|
||
usRegHoldBuf[HOLD_REG_CH0_ELOAD+idx*TOTAL_HOLD_CH_REGS] = pLOAD->eload;
|
||
usRegHoldBuf[HOLD_REG_CH0_WORK+idx*TOTAL_HOLD_CH_REGS] = pLOAD->work;
|
||
usRegHoldBuf[HOLD_REG_CH0_MODE+idx*TOTAL_HOLD_CH_REGS] = pLOAD->mode;
|
||
usRegHoldBuf[HOLD_REG_CH0_VOL_H+idx*TOTAL_HOLD_CH_REGS] = (pLOAD->voltage>>16)&0xFFFF;
|
||
usRegHoldBuf[HOLD_REG_CH0_VOL_L+idx*TOTAL_HOLD_CH_REGS] = pLOAD->voltage&0xFFFF;
|
||
usRegHoldBuf[HOLD_REG_CH0_CUR_H+idx*TOTAL_HOLD_CH_REGS] = (pLOAD->current>>16)&0xFFFF;
|
||
usRegHoldBuf[HOLD_REG_CH0_CUR_L+idx*TOTAL_HOLD_CH_REGS] = pLOAD->current&0xFFFF;
|
||
// usRegHoldBuf[HOLD_REG_CH0_TEMP+idx*TOTAL_HOLD_CH_REGS] = pLOAD->temperatue;
|
||
// usRegHoldBuf[HOLD_REG_CH0_VERSION+idx*TOTAL_HOLD_CH_REGS] = pLOAD->version;
|
||
// usRegHoldBuf[HOLD_REG_CH0_ADDR+idx*TOTAL_HOLD_CH_REGS] = pLOAD->address;
|
||
usRegHoldBuf[TEST_SHORT_CH0_VOLT+idx*TOTAL_HOLD_CH_REGS] = pLOAD->SHORT_volt;
|
||
usRegHoldBuf[TEST_SHORT_CHO_CURR+idx*TOTAL_HOLD_CH_REGS] = pLOAD->SHORT_curr;
|
||
usRegHoldBuf[TEST_OCP_CHO_VOLT+idx*TOTAL_HOLD_CH_REGS] = pLOAD->OCP_volt;
|
||
usRegHoldBuf[TEST_OCP_CHO_CURR+idx*TOTAL_HOLD_CH_REGS] = pLOAD->OCP_curr;
|
||
usRegHoldBuf[HOLD_REG_CH0_VPKP+idx*TOTAL_HOLD_CH_REGS] = pLOAD->vpkp;
|
||
usRegHoldBuf[HOLD_REG_CH0_VPKN+idx*TOTAL_HOLD_CH_REGS] = pLOAD->vpkn;
|
||
usRegHoldBuf[HOLD_REG_CH0_VPP+idx*TOTAL_HOLD_CH_REGS] = pLOAD->vpp;
|
||
usRegHoldBuf[HOLD_REG_CH0_Ripple+idx*TOTAL_HOLD_CH_REGS] = pLOAD->Ripple;
|
||
/* 上位机D+/D-寄存器按0.001V解释,内部/LCD仍保持0.01V原始值。 */
|
||
usRegHoldBuf[HOLD_REG_CH0_VZ+idx*TOTAL_HOLD_CH_REGS] =
|
||
chrg_eload_dpdm_host_value(pSW->VZ);
|
||
usRegHoldBuf[HOLD_REG_CH0_VF+idx*TOTAL_HOLD_CH_REGS] =
|
||
chrg_eload_dpdm_host_value(pSW->VF);
|
||
return 0;
|
||
}
|
||
|
||
|
||
// 公共格式化辅助函数
|
||
static void snp_ch(char *tmp, rt_uint8_t idx, const char *name, rt_uint32_t val, rt_uint8_t online)
|
||
{
|
||
snprintf(tmp, 36, "status.CH%d_%s.val=%d", idx+1, name, online ? val : 0);
|
||
}
|
||
|
||
// 各显示函数增加 online 入参
|
||
void Show_Volt(rt_uint8_t idx, struct chrg_eload_t *pLOAD, char *tmp, rt_uint8_t online)
|
||
{
|
||
snp_ch(tmp, idx, "Volt", pLOAD->voltage, online);
|
||
}
|
||
void Show_Curr(rt_uint8_t idx, struct chrg_eload_t *pLOAD, char *tmp, rt_uint8_t online)
|
||
{
|
||
snp_ch(tmp, idx, "Curr", pLOAD->current, online);
|
||
}
|
||
void Show_Ripple(rt_uint8_t idx, struct chrg_eload_t *pLOAD, char *tmp, rt_uint8_t online,struct chrg_switch_t *pSW)
|
||
{
|
||
if ((online == 0) ||
|
||
(pSW->Now_voltage < ELOAD_VALID_VOLTAGE_MIN_MV)) {
|
||
snprintf(tmp, 36, "status.CH%d_Ripple.val=0",idx+1);
|
||
return;
|
||
}
|
||
snprintf(tmp, 36, "status.CH%d_Ripple.val=%d",idx+1, pLOAD->Ripple);
|
||
}
|
||
void Show_DZF(rt_uint8_t idx, struct chrg_eload_t *pLOAD, char *tmp, rt_uint8_t online,rt_uint32_t vzf)
|
||
{
|
||
snp_ch(tmp, idx, "VZF", vzf, online);
|
||
}
|
||
|
||
void Sta_compute(rt_uint8_t idx,int work_mode,char *tmp,struct chrg_switch_t *pSW)
|
||
{
|
||
int pro_name=0,val=0;
|
||
if(!pSW)return;
|
||
if(pSW->id==ID_SINK){
|
||
for(int i=0;i<LOAD_PRO_MAP_NUM;i++){
|
||
if(load_pro_map[i].pro_val==pSW->sink.protocol){
|
||
pro_name=load_pro_map[i].pro_name;val=pro_name*1000;
|
||
if(pSW->sink.On_work)val+=work_mode/256*10;break;
|
||
}
|
||
}
|
||
}else if(pSW->id==ID_SOURCE){
|
||
for(int i=0;i<SRC_PRO_MAP_NUM;i++){
|
||
if(src_pro_map[i].pro_val==pSW->source.protocol){
|
||
pro_name=src_pro_map[i].pro_name;val=pro_name*1000+100;
|
||
if(pSW->source.On_Flag)val+=work_mode/256*10;break;
|
||
}
|
||
}
|
||
}
|
||
snprintf(tmp,36,"status.va%d.val=%d",idx+1,val);
|
||
}
|
||
|
||
// 总调度函数
|
||
void LCD_SHOW(rt_uint8_t idx, struct eload_p1_t *pP1, struct chrg_eload_t *pLOAD, struct chrg_switch_t *pSW, rt_uint8_t online)
|
||
{
|
||
char tmp[36] = {0};
|
||
rt_uint32_t vzf = pSW->VZ*1000+pSW->VF;
|
||
switch(pSW->show_step)
|
||
{
|
||
case SHOW_STATUS: Sta_compute(idx, pP1->work_mode, tmp, pSW); pSW->show_step = SHOW_VOLT; break;
|
||
case SHOW_VOLT: Show_Volt(idx, pLOAD, tmp, online); pSW->show_step = SHOW_CURR; break;
|
||
case SHOW_CURR: Show_Curr(idx, pLOAD, tmp, online); pSW->show_step = SHOW_RIPPLE; break;
|
||
case SHOW_RIPPLE: Show_Ripple(idx, pLOAD, tmp, online,pSW); pSW->show_step = SHOW_DZF; break;
|
||
case SHOW_DZF: Show_DZF(idx, pLOAD, tmp, online,vzf); pSW->show_step = SHOW_STATUS; break;
|
||
}
|
||
chrg_lcd_send(tmp);
|
||
}
|