/****************************************************************************** 版权所有: 文件名称: equ.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2013-03-25 功能说明: 装置信息管理维护 其它说明: 修改记录: */ /*------------------------------- 头文件 -------------------------------------- */ #include "head.h" /*------------------------------- 宏定义 -------------------------------------- */ #define EQU_SLOT_CHECK_TIMEOUT 4 // 子板检查超时,以秒为单位,不能小于4s /*------------------------------ 类型结构 ------------------------------------- */ //子板信息帧结构 struct board_info_frame { u8 type; // 子板类型 u8 status :4; // 子板状态 u8 errcode:4; // 子板错误代码 u16 crc; // 子板CRC u32 version; // 子板版本 }; /*------------------------------ 全局变量 ------------------------------------- */ // 控制板类型 u32 g_brd_type_kz; // 模拟量对应关系 static const s8 g_ac_index[BOARD_TYPE_KZ_NUM][EQU_SLOT_AC_CHN] = { {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X04,0X0A,0X0E,0X02,0X08,0X0C,0X00,0X06,0X0F}, // KC00 {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x0E,0x04,0x02,0x08,0x0C,0x00,0x06,0x0A}, // KC08 {0X0C,0X0E,0X01,0X03,0X00,0X02,0X04,0X06,0X08,0X0A,0X05,0X07,0X09,0X0B,0X0D,0X0F}, // KC10,10AC {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X04,0X0A,0X0E,0X02,0X08,0X0C,0X00,0X06,0X0F}, // 一体式分布式DTU控制板 {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x0E,0x04,0x02,0x08,0x0C,0x00,0x06,0x0A}, // 后拔插分布式DTU控制板 FB_V3_22_12 {0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00}, // 18 老版本分布式主板类型,不起作用 {0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00}, // 19 老版本分布式主板类型,不起作用 {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x0E,0x04,0x02,0x08,0x0C,0x00,0x06,0x0A}, // 类型 20 FB_V4_24_12 {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x08,0x0A,0x0C,0x0E,0x06,0x04,0x02,0x00}, //类型 21 FB_V4.1_24_12 {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x08,0x0A,0x0C,0x0E,0x06,0x04,0x02,0x00}, //类型 22 FB_V3.1_22_12 {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x0E,0x04,0x02,0x08,0x0C,0x00,0x06,0x0A}, //类型 23 FB_V3D_1_22_12 {0X01,0X03,0X05,0X07,0X09,0X0B,0X0D,0X0F,0x0E,0x04,0x02,0x08,0x0C,0x00,0x06,0x0A}, //类型 24 V4_D_30_12 }; //遥信转换表 s8 g_change_di_index[BOARD_TYPE_KZ_NUM][EQU_DB_YX_NUM] = { { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32},//13 { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32},//14 FB_V3_22_8 21,20,19,22,23,24,25,26,27,28,29,30,31,32} { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32},//15 { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,00,00,00,00,00,00,00,00,00,00,00,00,00},//16 FBV1_19_6 { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32},//17 FB_V3_22_12 { 1, 2, 3, 5, 7, 9,11,13,15,19,21,23,24,18,17, 4, 6, 8,10,12,14,16,20,22,00,00,00,00,00,00,00,00},//18 null { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32},//19 null { 1, 2, 3, 5, 7, 9,11,13,15,19,21,23,24,18,17, 4, 6, 8,10,12,14,16,20,22,00,00,00,00,00,00,00,00},//20 FB_V4_24_12 { 1, 2, 3, 5, 7, 9,11,13,15,19,21,23,24,18,17, 4, 6, 8,10,12,14,16,20,22,00,00,00,00,00,00,00,00},//21 FB_V4.1_24_12 { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,24,23,21,22,25,26,27,28,29,30,31,32},//22 FB_V3.1_22_12 { 2, 4, 6, 8,10,12,14,15,16, 1, 3, 5, 7, 9,11,13,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32},//23 FB_V3D_122_12 { 1, 3, 5, 7, 9,11,13,15,19,21,25,27,29, 2, 4, 6, 8,10,12,14,16,20,22,26,28,30,17,18,23,24,00,00},//24 V4_D_30_12 }; // 开出对应关系 static const s8 g_do_index[BOARD_TYPE_KZ_NUM][DO_NUM] = { {-1,-1,-1,-1-1,-1,-1,-1-1,-1,-1,-1}, {DO_OUT8,DO_OUT0,DO_OUT1,DO_OUT6,DO_OUT5,DO_OUT2,DO_OUT3,DO_OUT4,DO_OUT7,-1}, //14 {DO_OUT9,DO_OUT0,DO_OUT2,DO_OUT4,DO_OUT6,DO_OUT1,DO_OUT3,DO_OUT5,DO_OUT7,-1}, //15 {-1,-1,-1,-1-1,-1,-1,-1-1,-1,-1,-1}, // 18 老版本分布式主板类型,不起作用 {-1,-1,-1,-1-1,-1,-1,-1-1,-1,-1,-1}, // 19 老版本分布式主板类型,不起作用 // {DO_PWM2,DO_PWM1,DO_OUT7,DO_OUT6,DO_OUT3,DO_OUT2,DO_PWM0,DO_PWM3,DO_OUT0,DO_OUT1,DO_OUT5,-1}, //20 V4 类型20 // {DO_PWM2,DO_PWM1,DO_OUT7,DO_OUT6,DO_OUT3,DO_OUT2,DO_PWM0,DO_PWM3,DO_OUT0,DO_OUT1,DO_OUT5,-1}, //21 V4.1 类型20 // {DO_PWM0,DO_PWM3,DO_OUT0,DO_OUT1,DO_OUT6,DO_OUT5,DO_OUT2,DO_OUT3,DO_OUT4,DO_OUT7,DO_PWM1,-1}, //22 FB_V3.1_22_12 // {DO_PWM0,DO_PWM3,DO_OUT0,DO_OUT1,DO_OUT6,DO_OUT5,DO_OUT2,DO_OUT3,DO_OUT4,DO_OUT7,DO_PWM1,-1}, //23 FB_V3D1_22_12 // {DO_OUT2,DO_OUT3,DO_PWM2,DO_PWM0,DO_PWM3,DO_OUT0,DO_OUT1,DO_OUT6,DO_OUT5,DO_OUT7,DO_PWM1,-1},//24 V4_D_30_12 }; // 采样板索引和插槽的对应关系 const int g_ac_index_to_slot[EQU_SLOT_AC_NUM] = {1}; // 采样板起始槽位,每种机箱不一样。 u32 g_ac_slot_begin; // 记录频率对应ui通道的索引值 int g_ui_freq[CFG_FREQ_NUM]; /*------------------------------ 函数声明 ------------------------------------- */ int equ_slot_config_di(int slot); int equ_slot_config_do(int slot); unsigned int chDi; unsigned int change_di_ch(unsigned int di) { register int i,rts=0; #if 0 static int di_bak; if(di_bak!=di) { rt_printf_time("change_di_ch di=%x \r\n",di); di_bak=di; } #endif for(i=0;i>(g_change_di_index[g_brd_type_kz][i]-1)&0x01) rts|= (1<di_num;i++) { // 开入扫描在156us中断,通过以下算法,得出对应不同防抖延时的最佳动态转换系数,理论误差为156us左右 //g_di_st[ecd->slot][ecd->index].tm_filter = ecd->filter_time * 1000 / 156; if(ecd->filter_time>=10000) { g_di_st[ecd->slot][ecd->index].tm_filter = ecd->filter_time * 3200 / 500; g_di_st[ecd->slot][ecd->index].tm_filter -= (g_di_st[ecd->slot][ecd->index].tm_filter/10000); } else { g_di_st[ecd->slot][ecd->index].tm_filter = ecd->filter_time * 3200 / 500; } //rt_printf("filter_time[%d]=%d\r\n",i,ecd->filter_time); g_di_st[ecd->slot][ecd->index].owner = ecd->owner; g_di_st[ecd->slot][ecd->index].type = ecd->type; ecd++; } return 0; } int equ_config_do(void) { u32 i,index; struct equ_config_do *ecd; memset(&g_do_st,0,sizeof(struct do_struct)*14); // 用户配置的保持时间 ecd = g_equ_config_do; for(i=0;ido_num;i++) { if(ecd->slot == EQU_SLOT_KZ) { index = equ_get_do_channel(ecd->index); g_do_st[index].us_keep = (u32)ecd->time_pulse; g_do_st[index].us_keep *= 1000; //ms转换为us } ecd++; } return 0; } int equ_config_di_yd(void) { u32 i; struct equ_config_di *ecd; // 用户配置的保持时间、拥有者、类型 ecd = g_equ_config_di; for(i=0;idi_num;i++) { // 开入扫描在156us中断,通过以下算法,得出对应不同防抖延时的最佳动态转换系数,理论误差为156us左右 g_di_st[ecd->slot][ecd->index].tm_filter = (u32)tRunPara.wYXFD * 1000 / 156; ecd++; } return 0; } int equ_config_do_yd(void) { #if 0 int i,index; struct equ_config_do *ecd; // 用户配置的保持时间 ecd = g_equ_config_do; for(i=0;ido_num;i++) { u32 dotime=(u32)ecd->time_pulse; if(ecd->slot == EQU_SLOT_KZ) { // 如果定值参数中设置了分闸时间,覆盖 if(ecd->owner&&((ecd->type == (SW_DO_FZ+1))||(ecd->type == (SW_DO_BHT+1))||(ecd->type == (SW_DO_YKT+1)))) { if(pRunSet->bTT_RmtPara) { dotime=tRunPara.wFZMC; } } // 如果定值参数中设置了合闸时间,覆盖 if(ecd->owner&&((ecd->type == (SW_DO_HZ+1))||(ecd->type == (SW_DO_BHH+1))||(ecd->type == (SW_DO_YKH+1)))) { if(pRunSet->bTT_RmtPara) { dotime=tRunPara.wHZMC; } } index = equ_get_do_channel(ecd->index); g_do_st[index].us_keep = (u32)dotime; g_do_st[index].us_keep *= 1000; //ms转换为us } ecd++; } #endif return 0; } int equ_init_later(void) { u32 i; int ui,index; //TODO:need to check g_brd_type_kz how to work g_brd_type_kz = g_board_info[EQU_SLOT_KZ].type - BOARD_TYPE_DFTU_KC00; if(g_brd_type_kz >= BOARD_TYPE_KZ_NUM) { rt_printf("控制板类型错误(g_brd_type_kz=%lu).\r\n",g_brd_type_kz); g_brd_type_kz = 0; return -1; } //通道取反,重新初始化一下,在equ.c中初始化过,但由于g_brd_type_kz未初始化,取反是错误的 memset(g_equ_adc_inv,0,sizeof(g_equ_adc_inv)); g_equ_adc_inv_num=0; memset(g_equ_adc_config,0,sizeof(g_equ_adc_config)); //jack.liu20200917 g_equ_adc_config初始化 for(i=0; iac_num; i++) { u32 adc; adc = equ_get_ac_channel(g_equ_config_ac[i].slot,g_equ_config_ac[i].index); if (adcac_num; i++) { // 频率通道必须是配置了的公共电压类型 if(g_equ_config_ac[i].type == 0 || g_equ_config_ac[i].owner != 0) { continue; } ui = g_equ_config_ac[i].type -1; if(ui >= PUB_AC_NUM) { continue; } if(g_equ_config_ac[i].slot == EQU_SLOT_KZ && g_equ_config_ac[i].index == index) { g_ui_freq[0] = ui; } } // 获取频率所对应的UI通道 // 频率1采样对应ADC通道为12. for(index=0;indexac_num; i++) { // 频率通道必须是配置了的公共电压类型 if(g_equ_config_ac[i].type == 0 || g_equ_config_ac[i].owner != 0) { continue; } ui = g_equ_config_ac[i].type -1; if(ui >= PUB_AC_NUM) { continue; } if(g_equ_config_ac[i].slot == EQU_SLOT_KZ && g_equ_config_ac[i].index == index) { g_ui_freq[1] = ui; } } // 采样板起始槽位 g_ac_slot_begin = EQU_SLOT_AC_BEGIN; // 初始化开入开出 equ_config_do(); equ_config_di(); return 0; } /****************************************************************************** 函数名称: equ_board_info_update 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-08 函数说明: 接收到子板的对时应答帧后,更新子板信息 参数说明: can_bus 从哪条can总线接收到的帧。 frame 接收帧的buf指针 返回值: 0: 成功 其它: 失败 修改记录: */ int equ_board_info_update(int can_bus,u8 * frame) { struct can_frame_head *cfh; struct board_info_frame *bif; struct board_info *bi; // 检查帧内容 cfh = (struct can_frame_head *)frame; #ifdef CAN_SLAVE_BOARD if(cfh->src >= (EQU_SLOT_NUM_MAX+CAN_BOARD_NUM)) #else if(cfh->src >= EQU_SLOT_NUM_MAX) #endif { return -1; } if(cfh->len != 8) { return -2; } // 比较子板类型 bi = &g_board_info[cfh->src]; bif = (struct board_info_frame *)(frame + sizeof(cfh)); if(bif->type != bi->type) { // rt_printf("board type error(no=%d,bi_type=%d,gbi_type=%d)\r\n",cfh->src,bif->type,bi->type); // print_mem("frame",frame,16); return -3; } // 得到子板信息 bi->status = bif->status; bi->errcode = bif->errcode; bi->crc = bif->crc; bi->version = bif->version; //rt_printf("%02d\t%02d\t%02d\t%04x\t%08x\t",bi->type,bi->status,bi->errcode,bi->crc,bi->version); // 得到子板时间 clk_time_get(&bi->update_time); bi->us0 = ustimer_get_origin(); bi->is_ok = 1; bi->can_bus = can_bus; return 0; } /****************************************************************************** 函数名称: equ_ac_channel_is_ok 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-08 函数说明: 得到插槽中子板的模拟量通道对应的ADC采样通道。 参数说明: slot 插槽索引号 index 子板上模拟量通道索引号 返回值: ADC采样通道索引号 修改记录: */ int equ_ac_channel_is_ok(u32 index) { // 检查参数 if(index >= CFG_ADC_CHANNEL) { return 0; } // 板卡不能插拔,直接返回ok return 1; // return g_ac_slot_is_ok[index/EQU_SLOT_AC_CHN]; } /****************************************************************************** 函数名称: equ_get_ac_channel 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-08 函数说明: 得到插槽中子板的模拟量通道对应的ADC采样通道。 参数说明: slot 插槽索引号 index 子板上模拟量通道索引号 返回值: ADC采样通道索引号 修改记录: */ int equ_get_ac_channel(u32 slot,u32 index) { // 检查参数 if(slot != EQU_SLOT_KZ) { return -1; } if(index >= 16) { return -2; } return g_ac_index[g_brd_type_kz][index]; } /****************************************************************************** 函数名称: equ_get_ac_slot 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2014-10-09 函数说明: 得到采样通道对应的板卡 参数说明: owner 归属公共、开关 type 采样类型 返回值: ADC采样通道索引号 修改记录: */ int equ_get_ac_slot(u32 owner, u32 type) { u32 no; if (owner) { no = g_sw[owner].ac_cfg_index[type]; } else { no = g_sw_pub.ac_cfg_index[type]; } return g_equ_config_ac[no].slot; } /****************************************************************************** 函数名称: equ_ac_index_to_slot 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-08 函数说明: 将采样板索引号(和ADC通道号对应)转换为插槽号。 参数说明: ac_index 采样板索引号 返回值: 插槽号 修改记录: */ int equ_ac_index_to_slot(int ac_index) { if((u32)ac_index >= EQU_SLOT_AC_NUM) { return 0; } return g_ac_index_to_slot[ac_index]; } /****************************************************************************** 函数名称: equ_slot_config_do 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-08 函数说明: 配置子板上的开出资源 参数说明: slot 插槽索引号 返回值: 插槽号 0: 成功 其它: 失败 修改记录: */ int equ_get_do_channel(u32 index) { return g_do_index[g_brd_type_kz][index]; } /****************************************************************************** 函数名称: equ_slot_config_di 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2014-04-08 函数说明: 配置子板上的开入资源 参数说明: slot 插槽索引号 返回值: 插槽号 0: 成功 其它: 失败 修改记录: */ /*------------------------------ 内部函数 ------------------------------------- 内部函数以下划线‘_’开头,不需要检查参数的合法性. */ /*------------------------------ 测试函数 ------------------------------------- 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数). */ /*------------------------------ 文件结束 ------------------------------------- */