/****************************************************************************** 版权所有: 文件名称: factor.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2013-05-20 功能说明: 通道参数处理。 其它说明: 修改记录: */ /*------------------------------- 头文件 -------------------------------------- */ #include "head.h" /*------------------------------- 宏定义 -------------------------------------- */ #define FACTOR_P_BASE (-360.0/32/8) //CT PT标度,1V或1A对应的码值 // = (二次有效值/一次有效值)*(AD码值范围/电压范围(V))*1.4142 // = (7.07/一次有效值)*(65536/20)*1.4142 // = (7.07*65536/20*1.4142)/ 一次有效值. #define SCALE_PT_BIG (32768.0) // 二次有效值为7.07V或3.53V,需对应改变ADC的输入范围 #define SCALE_CT_BIG (32768.0) // 二次有效值为7.07V或3.53V,需对应改变ADC的输入范围 // 使用初级电阻标识 #define SCALE_PT_102K (1.650*32768/5.0*1.4142) // DTU FTU使用电阻配置100V #define SCALE_PT_120K (1.032*32768/2.5*1.4142) //153K #define SCALE_PT_150K (1.0348*32768/2.5*1.4142) // 开普测试,测量范围264 增加了电阻 #define SCALE_PT_172K (0.916*32768/2.5*1.4142) // 加264V相电压二次用万用表测有效值为0.916v #define SCALE_PT_204K (0.513*32768/2.5*1.4142) // 次级电阻200k 最终版本 // 使用次级电阻标识 #define SCALE_CT_100A_51 (2.526*32768/5.0*1.4142) // 次级电阻51欧,,加5A相电流二次用万用表测有效值为0.127V #define SCALE_CT_10A_51 (0.254*32768/2.5*1.4142) // 次级电阻51欧,加10A相电流二次用万用表测有效值为0.254V #define SCALE_CT_10A_120 (1.27*32768/2.5*1.4142) // 次级电阻249欧,加10A相电流二次用万用表测有效值为0.643V // 零序穿心5倍 最大量程20A #define SCALE_CT_10A_249 (1.265*32768/5.0*1.4142) // 1ACT 量程20A #define SCALE_CT_10A_604 (3.235*32768/5.0*1.4142) // 次级电阻604欧,加10A相电流二次用万用表测有效值为3.235V #define SCALE_EVT (32768.0) #define SCALE_ECT (32768.0) #define SCALE_PT_DEFAULT SCALE_PT_204K #define SCALE_CT_DEFAULT SCALE_CT_100A_51 /*------------------------------ 类型结构 ------------------------------------- */ /*------------------------------ 全局变量 ------------------------------------- */ // 比例系数计算方法请参考<电子互感器比例系数计算方法.xlsx> static const float g_e_k[EQU_SCALE_NUM] = { SCALE_PT_BIG/(220*1.2), SCALE_PT_DEFAULT/(220*1.2), SCALE_EVT/(108.7856586), // EQU_SCALE_EVT_3V25_100V,10/(3.25*1.414)*100; SCALE_EVT/(31.31), // EQU_SCALE_EVT 最大测到30V #if 1 SCALE_CT_BIG/54.752, #else SCALE_CT_BIG/100, #endif SCALE_CT_DEFAULT/100 , SCALE_ECT/(10.60660172), // EQU_SCALE_ECT_1V_1A, 1V=1A SCALE_ECT/(11.73797257), // EQU_SCALE_ECT_0V2_1A,0.2V=1A. SCALE_CT_10A_51/10 , SCALE_PT_102K/(220*1.2), SCALE_PT_120K/(220*1.2), SCALE_PT_172K/(220*1.2), SCALE_PT_204K/(220*1.2), SCALE_CT_10A_604/10 , SCALE_CT_10A_120/10 , SCALE_CT_10A_249/10 , }; //一次/二次变比 static const float g_e_ps[EQU_SCALE_NUM] = { 10000.0/220.0, 10000.0/100.0, 10000.0/100.0, // EQU_SCALE_EVT_3V25_100V,10/(3.25*1.414)*100; 5773.502692/(100.0/3), // EQU_SCALE_EVT_6V50_100V, 600.0/5.0, 600.0/5.0, 600.0/1.0, // EQU_SCALE_ECT_1V_1A, 1V=1A 20.0/1.0, // EQU_SCALE_ECT_0V2_1A,0.2V=1A. 600.0/1.0, 10000.0/100.0, 10000.0/100.0, 10000.0/100.0, 10000.0/100.0, 10000.0/100.0, 10000.0/100.0, 10000.0/100.0, }; // 电子互感器和电磁互感器二次值换算的比值 const float g_e_k_ECVT[EQU_SCALE_NUM] = { 1.0, 1.0, 0.0325, // EQU_SCALE_EVT_3V25_100V,10/(3.25*1.414)*100; 0.065, // EQU_SCALE_EVT_6V50_100V, 1.0, 1.0, 1.0, // EQU_SCALE_ECT_1V_1A, 1V=1A 0.2, // EQU_SCALE_ECT_0V2_1A,0.2V=1A. 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, }; struct ac_slot_factor g_ac_factor[EQU_SLOT_AC_NUM]; u32 g_factor_version = ACFACTOR_FILE_VERSION; u16 g_base_v,g_base_i; /*------------------------------ 函数声明 ------------------------------------- */ int factor_read_all(void); int factor_printf_temp(void); /*------------------------------ 外部函数 ------------------------------------- 外部函数供其它实体文件引用,必须仔细检查传入参数的合法性. */ int factor_init(void) { int slot,ret; // 取默认值 g_factor_version = ACFACTOR_FILE_VERSION; for(slot=0; slot= EQU_SLOT_AC_NUM || asf == NULL) { return -1; } memcpy ((u8*)asf, &g_ac_factor[slot], sizeof(struct ac_slot_factor)); return 0; } /****************************************************************************** 函数名称: factor_write 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-10-23 函数说明: 创建交流系数文件 参数说明: 无 返回值: 成功返回0. 修改记录: */ int factor_write(u32 slot,struct ac_slot_factor *asf) { // 检查参数 slot -= g_ac_slot_begin; if(slot >= EQU_SLOT_AC_NUM || asf == NULL) { return -1; } memcpy (&g_ac_factor[slot],(u8*)asf, sizeof(struct ac_slot_factor)); return 0; } /****************************************************************************** 函数名称: factor_read 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-10-23 函数说明: 读取交流系数文件 参数说明: 无 返回值: 成功返回0. 修改记录: */ int factor_read_all(void) { int len; u16 crc; u8 *buf; off_t pos; struct file * pfile; //int file_size; struct acfactor_file_head_data *brh; // 创建并打开文件 pfile = (struct file *)rt_file_open("/app/data/acfactor.bin",O_RDWR,0); if(IS_ERR(pfile)) { return -2; } // 得到文件长度 len = rt_file_getfile_size(pfile); if(len <= 0) { rt_file_close(pfile, 0); return -21; } // 分配内存 buf = (u8 *)rt_malloc(len); if((buf) == NULL) { rt_file_close(pfile,0); return -3; } // 读出内容 pos = 0; if(rt_file_read(pfile,buf,len,&pos) != len) { rt_file_close(pfile,0); rt_free(buf); return -4; } // 关闭文件 rt_file_close(pfile,0); // 检查CRC crc = CrcStr(buf,len-2); if(crc != *(u16*)(buf+len-2)) { rt_free(buf); return -5; } // 检查文件签名 brh = (struct acfactor_file_head_data*)buf; if(brh->cfh.signature != SIG_ACFACTOR_FILE) { rt_free(buf); return -6; } #if 0 // 检查文件版本 if(brh->cfh.version != ACFACTOR_FILE_VERSION) { rt_free(buf); return -66; } #endif //noted by sunxi: 20220413 暂进屏蔽 #if 0 // 检查FLASH唯一ID号 if (memcmp (brh->auth_id, g_auth_id, 8) != 0) { rt_free(buf); return -7; } #endif // 检查板卡数量 if(brh->num != EQU_SLOT_AC_NUM) { rt_free(buf); return -77; } // 检查文件长度 if(len < (int)(sizeof(*brh) + brh->num*sizeof(struct ac_slot_factor)+ 2)) { rt_free(buf); return -8; } //取出文件中存储内容 g_factor_version = brh->cfh.version; g_base_v = brh->base_v; g_base_i = brh->base_i; memcpy ((u8*)g_ac_factor, buf+brh->addr, EQU_SLOT_AC_NUM*sizeof(struct ac_slot_factor)); rt_free(buf); return 0; } int factor_write_all(u16 base_v,u16 base_i) { unsigned int addr,file_length; u16 crc; char *p; off_t pos; int pfile; struct acfactor_file_head_data acfactor_file; // 写文件头 memset(&acfactor_file,0,sizeof(acfactor_file)); acfactor_file.cfh.signature = SIG_ACFACTOR_FILE; acfactor_file.cfh.version = ACFACTOR_FILE_VERSION; memcpy (&acfactor_file.auth_id, g_auth_id, 8); acfactor_file.base_v = base_v ? base_v : g_base_v; acfactor_file.base_i = base_i ? base_i : g_base_i; g_base_v = acfactor_file.base_v; g_base_i = acfactor_file.base_i; acfactor_file.addr = FILE_ADDR_ALGIN(sizeof(acfactor_file)); acfactor_file.num = EQU_SLOT_AC_NUM; // 得到文件长度 addr = acfactor_file.addr + acfactor_file.num * sizeof(struct ac_slot_factor); file_length = FILE_ADDR_ALGIN(addr); // 分配并初始化空间 p = (u8 *)rt_malloc(file_length + 2); if(!p) { rt_err_set(ERR_CODE_FACTOR,0); return -2; } memset(p, 0, file_length + 2); // 写入文件头 memcpy(p, (char *)&acfactor_file, sizeof(acfactor_file)); // 写系数 memcpy(p+acfactor_file.addr, g_ac_factor, EQU_SLOT_AC_NUM * sizeof(struct ac_slot_factor)); // 计算CRC crc = CrcStr(p, file_length); memcpy(p+file_length, &crc, 2); //swap16(p+file_length);//added by sunxi: 大小端问题 ----- 维护工具好像没有处理crc的大小端 // 创建数据文件 pfile = rt_file_open("/app/data/acfactor.bin",O_CREAT|O_RDWR|O_TRUNC,0); if(IS_ERR(pfile)) { rt_err_set(ERR_CODE_FACTOR,0); rt_free(p); return -3; } pos = 0; rt_file_write(pfile, p, file_length+2, &pos); rt_file_close(pfile,0); rt_free(p); system("sync");//noted by sunxi: 把写好的文件,写到系统中去,不然,断电重启,有机会掉失 //清除交流告警灯 rt_err_clr(ERR_CODE_FACTOR,0); return 0; } int factor_write_board(u32 slot,struct ac_slot_factor *asf) { int ret ; ret = factor_write(slot,asf); if(ret != 0) { rt_err_set(ERR_CODE_FACTOR,slot); rt_printf("factor_write_board:slot=%lu,ret=%d.\r\n",slot,ret); return -1; } g_base_v = 0; g_base_i = 0; ret = factor_write_all(0,0); return ret; } int factor_get_default(struct ac_slot_factor *asf) { int i; if(asf == NULL) { return -1; } for(i=0; ifactor_e_c[i] = 1.0; asf->factor_p_c[i] = 0.0; #ifdef PROTECT_AC_ADJUST asf->factor_p_e_c[i] = 1.0; #endif asf->pq_factor[i][0] = 0.0; asf->pq_factor[i][1] = 0.0; } asf->temp = 35.0; return 0; } int factor_restore_default(void) { int slot,ret ; // 取默认值 g_factor_version = ACFACTOR_FILE_VERSION; for(slot=0; slot=(u32)equ_get_ac_num(slot)) { return -1; } if(f == NULL) { return -2; } slot -= g_ac_slot_begin; if(slot >= EQU_SLOT_AC_NUM) { return -3; } *f = g_ac_factor[slot].factor_e_c[index]; return 0; } int factor_e_c_set(u32 slot,u32 index,float f) { // 检查参数 if(index >=(u32)equ_get_ac_num(slot)) { return -1; } slot -= g_ac_slot_begin; if(slot >= EQU_SLOT_AC_NUM) { return -2; } g_ac_factor[slot].factor_e_c[index] = f; return 0; } int factor_p_c_get(u32 slot,u32 index,float *f) { // 检查参数 if(index >=(u32)equ_get_ac_num(slot)) { return -1; } if(f == NULL) { return -2; } slot -= g_ac_slot_begin; if(slot >= EQU_SLOT_AC_NUM) { return -3; } *f = g_ac_factor[slot].factor_p_c[index]; return 0; } int factor_p_c_set(u32 slot,u32 index,float f) { // 检查参数 if(index >=(u32)equ_get_ac_num(slot)) { return -1; } slot -= g_ac_slot_begin; if(slot >= EQU_SLOT_AC_NUM) { return -2; } g_ac_factor[slot].factor_p_c[index] = f; return 0; } #ifdef PROTECT_AC_ADJUST int factor_p_e_c_get(u32 slot,u32 index,float *f) { // 检查参数 if(index >=(u32)equ_get_ac_num(slot)) { return -1; } if(f == NULL) { return -2; } slot -= g_ac_slot_begin; if(slot >= EQU_SLOT_AC_NUM) { return -3; } *f = g_ac_factor[slot].factor_p_e_c[index]; return 0; } int factor_p_e_c_set(u32 slot,u32 index,float f) { // 检查参数 if(index >=(u32)equ_get_ac_num(slot)) { return -1; } slot -= g_ac_slot_begin; if(slot >= EQU_SLOT_AC_NUM) { return -2; } g_ac_factor[slot].factor_p_e_c[index] = f; return 0; } #endif int factor_pq_get(u32 slot,u32 index,float *f) { // 检查参数 if(index >=(u32)equ_get_ac_num(slot)) { return -1; } if(f == NULL) { return -2; } slot -= g_ac_slot_begin; if(slot >= EQU_SLOT_AC_NUM) { return -3; } *f++ = g_ac_factor[slot].pq_factor[index][0]; *f = g_ac_factor[slot].pq_factor[index][1]; return 0; } int factor_pq_set(u32 slot,u32 index,float *f) { // 检查参数 if(index >=(u32)equ_get_ac_num(slot)) { return -1; } if(f == NULL) { return -2; } slot -= g_ac_slot_begin; if(slot >= EQU_SLOT_AC_NUM) { return -3; } g_ac_factor[slot].pq_factor[index][0] = *f++; g_ac_factor[slot].pq_factor[index][1] = *f; return 0; } float factor_e_k(u32 index) { if(index >= EQU_SCALE_NUM) { return -1; } return g_e_k[index]; } float factor_e_ps(u32 index) { if(index >= EQU_SCALE_NUM) { return -1; } return g_e_ps[index]; } float factor_p_k(u32 index) { if(index >= CFG_ADC_CHANNEL) { return 0; } #ifdef BSP_DTU2 // 只有DTU2.0是分时通道切换采样的,所有有理论的角度偏差。 //#if 1 // 目前先使用此值,以保证已校准设备的兼容性 return (index/8)*FACTOR_P_BASE ; #else #ifdef BSP_DTU3 // 保持旧版本的兼容性 { u32 us; if(g_factor_version != ACFACTOR_FILE_VERSION) { return (index/8)*FACTOR_P_BASE ; } //1倍过采样延时1us us = (index%16)/2*CFG_ADC_OS_NUM; return -g_freq*us/1000000.0*360 ; } #else return 0; #endif #endif } int factor_temp_get(int slot,float *temp) { // 检查参数 slot -= g_ac_slot_begin; if(slot >= EQU_SLOT_AC_NUM) { return -1; } *temp = g_ac_factor[slot].temp; return 0; } int factor_temp_set(int slot,float temp) { // 检查参数 slot -= g_ac_slot_begin; if(slot >= EQU_SLOT_AC_NUM) { return -1; } g_ac_factor[slot].temp = temp; return 0; } /*------------------------------ 内部函数 ------------------------------------- 内部函数以下划线‘_’开头,不需要检查参数的合法性. */ /*------------------------------ 测试函数 ------------------------------------- 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数). */ int factor_printf(void) { int slot,j; float f; rt_printf("校正系数:\r\n"); rt_printf("版本:0x%08lx.\r\n",g_factor_version); rt_printf("最后校准基准值:电压=%d,电流=%d.\r\n",g_base_v,g_base_i); for(slot=0; slot