Files
chrg/apps/chrg/applications/thread/chrg_roll_nor.c
T
yhf c820aad809 feat: 完成项目多模块功能迭代与配置更新
1. 新增sqlite文件、协议文档、调试截图、配置ini等各类辅助文件
2. 更新Keil开发包版本与工程配置,调整编译优化等级
3. 重构继电器控制逻辑、串口收发逻辑与线程优先级
4. 新增Modbus寄存器映射、校准结构体与Ymodem升级相关代码
5. 完善南北向协议解析、快充挡位配置与调试日志
6. 修复注释格式、数组越界与线程邮箱溢出问题
7. 新增屏幕控制、功率板调试与协议格式说明文档
2026-07-18 15:32:54 +08:00

875 lines
23 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/****************************************************************************
文件名称 : chrg_roll_nor.c
完成日期 :
当前版本号 : V1.0
主要功能 : 实现北向通信轮巡请求命令。以独立线程处理。
版本历史 : 创建原始版本
说明 :
******************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <rtthread.h>
#include "chrg_gpio.h"
#include "chrg_led.h"
#include "chrg_thread.h"
#include "chrg_sink.h"
#include "chrg_source.h"
#include "chrg_roll_nor.h"
#include "chrg_north.h"
#include "chrg_switch.h"
#include "chrg_utils.h"
#include "chrg_rel.h"
#include "chrg_wdt.h"
#define LOG_TAG "chrg.rollnor"
#include <rtdbg.h>
const rt_base_t sw_uart[TOTAL_NOR_CHS] = {
IDX_GPO_UART_SW1,
IDX_GPO_UART_SW2,
IDX_GPO_UART_SW3,
IDX_GPO_UART_SW4
};
struct chrg_rollnor_t chrgrollnor = {
.run = RUN_CONSOLE, // RUN_AUTO,
.ch = IDX_NOR_CH1,
// .Set_Role = ID_SINK,
// .group = 0,
};
/*****************************************************************
函数名称: sink_fill_pd_buf
函数描述: 根据快充协议类型填充PD指令的5字节数据缓冲区
输入参数:
pd_val: 快充协议类型(如0xC1/0xF8/0xFB等)
pd_volt: 电压值(mV16位)
pd_curr: 电流值(mA16位)
buf: 输出缓冲区
输出参数: buf: 填充后的5字节协议数据
返回说明: 0:成功 -1:参数错误
*****************************************************************/
int sink_fill_pd_buf(rt_uint8_t group,rt_uint8_t pd_val, rt_uint16_t pd_volt, rt_uint16_t pd_curr,rt_uint8_t *buf)
{
// 参数合法性校验
if (buf == RT_NULL) {
rt_kprintf("sink_fill_pd_buf: buf is a null pointer!\n");
return -1;
}
// 先清空缓冲区(默认全0
rt_memset(buf, 0, 5);
// 按协议类型填充buf
switch(pd_val) {
// 标准/QC2.0/QC3.0/FCP(仅电压,第五位=电压)
case 0xFE: // 标准协议
case 0xF8: // QC2.0协议
case 0xF6: // QC3.0协议
case 0xF2: // FCP协议
buf[0] = pd_volt / 100; // 第5字节=电压(0.1V)
buf[1] = pd_curr / 100; // 第6字节=电流(0.1A)
#if PRO_TEST_DEBUG
rt_kprintf("type: %02X, Voltage(0.1V)=%d\n", pd_val, pd_volt/100);
rt_kprintf("type: %02x, Curr(0.1A)=%d\n",pd_curr,pd_curr/100);
#endif
break;
// PDO/PPS/PD3.1/UFCS/AVS(组号+电压+电流)
case 0xFC: // PPS手动/自动
case 0xE3: // AVS协议
buf[0] = group; // 第5字节=组号(默认0
buf[1] = (pd_volt >> 8) & 0xFF; // 第6字节=电压高8位(mV)
buf[2] = pd_volt & 0xFF; // 第7字节=电压低8位(mV)
buf[3] = (pd_curr >> 8) & 0xFF; // 第8字节=电流高8位(mA)
buf[4] = pd_curr & 0xFF; // 第9字节=电流低8位(mA)
#if PRO_TEST_DEBUG
rt_kprintf("type: %02X, Group=0, Voltage=%d mV, Current=%d mA\n", pd_val, pd_volt, pd_curr);
#endif
break;
case 0xE0: // UFCS协议
case 0xE1: // PD3.1协议
case 0xFB: // PDO手动
buf[0] = 0x00; // 第5字节=组号(默认0
buf[1] = (pd_volt >> 8) & 0xFF; // 第6字节=电压高8位(mV)
buf[2] = pd_volt & 0xFF; // 第7字节=电压低8位(mV)
buf[3] = (pd_curr >> 8) & 0xFF; // 第8字节=电流高8位(mA)
buf[4] = pd_curr & 0xFF; // 第9字节=电流低8位(mA)
#if PRO_TEST_DEBUG
rt_kprintf("type: %02X, Group=0, Voltage=%d mV, Current=%d mA\n", pd_val, pd_volt, pd_curr);
#endif
break;
// SCP/VIVO/传音(电压+电流)
case 0xF3: // SCP协议
case 0xFD: // VIVO协议
case 0xF7: // 传音/TFC协议
buf[0] = (pd_volt >> 8) & 0xFF; // 第6字节=电压高8位(mV)
buf[1] = pd_volt & 0xFF; // 第7字节=电压低8位(mV)
buf[2] = (pd_curr >> 8) & 0xFF; // 第8字节=电流高8位(mA)
buf[3] = pd_curr & 0xFF; // 第9字节=电流低8位(mA)
buf[4] = 0;
#if PRO_TEST_DEBUG
rt_kprintf("type: %02X, Voltage=%d mV, Current=%d mA\n", pd_val, pd_volt, pd_curr);
#endif
break;
// VOOC(无参数)
case 0xE2: // VOOC协议
#if PRO_TEST_DEBUG
rt_kprintf("type: VOOC(0xE2), No parameters\n");
#endif
break;
case 0xF9: // AFC协议
{
// 1. 电压转HEX
rt_uint8_t volt_hex = 0;
if (pd_volt >= 5000 && pd_volt <= 20000) { // 电压范围:5V(5000mV)~20V(20000mV)
rt_uint8_t volt_v = pd_volt / 1000; // 转成V5000mV→5V
volt_hex = volt_v - 5; // 5V对应020V对应150xF
} else {
#if PRO_TEST_DEBUG
rt_kprintf("AFC VOLT ERROR VOLT=:%d mV Set 5000~20000\n", pd_volt);
#endif
return -1;
}
// 2. 电流转HEX
rt_uint8_t curr_hex = 0;
if (pd_curr >= 750 && pd_curr <= 3000) { // 电流范围:0.75A(750mA)~3.0A(3000mA)
rt_uint16_t curr_ma_step = (pd_curr - 750) / 150; // 步长150mA0.75→1.5→...→3.0
curr_hex = curr_ma_step; // 0.75A对应03.0A对应150xF
rt_kprintf("curr_ma_step = %d",curr_ma_step);
} else {
#if PRO_TEST_DEBUG
rt_kprintf("AFC CURR ERROR%d mA SET 750~3000 \n", pd_curr);
#endif
return -1;
}
// 3. 合并电压Hex(高4位)和电流Hex(低4位)→ 填充第五字节
buf[0] = (volt_hex << 4) | curr_hex;
rt_kprintf("type: AFC(0xF9), Voltage=%d V, Current=%.2f A, volaue=0x%X\n",
pd_volt/1000, pd_curr/1000.0, buf[0]);
}
break;
// 未知类型
default:
// rt_kprintf("Unknown fast charge type: %02X, Parameters cleared\n", pd_val);
break;
}
return 0;
}
rt_uint16_t v1=0,v2=0;
//电源关闭
void chrg_nor_source_stop(struct chrg_switch_t *pSW,rt_uint8_t idx,rt_uint8_t *enable){
switch(pSW->source.Stop_step_flag){
case 0:
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_WORK, WORK_STOP);
pSW->source.Stop_step_flag = 1;
break;
case 1: // 停止工作
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_WORK, WORK_STOP);
pSW->source.Stop_step_flag = 2;
break;
case 2: // 关闭北向继电器
chrg_nor_sw_rel((eIDX_NOR_CH)idx,0);
pSW->source.Stop_step_flag = 3;
break;
case 3: // 状态2:已执行完停止操作,清空标志位
pSW->source.Set_CV_Flag = 0;
if(pSW->source.change_sink_Flag == 1){
pSW->source.change_sink_Flag = 0;
// chrg_com_sink_on(idx,pSW,enable);
}else{
*enable = 0;
}
break;
default:
pSW->source.Stop_step_flag = 0;
break;
}
}
/*****************************************************************
函数名称: chrg_roll_nor_sw_uart
函数描述: 北向通道切换 sink/source 串口
输入参数: ch: 通道 id: sink/source
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
static void chrg_roll_nor_sw_uart (eIDX_NOR_CH ch, eIDX_ID id)
{
if (ch >= TOTAL_NOR_CHS) {
return ;
}
if (ID_SOURCE == id) {
rt_pin_write(chrgios[sw_uart[ch]].base, PIN_HIGH);
} else if (ID_SINK == id) {
rt_pin_write(chrgios[sw_uart[ch]].base, PIN_LOW);
}
}
//设置负载协议
void chrg_roll_nor_sink_pro_set(struct chrg_switch_t *pSW)
{
rt_uint8_t buf[6] = {0};
sink_fill_pd_buf(pSW->sink.Pro_Group,pSW->sink.protocol,pSW->sink.pro_loadv,pSW->sink.pro_loadc,buf);
sink_set_pd(pSW->sink.protocol,buf);
#if DEBUG_NORTH
rt_kprintf("set_pro\r\n");
#endif
}
//设置电源协议
void chrg_roll_nor_source_pro_set(struct chrg_switch_t *pSW){
if(pSW->source.Set_Pro_Flag == 1){
pSW->source.Set_Pro_Flag = 0;
if(pSW->source.LCD_Set_Pro_Flag==1){
source_set_pd(pSW->source.protocol,0,0,pSW->source.vc.set_voltage,0,pSW->source.vc.set_current);
}
else if(pSW->source.LCD_Set_Pro_Flag==2){
source_set_pd_com(pSW->source.protocol,pSW->source.pro_gear_idx);
}
else if(pSW->source.LCD_Set_Pro_Flag==3){
source_set_pd_new_com(pSW->source.protocol,pSW);
}
}else {
pSW->sub = IDX_GET_SOURCE_VC;
}
}
static int chrg_roll_nor_parse (struct chrg_rollnor_t *pROLL, rt_uint8_t *data)
{
if ((RT_NULL == pROLL)||(RT_NULL == data)) {
return -1;
}
chrg_north_switch(IDX_NOR_CH1);
// 读取北向全局结构体中当前通道的Source/Sink参数
struct chrg_switch_t *pSW = &chrgnorth.sw[pROLL->ch];
if (1 == pROLL->type) {
switch (pROLL->sub) {
case IDX_GET_SOURCE_VC: {
}
break;
case IDX_GET_SOURCE_PD: {
}
break;
case IDX_SET_SOURCE_PD: {
}
break;
case IDX_SET_SOURCE_CCLVL: {
}
break;
default:
return -1;
break;
}
} else if (0 == pROLL->type) {
chrg_roll_nor_sw_uart(IDX_NOR_CH1,ID_SINK);
switch (pROLL->sub) {
case IDX_GET_SINK_VC: {
sink_get_vc(pSW->sink.pro_loadv,pSW->sink.pro_loadc);
}
break;
case IDX_GET_SINK_PD: {
}
break;
case IDX_SET_SINK_PD: {
}
break;
case IDX_SET_SINK_CCLINE: {
}
break;
case IDX_SET_SINK_CCLVL: {
}
break;
default:
return -1;
}
} else {
return -1;
}
return 0;
}
static int chrg_roll_nor_cmd (struct chrg_rollnor_t *pROLL)
{
if (RT_NULL == pROLL) {
return -1;
}
return 0;
}
void chrg_roll_nor_set(rt_uint8_t ch, struct chrg_switch_t *pSW,rt_uint8_t *enable)
{
if(pSW->id==ID_SOURCE){ //电源
chrg_roll_nor_sw_uart((eIDX_NOR_CH)ch, ID_SOURCE);
switch(pSW->sub){
case IDX_SET_SOURCE_ID: //角色
chrg_set_eload_source(ch,pSW);
if(pSW->continue_flag)
pSW->sub = IDX_SET_SOURCE_CC_SET;
// rt_kprintf("set_start\r\n");
break;
case IDX_SET_SOURCE_CC_SET:
source_set_cc_choose(pSW->source.cc_set);
pSW->sub = IDX_SET_SOURCE_CV;
break;
case IDX_SET_SOURCE_CV: //恒压恒流
pSW->sub = IDX_SER_SOURCE_VOLT;
break;
case IDX_SER_SOURCE_VOLT://电压
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_VOLTAGE_OUT+1, 0);
pSW->sub = IDX_SER_SOURCE_CURR;
break;
case IDX_SER_SOURCE_CURR://电流
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_CURRENT_OUT+1, pSW->source.protective_curr);
pSW->sub = IDX_SET_SOURCE_WORK;
break;
case IDX_SET_SOURCE_WORK:
chrg_sou_work(ch,pSW);
break;
case IDX_SET_SOURCE_PD:
chrg_roll_nor_source_pro_set(pSW);
pSW->source.On_Flag = 1;
break;
case IDX_GET_SOURCE_VC:
source_get_vc(pSW->source.vc.set_voltage, pSW->source.vc.set_current);
break;
case IDX_SET_SOURCE_CCLVL:
source_set_cc_lvl(pSW->source.vol_lvl);
break;
case IDX_SET_SOURCE_STOP_STATE:
chrg_nor_source_stop(pSW,ch,enable);
break;
default:
break;
}
}else{
chrg_roll_nor_sw_uart((eIDX_NOR_CH)ch, ID_SINK);
switch(pSW->sub){
case IDX_GET_SINK_VC: //查询
sink_get_vc(pSW->sink.pro_loadv,pSW->sink.pro_loadc);
break;
case IDX_SET_SINK_CCLINE: //CC线选择
sink_set_cc_line(pSW->sink.cc_set);
pSW->sub = IDX_SET_SINK_PD;
break;
case IDX_SET_SINK_CCLVL: //CC电平
sink_set_cc_lvl(pSW->sink.cc_lvl);
break;
case IDX_SET_SINK_PD:
chrg_roll_nor_sink_pro_set(pSW);
pSW->sub = IDX_GET_SINK_VC;
break;
}
}
}
/*****************************************************************
函数名称: chrg_roll_nor_thread_entry
函数描述: 北向通道轮巡请求数据线程体
输入参数: *data: 本线程信息
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
void chrg_roll_nor_thread_entry (void *data)
{
struct chrg_thread_t *pTHR = (struct chrg_thread_t *)data;
if (RT_NULL == pTHR) {
return ;
}
rt_uint8_t index = 0, idx = 0, i = 0;
rt_uint8_t run = 0, crc = 0;
rt_err_t ret = RT_EOK;
struct chrg_rollnor_t *pROLL = &chrgrollnor;
struct chrg_thread_t *pTN = &chrgthr[IDX_THR_NORTH];
struct chrg_north_t *pNOR = &chrgnorth;
struct chrg_switch_t *pSW = RT_NULL;
struct mb_msg_t *pMB_R = RT_NULL;
for (i = 0; i < TOTAL_NOR_CHS; i++) {
chrg_roll_nor_sw_uart((eIDX_NOR_CH)i, ID_SINK);
}
while (1) {
chrg_wdt_feed();
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
run = pROLL->run;
rt_mutex_release(pTHR->mutex);
switch (run) {
case RUN_AUTO: {
idx = index%TOTAL_NOR_CHS;
if (0 == pNOR->enable[idx]) {
index++;
rt_thread_mdelay(2);
continue;
} else {
chrg_led_flashing(IDX_LED2, TIMES_ONE, PULSE_TIME*2, PULSE_TIME*2);
chrg_north_switch((eIDX_NOR_CH)idx);
chrgnorth.idx = idx;
pROLL->idx = idx;
pSW = &pNOR->sw[idx];
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
if(pNOR->north_mode == 0){
chrg_roll_nor_set(pROLL->idx,pSW,&pNOR->enable[idx]);
}
if(pNOR->north_mode == 1){
chrg_roll_trim_set(pROLL->idx,pNOR);
}
rt_mutex_release(pTHR->mutex);
}
index++;
}
break;
case RUN_LCD: {
chrg_roll_nor_cmd(pROLL);
}
break;
case RUN_CONSOLE: {
chrg_roll_nor_cmd(pROLL);
}
break;
case RUN_COM:
// {
// chrg_roll_nor_cmd(pROLL);
// }
break;
case RUN_NONE:
default:
rt_thread_mdelay(5);
continue;
break;
}
ret = rt_mb_recv(pTN->mb, (rt_uint32_t *)&pMB_R, 200); // 超时 200ms
if ((RT_EOK == ret)&&(RT_NULL != pMB_R)) { // 存在返回数据
crc = calc_crc8(pMB_R->payload, pMB_R->length-1);
if (crc == pMB_R->payload[pMB_R->length-1]) { // 数据正确
if (RUN_AUTO != run) { // 恢复自动轮巡
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
pROLL->run = RUN_AUTO;
rt_mutex_release(pTHR->mutex);
} else {
chrg_roll_nor_parse(pROLL, pMB_R->payload);
}
} else {
LOG_E("crc failed.");
}
if (RT_NULL != pMB_R->payload) {
rt_free(pMB_R->payload);
pMB_R->payload = RT_NULL;
}
if (RT_NULL != pMB_R) {
rt_free(pMB_R);
pMB_R = RT_NULL;
}
rt_thread_mdelay(20); // 间隔 200ms
} else {
if (RUN_AUTO != run) { // 非自动轮巡
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
//todo
pROLL->run = RUN_AUTO; // 切换会自动轮巡
rt_mutex_release(pTHR->mutex);
}
}
}
}
#if 1
static int sink (int argc, char **argv)
{
int ret = 0;
if (argc < 4) {
rt_kprintf("help : %s get|set [0-3] vc|pd|ccline|cclvl <data>\r\n", argv[0]);
return -1;
}
int gset = 0;
struct chrg_rollnor_t *pROLL = &chrgrollnor;
if (strcmp(argv[1], "get") == 0) {
gset = 0;
} else if (strcmp(argv[1], "set") == 0) {
gset = 1;
} else {
rt_kprintf("help : %s get|set [0-3] vc|pd|ccline|cclvl <data>\r\n", argv[0]);
return -1;
}
rt_uint8_t ch = (rt_uint8_t)atoi(argv[2]);
if ((ch < 0)||(ch >= TOTAL_NOR_CHS)) {
rt_kprintf("help : %s get|set [0-3] vc|pd|ccline|cclvl <data>\r\n", argv[0]);
return -1;
}
if (strcmp(argv[3], "vc") == 0) {
if (0 == gset) {
pROLL->sub = IDX_SET_SINK_WORK_STATE;
} else {
ret = -1;
rt_kprintf("sink vc can't set.\r\n");
return -1;
}
} else if (strcmp(argv[3], "pd") == 0) {
if (0 == gset) {
pROLL->sub = IDX_GET_SINK_PD;
} else {
//长度
if (argc != 5) {
rt_kprintf("help : %s set 0-3 ccline 0-3.\r\n", argv[0]);
return -1;
// sink_set_pd
} else { // sink set 0 pd 0
int type = atoi(argv[4]);
pROLL->pd = (rt_uint8_t)type;
pROLL->sub = IDX_SET_SINK_PD;
}
}
} else if (strcmp(argv[3], "ccline") == 0) {
if (1 == gset) {
if (argc != 5) {
rt_kprintf("help : %s set 0-3 ccline 0-3.\r\n", argv[0]);
return -1;
} else { // sink set 0 ccline 0-3
int line = atoi(argv[4]);
if ((line >= 0)&&(line <= 3)) {
pROLL->sub = IDX_SET_SINK_CCLINE;
pROLL->cc_line = (rt_uint8_t)line;
} else {
rt_kprintf("help : %s set 0-3 ccline 0-3.\r\n", argv[0]);
return -1;
}
}
} else {
ret = -1;
rt_kprintf("sink cc line can't get.\r\n");
}
} else if (strcmp(argv[3], "cclvl") == 0) {
if (1 == gset) {
if (argc != 5) {
rt_kprintf("help : %s set 0-3 cclvl 0-3.\r\n", argv[0]);
return -1;
} else { // sink set 0 cclvl 0-3
int line = atoi(argv[4]);
if ((line >= 0)&&(line <= 3)) {
pROLL->sub = IDX_SET_SINK_CCLVL;
pROLL->cc_line = (rt_uint8_t)line;
} else {
rt_kprintf("help : %s set 0-3 cclvl 0-3.\r\n", argv[0]);
return -1;
}
}
} else {
ret = -1;
rt_kprintf("sink cc level can't get.\r\n");
}
} else {
ret = -1;
}
if (0 == ret) {
pROLL->ch = ch;
pROLL->type = 0; // sink
pROLL->run = RUN_CONSOLE;
} else {
rt_kprintf("help : %s get|set [0-3] vc|pd|ccline|cclvl\r\n", argv[0]);
}
return ret;
}
MSH_CMD_EXPORT(sink, north sink test);
static int source (int argc, char **argv)
{
int ret = 0;
if (argc < 4) {
rt_kprintf("help : %s get|set [0-3] vc|pd|cclvl <data>\r\n", argv[0]);
return -1;
}
int gset = 0;
struct chrg_rollnor_t *pROLL = &chrgrollnor;
if (strcmp(argv[1], "get") == 0) {
gset = 0;
} else if (strcmp(argv[1], "set") == 0) {
gset = 1;
} else {
rt_kprintf("help : %s get|set [0-3] vc|pd|cclvl <data>\r\n", argv[0]);
return -1;
}
rt_uint8_t ch = (rt_uint8_t)atoi(argv[2]);
if ((ch < 0)||(ch >= TOTAL_NOR_CHS)) {
rt_kprintf("help : %s get|set [0-3] vc|pd|cclvl <data>\r\n", argv[0]);
return -1;
}
if (strcmp(argv[3], "vc") == 0) {
if (0 == gset) {
pROLL->sub = IDX_GET_SOURCE_VC;
} else {
ret = -1;
rt_kprintf("sink vc can't set.\r\n");
return -1;
}
} else if (strcmp(argv[3], "pd") == 0) {
if (0 == gset) {
pROLL->sub = IDX_GET_SOURCE_PD;
} else {
if (argc != 5) {
//if (argc != 5) {
rt_kprintf("help : %s set 0-3 pd 0-.\r\n", argv[0]);
return -1;
// sink_set_pd
} else { // sink set 0 pd 0
int type = atoi(argv[4]);
//协议
pROLL->pd = (rt_uint8_t)type;
//子命令
pROLL->sub = IDX_SET_SOURCE_PD;
}
}
} else if (strcmp(argv[3], "cclvl") == 0) {
if (1 == gset) {
if (argc != 5) {
rt_kprintf("help : %s set 0-3 cclvl 0-3.\r\n", argv[0]);
return -1;
} else { // sink set 0 cclvl 0-3
int line = atoi(argv[4]);
if ((line >= 0)&&(line <= 3)) {
pROLL->sub = IDX_SET_SOURCE_CCLVL;
pROLL->cc_line = (rt_uint8_t)line;
} else {
rt_kprintf("help : %s set 0-3 cclvl 0-3.\r\n", argv[0]);
return -1;
}
}
} else {
ret = -1;
rt_kprintf("sink cc level can't get.\r\n");
}
} else {
ret = -1;
}
if (0 == ret) {
pROLL->ch = ch;
pROLL->type = 1; // source
pROLL->run = RUN_CONSOLE;
} else {
rt_kprintf("help : %s get|set [0-3] vc|pd|cclvl\r\n", argv[0]);
}
return ret;
}
MSH_CMD_EXPORT(source, north source test);
#endif
//校准CRC计算
rt_uint16_t chrg_trim_crc(rt_uint8_t ch, struct chrg_north_t *pNOR)
{
struct chrg_trim *pTrim = &pNOR->trim[ch];
rt_uint8_t buf[22];
int idx = 0;
buf[idx++] = (pTrim->trim_volt_k_H >> 8) & 0xFF;
buf[idx++] = pTrim->trim_volt_k_H & 0xFF;
buf[idx++] = (pTrim->trim_volt_k_L >> 8) & 0xFF;
buf[idx++] = pTrim->trim_volt_k_L & 0xFF;
buf[idx++] = (pTrim->trim_volt_b >> 8) & 0xFF;
buf[idx++] = pTrim->trim_volt_b & 0xFF;
buf[idx++] = (pTrim->trim_curr_k_H >> 8) & 0xFF;
buf[idx++] = pTrim->trim_curr_k_H & 0xFF;
buf[idx++] = (pTrim->trim_curr_k_L >> 8) & 0xFF;
buf[idx++] = pTrim->trim_curr_k_L & 0xFF;
buf[idx++] = (pTrim->trim_curr_b >> 8) & 0xFF;
buf[idx++] = pTrim->trim_curr_b & 0xFF;
buf[idx++] = (pTrim->trim_source_curr_k_H >> 8) & 0xFF;
buf[idx++] = pTrim->trim_source_curr_k_H & 0xFF;
buf[idx++] = (pTrim->trim_source_curr_k_L >> 8) & 0xFF;
buf[idx++] = pTrim->trim_source_curr_k_L & 0xFF;
buf[idx++] = (pTrim->trim_source_curr_b >> 8) & 0xFF;
buf[idx++] = pTrim->trim_source_curr_b & 0xFF;
buf[idx++] = (pTrim->trim_zero >> 8) & 0xFF;
buf[idx++] = pTrim->trim_zero & 0xFF;
return mb_crc16(buf, 20);
}
//电源校准设置
void chrg_trim_set_volt(rt_uint8_t ch,struct chrg_north_t *pNOR){
struct chrg_trim *pTRIM = &pNOR->trim[ch];
switch(pTRIM->trim_step){
case 0:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Volt_CAL_K_H, pTRIM->trim_volt_k_H);
break;
case 1:
break;
case 2:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Volt_CAL_K_L, pTRIM->trim_volt_k_L);
break;
case 3:
break;
case 4:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Volt_CAL_B, pTRIM->trim_volt_b);
break;
pNOR->north_mode = 0;
break;
}
pTRIM->trim_step++;
}
//电流校准设置
void chrg_trim_set_curr(rt_uint8_t ch,struct chrg_north_t *pNOR){
struct chrg_trim *pTRIM = &pNOR->trim[ch];
switch(pTRIM->trim_step){
case 0:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Current_CAL_K_H, pTRIM->trim_curr_k_H);
break;
case 1:
break;
case 2:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Current_CAL_K_L, pTRIM->trim_curr_k_L);
break;
case 3:
break;
case 4:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Current_CAL_B, pTRIM->trim_curr_b);
pNOR->north_mode = 0;
break;
}
pTRIM->trim_step++;
}
//电源校准设置
void chrg_trim_set_source_curr(rt_uint8_t ch,struct chrg_north_t *pNOR){
struct chrg_trim *pTRIM = &pNOR->trim[ch];
rt_uint16_t crc = 0;
switch(pTRIM->trim_step){
case 0:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_SourceCurrent_CAL_K_H, pTRIM->trim_source_curr_k_H);
break;
case 1:
break;
case 2:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_SourceCurrent_CAL_K_L, pTRIM->trim_source_curr_k_L);
break;
case 3:
break;
case 4:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_SourceCurrent_CAL_B, pTRIM->trim_source_curr_b);
break;
case 5:
break;
case 6:
crc = chrg_trim_crc(ch, pNOR);
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Trim_CRC_CAL, crc);
rt_kprintf("crc=%04X\n",crc);
break;
case 7:
break;
case 8:
if(pTRIM->trim_enable_flag == 0){
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_CAL_WriteEnable_ADD,ModbusRTU_CAL_WriteValue);
}else{
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_CAL_WriteRecovery,ModbusRTU_CAL_WriteRecovery_Value);
}
pNOR->north_mode = 0;
break;
}
pTRIM->trim_step++;
}
//校准飘零设置
void chrg_trim_set_zero(rt_uint8_t ch,struct chrg_north_t *pNOR){
struct chrg_trim *pTRIM = &pNOR->trim[ch];
rt_uint16_t crc = 0;
switch(pTRIM->trim_step){
case 0:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Trim_Zero_CAL, pTRIM->trim_zero);
break;
case 1:
break;
case 2:
crc = chrg_trim_crc(ch, pNOR);
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Trim_CRC_CAL, crc);
break;
case 3:
break;
case 4:
if(pTRIM->trim_enable_flag == 0){
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_CAL_WriteEnable_ADD,ModbusRTU_CAL_WriteValue);
}else{
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_CAL_WriteRecovery,ModbusRTU_CAL_WriteRecovery_Value);
}
pNOR->north_mode = 0;
break;
}
pTRIM->trim_step++;
}
//校准设置
void chrg_roll_trim_set(rt_uint8_t ch, struct chrg_north_t *pNOR){
struct chrg_trim *pTRIM = &pNOR->trim[ch];
switch(pTRIM->trim_mode){
case MODE_VOLT_CAL:
chrg_trim_set_volt(ch, pNOR);
break;
case MODE_CURR_CAL:
chrg_trim_set_curr(ch, pNOR);
break;
case MODE_SOURCE_CURR_CAL:
chrg_trim_set_source_curr(ch, pNOR);
break;
case MODE_ZERO_CAL:
chrg_trim_set_zero(ch, pNOR);
break;
}
}