dido.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: dido.c
  4. 文件版本: 01.01
  5. 创建作者: sunxi
  6. 创建日期: 2013-02-28
  7. 功能说明: 开入开出
  8. 其它说明:
  9. // 启动继电器
  10. 1、启动继电器可以重复多次启动,每次启动都将重新计算超时时间。
  11. 2、启动继电器有2种关闭方式:
  12. 1) 超时自动关闭,超时时间为装置参数的遥控超时时间。
  13. 2) 通过函数调用关闭。
  14. 3、有保护启动标志时,选择继电器不允许关闭。
  15. 4、需提供启动继电器的超时设置函数.
  16. 5、只所以采用超时自动关闭,是因为以前的程序关闭方式存在问题,可能由于资源竞争的关系,
  17. 导致不该关闭时却关闭了,虽然概率很小,但理论上存在。
  18. 修改记录:
  19. */
  20. /*------------------------------- 头文件 --------------------------------------
  21. */
  22. #include "head.h"
  23. #include "gpio.h"
  24. #include "ad7616.h"
  25. /*------------------------------- 宏定义 --------------------------------------
  26. */
  27. #define DO_PWM_SW_HZ 0
  28. #define DO_PWM_SW_QD 1
  29. #define DO_PWM_SW_NULL 2
  30. #define DO_PWM_SW_FZ 3
  31. #define DO_QD_KC DO_OUT4
  32. /*------------------------------ 类型结构 -------------------------------------
  33. */
  34. /*------------------------------ 全局变量 -------------------------------------
  35. */
  36. struct di g_di[EQU_SLOT_NUM_MAX];
  37. struct _do g_do[EQU_SLOT_NUM_MAX];
  38. struct di_struct g_di_st[EQU_SLOT_NUM_MAX][DIDO_MAX_DI_PER_SLOT];
  39. struct do_struct g_do_st[DO_NUM];
  40. u16 g_do_status; // 开出状态,因为仅主板有开出
  41. u32 g_do_start_time;
  42. int g_do_flag;
  43. extern u32 g_brd_type_kz;
  44. struct rt_stat g_stat_di_delay;
  45. struct rt_stat g_stat_do_delay;
  46. static u32 di_error_count = 0;
  47. static u32 error_count = 0;
  48. struct do_time g_do_time[EQU_SLOT_NUM_MAX];
  49. /*------------------------------ 函数声明 -------------------------------------
  50. */
  51. static int _dido_do(u32 slot,u16 v,int is_on);
  52. static int _get_di(int slot,u16 di_num, u32 di, struct timespec ts);
  53. static inline void _io_do_status_update(int on, unsigned int i);
  54. unsigned int change_di_ch(unsigned int di);
  55. /*------------------------------ 外部函数 -------------------------------------
  56. 外部函数供其它实体文件引用,必须仔细检查传入参数的合法性.
  57. */
  58. /******************************************************************************
  59. 函数名称: dido_init
  60. 函数版本: 01.01
  61. 创建作者:
  62. 创建日期: 2013-03-13
  63. 函数说明: 开入开出初始化
  64. 参数说明: 无
  65. 返回值: 无
  66. 修改记录:
  67. */
  68. void dido_init_di(void)
  69. {
  70. //return ret;
  71. u32 i,slot;
  72. u32 di0,di,di_num;
  73. di0 = gpio_get_di();
  74. // 主板
  75. slot = EQU_SLOT_KZ;
  76. di = (di0 & 0x7FFFF);
  77. g_di[slot].value[0] = di^g_di[slot].inv[0];
  78. di_num = equ_get_di_num(slot);
  79. for(i=0; i<di_num; i++)
  80. {
  81. if(di&(1<<i))
  82. {
  83. g_di_st[slot][i].b_on = 1;
  84. }
  85. else
  86. {
  87. g_di_st[slot][i].b_on = 0;
  88. }
  89. if(g_di[slot].value[0]&(1<<i))
  90. {
  91. sw_di_set(g_di_st[slot][i].owner,g_di_st[slot][i].type,SW_DI_TYPE_ON);
  92. g_di[slot].ts_v[i][g_di[slot].ts_i[i].n] = 1;
  93. }
  94. g_di[slot].ts_t[i][g_di[slot].ts_i[i].n] = 0;
  95. g_di[slot].ts_i[i].n++;
  96. }
  97. }
  98. int dido_init(void)
  99. {
  100. u32 i;
  101. // 检查装置配置
  102. if(equ_config_null())
  103. {
  104. return -1;
  105. }
  106. // 初始化取反标志
  107. for(i=0; i< g_equ_config->di_num; i++)
  108. {
  109. if(g_equ_config_di[i].is_Inverse == 0)
  110. {
  111. continue;
  112. }
  113. if(g_equ_config_di[i].slot < EQU_SLOT_NUM_MAX && g_equ_config_di[i].index < DIDO_MAX_DI_PER_SLOT)
  114. {
  115. if(g_equ_config_di[i].index < 32)
  116. {
  117. g_di[g_equ_config_di[i].slot].inv[0] |= 1<<g_equ_config_di[i].index;
  118. }
  119. else
  120. {
  121. g_di[g_equ_config_di[i].slot].inv[1] |= 1<<(g_equ_config_di[i].index - 32);
  122. }
  123. }
  124. }
  125. dido_init_di();
  126. dido_stat_reset();
  127. return 0;
  128. }
  129. // 只有分合闸有选择启动继电器
  130. int dido_do_have_select(u32 slot,u32 index)
  131. {
  132. int i = 0;
  133. i = equ_get_do_channel(index);
  134. if(i==DO_OUT0||i==DO_OUT1||i==DO_OUT5||i==DO_OUT6)
  135. {
  136. return 1;
  137. }
  138. return 0;
  139. }
  140. /******************************************************************************
  141. 函数名称: dido_do
  142. 函数版本: 01.01
  143. 创建作者:
  144. 创建日期: 2013-03-13
  145. 函数说明: 板卡开出动作
  146. 参数说明: 无
  147. 返回值:
  148. 修改记录:
  149. */
  150. int dido_do(u32 slot,u16 v,int is_on)
  151. {
  152. //unsigned long flags;
  153. // 检查DO资源
  154. if(equ_get_do_num(slot) == 0)
  155. {
  156. return -2;
  157. }
  158. // 保存输出值,在5ms中断中输出
  159. rt_irq_save(flags);
  160. g_do_flag = 1;
  161. if(is_on)
  162. {
  163. g_do[slot].on |= v;
  164. }
  165. else
  166. {
  167. g_do[slot].off |= v;
  168. }
  169. rt_irq_restore(flags);
  170. return 0;
  171. }
  172. /******************************************************************************
  173. 函数名称: do_kout_check
  174. 函数版本:
  175. 创建作者:
  176. 创建日期: 2013-03-13
  177. 函数说明: 开出反校。
  178. 参数说明: 无
  179. 返回值: 结果
  180. 修改记录:
  181. */
  182. void io_do_check(void)
  183. {
  184. u16 now,fj;
  185. u32 us;
  186. #ifdef DO_KOUT_CHECK
  187. u8 index;
  188. // 取返校值,必须在下面时间点检查之
  189. index=g_equ_config_di[g_sw[0].di_cfg_index[SW_DI_KOCHK]].index;
  190. fj = gpio_di_fj(index)&0x01;//0x02;
  191. // 返回值只判断启动、分闸、合闸
  192. now = 0;
  193. if(g_do_status &(1<<DO_QD_KC))//预置反校DO_PWM_SW_QD
  194. {
  195. now |= 0x01;
  196. }
  197. //if(g_do_status &((1<<DO_PWM_SW_FZ)|(1<<DO_PWM_SW_HZ)))//动作反校
  198. //{
  199. //now |= 0x01;//0x02;
  200. //}
  201. #else
  202. // 取返校值,必须在下面时间点检查之
  203. fj = gpio_di_fj()&0x02;
  204. // 返回值只判断启动、分闸、合闸
  205. now = 0;
  206. if(g_do_status &(1<<DO_PWM_SW_QD))
  207. {
  208. //now |= 0x01;
  209. }
  210. if(g_do_status &((1<<DO_PWM_SW_FZ)|(1<<DO_PWM_SW_HZ)))
  211. {
  212. now |= 0x02;
  213. }
  214. #endif
  215. //开出动作20ms内不进行开出自检,
  216. //经实测启动继电器因为是继电器触点返校,其返回时间最长,但也小于10ms。
  217. //分合闸继电器是光耦返校,本身需要的时间可以忽略不计,但受启动继电器的影响
  218. us = ustimer_get_duration(g_do_start_time);
  219. if(us < 20*1000)
  220. {
  221. return ;
  222. }
  223. if (fj != now)
  224. {
  225. // rt_printf("返校失败:fj=%04x,now=%04x, g_do_status=%04x(us=%d)\r\n",fj,now, g_do_status,us);
  226. rt_err_set(ERR_CODE_DO_CHECK,0);
  227. return ;
  228. }
  229. }
  230. /******************************************************************************
  231. 函数名称: io_do_return
  232. 函数版本: 01.01
  233. 创建作者:
  234. 创建日期: 2013-03-13
  235. 函数说明: 开出保持时间
  236. 参数说明: 无
  237. 返回值: 无
  238. 修改记录:
  239. */
  240. void io_do_return(void)
  241. {
  242. int i;
  243. u32 dly;
  244. for(i=0; i<DO_NUM; i++) //开出保持
  245. {
  246. if(g_do_status & (1<<i)) //正在开出
  247. {
  248. dly = ustimer_get_duration(g_do_st[i].us_on);
  249. // +2500是为了提高脉宽精度,因为此函数是在5ms(5000)中断中调用的.
  250. // 如果us_keep为0,表示此开出没有自动返回的需求,应忽略。
  251. if (((dly + 2500) > g_do_st[i].us_keep) && (g_do_st[i].us_keep>0))
  252. {
  253. dido_do_kz(0,i);
  254. }
  255. }
  256. }
  257. }
  258. /******************************************************************************
  259. 函数名称: dido_do_poll
  260. 函数版本: 01.01
  261. 创建作者:
  262. 创建日期: 2013-03-13
  263. 函数说明: 是否开出巡检
  264. 参数说明: 无
  265. 返回值: 无
  266. 修改记录:
  267. */
  268. void dido_do_poll(void)
  269. {
  270. #if 1
  271. int i;
  272. // 真正开出
  273. if(g_do_flag)
  274. {
  275. g_do_flag = 0;
  276. for(i=0; i<EQU_SLOT_NUM_MAX; i++)
  277. {
  278. if(g_do[i].on)
  279. {
  280. _dido_do(i,g_do[i].on,1);
  281. g_do[i].on = 0;
  282. }
  283. if(g_do[i].off)
  284. {
  285. _dido_do(i,g_do[i].off,0);
  286. g_do[i].off = 0;
  287. }
  288. }
  289. }
  290. // 开出返回
  291. io_do_return();
  292. // 开出返校
  293. if(g_board_info[EQU_SLOT_KZ].do_num != 0)
  294. {
  295. #ifdef DO_KOUT_CHECK
  296. if((short)g_sw[0].di_cfg_index[SW_DI_KOCHK] != INDEX_INVALLID)
  297. {
  298. io_do_check();
  299. }
  300. #else
  301. //io_do_check();
  302. #endif
  303. }
  304. return;
  305. #endif
  306. }
  307. /******************************************************************************
  308. 函数名称: dido_qd_set_keeptime
  309. 函数版本: 01.01
  310. 创建作者: sunxi
  311. 创建日期: 2013-06-10
  312. 函数说明: 设置启动继电器的保持时间
  313. 参数说明: 无
  314. 返回值: 无
  315. 修改记录:
  316. */
  317. void dido_qd_set_keeptime(u32 us)
  318. {
  319. g_do_st[DO_QD_KC].us_keep = us;
  320. }
  321. /******************************************************************************
  322. 函数名称: get_di
  323. 函数版本: 01.01
  324. 创建作者:
  325. 创建日期: 2013-03-13
  326. 函数说明: 开入防抖处理
  327. 参数说明: 无
  328. 返回值: 无
  329. 修改记录:
  330. */
  331. //unsigned int di_val;
  332. void dido_di_poll(SHM_SAMPLE_T *sample_data)
  333. {
  334. u32 di,di_num,slot;
  335. u64 us0;
  336. // 如果交流延时失电信号有,闭锁遥信
  337. if(pRunSet->dSDYX_T && g_run_stu.dcjlsd_t)
  338. {
  339. return;
  340. }
  341. us0 = ustimer_get_origin();
  342. // 主板,19个遥信
  343. slot = EQU_SLOT_KZ;
  344. di_num = equ_get_di_num(slot);
  345. // di = gpio_get_di();
  346. di = change_di_ch(~sample_data->yx_buf[0]);
  347. rt_printf("gpio_get_di:yx_buf[0]=%x di=%x\r\n",sample_data->yx_buf[0],di);
  348. _get_di(slot, di_num, di, sample_data->ts);
  349. rt_stat_other_in(6,ustimer_get_duration(us0));
  350. }
  351. /******************************************************************************
  352. 函数名称: dido_di_is_on
  353. 函数版本: 01.01
  354. 创建作者:
  355. 创建日期: 2013-03-13
  356. 函数说明: 开入状态
  357. 参数说明: 无
  358. 返回值: 1:有开入,0:无开入
  359. 修改记录:
  360. */
  361. int dido_di_is_on(u8 slot,u8 index)
  362. {
  363. if(slot >= EQU_SLOT_NUM_MAX || index >= 64)
  364. {
  365. return 0;
  366. }
  367. if(index < 32)
  368. {
  369. if(g_di[slot].value[0]&(1<<index))
  370. {
  371. return 1;
  372. }
  373. }
  374. else
  375. {
  376. index -= 32;
  377. if(g_di[slot].value[1]&(1<<index))
  378. {
  379. return 1;
  380. }
  381. }
  382. return 0;
  383. }
  384. // 查看某个时间点下的开入值
  385. int dido_di_is_on_ts(u8 slot,u8 index,u32 ts)
  386. {
  387. int i,r;
  388. struct ts_index ts_i;
  389. if(slot >= EQU_SLOT_NUM_MAX || index >= 32)
  390. {
  391. return 0;
  392. }
  393. #if 0
  394. {
  395. static int cnt = 0;
  396. if(cnt++ < 16)
  397. rt_printf("slot=%d,index=%d,ts=%d.\r\n",slot,index,ts);
  398. }
  399. #endif
  400. ts_i.n = g_di[slot].ts_i[index].n - 1; //ts_i下是无值的,所以应该减1
  401. for(i=0;i<DIDO_TS_NUM;i++)
  402. {
  403. r = (int)(ts - g_di[slot].ts_t[index][ts_i.n]);
  404. if(r >= 0)
  405. {
  406. return g_di[slot].ts_v[index][ts_i.n];
  407. }
  408. ts_i.n--;
  409. }
  410. if(g_di[slot].value[0]&(1<<index))
  411. {
  412. return 1;
  413. }
  414. return 0;
  415. }
  416. int dido_do_kz(int on, unsigned int i)
  417. {
  418. if(on) // 开出,需启动启动继电器打开电源
  419. {
  420. if(i==DO_OUT0||i==DO_OUT1||i==DO_OUT5||i==DO_OUT6)
  421. {
  422. gpio_kout_do(on, DO_QD_KC-DO_OUT0); // 对应X4端子的DO0~DO7
  423. _io_do_status_update(1,DO_QD_KC);
  424. }
  425. }
  426. // if(i<=DO_PWM3)
  427. // {
  428. // gpio_pwm_do(on, i); // 对应X3端子的OUT3,分闸
  429. // _io_do_status_update(on,i);
  430. // }
  431. // else
  432. if(i==DO_QD_KC) //启动继电器出口
  433. {
  434. if(!on)
  435. {
  436. if(g_tRelay[0].zqd) // 如果保护启动,禁止关闭启动继电器
  437. {
  438. return -2;
  439. }
  440. if(g_do_status&(~(1<<DO_QD_KC))) //有其他开出,不收启动继电器
  441. {
  442. return -3;
  443. }
  444. }
  445. gpio_kout_do(on, i-DO_OUT0); // 对应X4端子的DO0~DO7
  446. _io_do_status_update(on,i);
  447. }
  448. else if ((i >= DO_OUT0) && (i <= DO_OUT7))
  449. {
  450. gpio_kout_do(on, i-DO_OUT0); // 对应X4端子的DO0~DO7
  451. _io_do_status_update(on,i);
  452. }
  453. else
  454. {
  455. rt_printf("dido_do_kz err(on=%d,i=%d).\r\n",on,i);
  456. }
  457. return 0;
  458. }
  459. /*------------------------------ 内部函数 -------------------------------------
  460. 内部函数以下划线‘_’开头,不需要检查参数的合法性.
  461. */
  462. static inline void _io_do_status_update(int on, unsigned int i)
  463. {
  464. if(on)
  465. {
  466. g_do_status |= (1<<i);
  467. g_do_st[i].us_on= ustimer_get_origin();
  468. }
  469. else
  470. {
  471. g_do_status &= ~(1<<i);
  472. }
  473. // 更新返校检查时间
  474. g_do_start_time = ustimer_get_origin();
  475. }
  476. static int _dido_do(u32 slot,u16 v,int is_on)
  477. {
  478. int i;
  479. // 循环检查开出位
  480. for(i=0; i<g_board_info[slot].do_num; i++)
  481. {
  482. // 如果对应开出位有效,开出。
  483. if(((v>>i) & 0x1))
  484. {
  485. dido_do_kz(is_on,equ_get_do_channel(i));
  486. }
  487. }
  488. if(((v>>g_board_info[slot].do_num) & 0x1)) // 启动继电器
  489. {
  490. dido_do_kz(is_on,DO_QD_KC);
  491. }
  492. return 0;
  493. }
  494. /******************************************************************************
  495. 函数名称: _get_di
  496. 函数版本: 01.01
  497. 创建作者:
  498. 创建日期: 2013-03-13
  499. 函数说明: 开入防抖处理
  500. 参数说明: 无
  501. 返回值:
  502. 修改记录:
  503. */
  504. #ifdef CN_AREA_GUANGXI//遥信全部为0
  505. u32 kktime_0=0;
  506. #endif
  507. static int _get_di(int slot,u16 di_num, u32 di, struct timespec ts)
  508. {
  509. int i,b_on;
  510. struct rtc_time_t ct;
  511. uint32 diff_nsec;
  512. // struct timespec ts;
  513. #if 0//#ifdef CN_AREA_GUANGXI//遥信全部为0,则关闭屏幕或者关机
  514. if(di==0)
  515. {
  516. kktime_0++;
  517. if(kktime_0 > 10)
  518. {
  519. #if 1
  520. g_run_stu.yxError=true; //遥信错误,关闭屏幕
  521. #else
  522. char *argv[] = {"poweroff", NULL};
  523. char *envp[] = { NULL };
  524. call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);//关机
  525. #endif
  526. return 0;
  527. }
  528. }
  529. else
  530. {
  531. g_run_stu.yxError=0;
  532. kktime_0=0;
  533. }
  534. #endif
  535. // 获取遥信值,并记录时间戳。
  536. // 用秒的低8位和纳秒的高24位合成32位时间戳
  537. // clk_time_get(&ts);
  538. // 循环处理每一个遥信
  539. for(i=0; i<di_num; i++)
  540. {
  541. struct di_struct *pt=&g_di_st[slot][i];
  542. // 处理当前变位遥信。
  543. b_on = (di&(1<<i))? 1:0;
  544. if(b_on^pt->b_on)
  545. {
  546. if(!pt->b_first_change)
  547. {
  548. pt->b_first_change=true;
  549. pt->tm_back=0;
  550. pt->tm_keep=0;
  551. // 记录变位的起始时刻点
  552. pt->ts_di = ts;
  553. pt->dt=g_adc_dots_data_count;
  554. #ifdef DIDO_TS_MODE
  555. pt->ts_tmp = ts;
  556. #endif
  557. }
  558. else
  559. {
  560. // 累计保持时间
  561. #ifdef DIDO_TS_MODE
  562. if(ts.tv_nsec >= pt->ts_tmp.tv_nsec)
  563. {
  564. diff_nsec = ts.tv_nsec - pt->ts_tmp.tv_nsec;
  565. }
  566. else
  567. {
  568. diff_nsec = 1000000000ul - pt->ts_tmp.tv_nsec + ts.tv_nsec;
  569. }
  570. if(diff_nsec > 312500ul)
  571. {
  572. diff_nsec = 156250ul;
  573. }
  574. pt->acc_nsec += diff_nsec;
  575. while(pt->acc_nsec >= 156250ul)
  576. {
  577. pt->tm_keep++;
  578. pt->acc_nsec -= 156250ul;
  579. }
  580. pt->ts_tmp = ts;
  581. // rt_printf("diff_nsec:%d, pt->tm_keep:%d\r\n", diff_nsec, pt->tm_keep);
  582. #else
  583. pt->tm_keep++;
  584. #endif
  585. pt->tm_back=0; // 现在返回门限是0.5us,所有必须在此清零。
  586. // 保持时间到,处理变位
  587. if(pt->tm_keep > pt->tm_filter)
  588. {
  589. // 记录遥信状态
  590. #if defined CN_AREA_GUANGXI || defined YX_DI_ERROR //广西遥信异常后,遥信屏蔽不保存,不上报
  591. if( g_run_stu.yxEnable==0 && b_on==0)
  592. {
  593. pt->type = SOE_TYPE_TST;
  594. pt->b_first_change=false;
  595. pt->tm_back=0;
  596. pt->tm_keep=0;
  597. return 0;
  598. }
  599. #endif
  600. pt->b_on = b_on;
  601. if(g_di[slot].inv[0] & (1<<i))
  602. {
  603. b_on = !b_on;
  604. }
  605. if(b_on)
  606. {
  607. g_di[slot].value[0] |= (1<<i);
  608. }
  609. else
  610. {
  611. g_di[slot].value[0] &= ~(1<<i);
  612. }
  613. // 记录SOE
  614. soe_record_yx((WORD)(i+(slot<<8)),b_on,&pt->ts_di);
  615. timespec_to_rtc(ts, &ct, 1);
  616. rt_printf("di=%x value[0]=%x\r\n",di,g_di[slot].value[0]);
  617. // 更新逻辑模型中的值
  618. sw_di_set(g_di_st[slot][i].owner,g_di_st[slot][i].type,b_on ? SW_DI_TYPE_ON : SW_DI_TYPE_OFF);
  619. // 更新记录
  620. g_di[slot].ts_t[i][g_di[slot].ts_i[i].n] = pt->dt;
  621. g_di[slot].ts_v[i][g_di[slot].ts_i[i].n] = b_on;
  622. g_di[slot].ts_i[i].n++;
  623. //滤波处理数据复位
  624. pt->b_first_change=false;
  625. pt->tm_back=0;
  626. pt->tm_keep=0;
  627. }
  628. }
  629. }
  630. else if(pt->b_first_change)
  631. {
  632. // 变位返回处理
  633. pt->tm_back++;
  634. // 屏蔽下一行,
  635. // 最新逻辑,有效电平不连续可计数累加;
  636. // 无效电平连续超0.5ms复归,且不连续累加。
  637. //pt->tm_keep=0;
  638. // if(pt->tm_back > pt->tm_filter)
  639. if(pt->tm_back>4) // 针对高频振荡波测试优化,返回门限设置为500us附件(4*156=624us)。
  640. {
  641. pt->tm_back = 0;
  642. pt->tm_keep=0;
  643. pt->b_first_change = false;
  644. }
  645. }
  646. }
  647. return 0;
  648. }
  649. /*------------------------------ 测试函数 -------------------------------------
  650. 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中
  651. 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数).
  652. */
  653. // SOE信号发生器控制全局变量
  654. extern int g_soe_gen_state; // 状态,0停止,1初始化,2运行
  655. extern int g_soe_gen_on_us; // 导通时间
  656. extern int g_soe_gen_off_us; // 断开时间
  657. extern int g_soe_gen_seq_us; // 通道序列间隔时间
  658. #define SOE_GEN_NUM 8
  659. u32 g_soe_gen_count;
  660. u32 g_soe_gen_us0[SOE_GEN_NUM];
  661. u8 g_soe_gen_on[SOE_GEN_NUM];
  662. void dido_soe_gen(void)
  663. {
  664. int i;
  665. if(g_soe_gen_state == 0)
  666. {
  667. return;
  668. }
  669. else if(g_soe_gen_state == 1)
  670. {
  671. pit_156us_period_set(78.125);
  672. g_soe_gen_count = 0;
  673. for(i=0; i<SOE_GEN_NUM; i++)
  674. {
  675. g_soe_gen_us0[i] = g_soe_gen_seq_us*(i);
  676. g_soe_gen_on[i] = 0;
  677. g_soe_gen_state = 2;
  678. }
  679. }
  680. else if(dido_di_is_on(1,0))
  681. {
  682. for(i=0; i<SOE_GEN_NUM; i++)
  683. {
  684. if(g_soe_gen_on[i] == 0)
  685. {
  686. if((int)(g_soe_gen_count - g_soe_gen_us0[i]) >= g_soe_gen_off_us)
  687. {
  688. g_soe_gen_on[i] = 1;
  689. gpio_kout_do(1,i);
  690. g_soe_gen_us0[i] = g_soe_gen_count;
  691. }
  692. }
  693. else
  694. {
  695. if((int)(g_soe_gen_count - g_soe_gen_us0[i]) >= g_soe_gen_on_us)
  696. {
  697. g_soe_gen_on[i] = 0;
  698. gpio_kout_do(0,i);
  699. g_soe_gen_us0[i] = g_soe_gen_count;
  700. }
  701. }
  702. }
  703. }
  704. else
  705. {
  706. g_soe_gen_count = 0;
  707. for(i=0; i<SOE_GEN_NUM; i++)
  708. {
  709. g_soe_gen_us0[i] = g_soe_gen_seq_us*(i);
  710. g_soe_gen_on[i] = 0;
  711. g_soe_gen_state = 2;
  712. }
  713. }
  714. g_soe_gen_count++;
  715. }
  716. int dido_printf(void)
  717. {
  718. int i,slot,index;
  719. struct ts_index ts_i;
  720. rt_printf("槽号\t值\r\n");
  721. for(i=0; i<EQU_SLOT_NUM_MAX; i++) // xj 2015-5-4
  722. {
  723. rt_printf("%02d:\tvalue=0x%08lx_%08lx,inv=0x%08lx_%08lx\r\n",i,g_di[i].value[1],g_di[i].value[0],g_di[i].inv[1],g_di[i].inv[0]);
  724. }
  725. rt_printf("\r\n");
  726. slot = EQU_SLOT_MAIN;
  727. index = 1;
  728. ts_i.n = g_di[slot].ts_i[index].n;
  729. rt_printf("开入时间戳记录:slot=%d,index=%d,ts_i=%d.\r\n",slot,index,ts_i.n);
  730. rt_printf("序号\t值\t时间戳\r\n");
  731. ts_i.n = 0;
  732. for(i=0;i<DIDO_TS_NUM;i++)
  733. {
  734. rt_printf("%02d\t%d\t%08lu\r\n",ts_i.n,g_di[slot].ts_v[index][ts_i.n],g_di[slot].ts_t[index][ts_i.n]);
  735. ts_i.n++;
  736. }
  737. rt_printf("开出状态:0x%04x\r\n\r\n",g_do_status);
  738. rt_stat_printf(&g_stat_di_delay);
  739. rt_stat_printf(&g_stat_do_delay);
  740. return 0;
  741. }
  742. int dido_stat_reset(void)
  743. {
  744. rt_stat_init(&g_stat_di_delay,"di_delay");
  745. rt_stat_init(&g_stat_do_delay,"do_delay");
  746. return 0 ;
  747. }
  748. int dido_single_test(u8 slot, u8 point)
  749. {
  750. dido_do(slot,(1<<point),1);
  751. ustimer_delay(250*USTIMER_MS);
  752. dido_do(slot,(1<<point),0);
  753. return 0;
  754. }
  755. int dido_test(void)
  756. {
  757. static unsigned long us0 = 0;
  758. static char dido_test_pair[3][2] =
  759. {
  760. {1,3},
  761. {2,4},
  762. {5,5},
  763. };
  764. static char dido_test_di[32] =
  765. {
  766. 0,1,2,3,
  767. 0,1,2,3,
  768. 4,5,6,7,
  769. 4,5,6,7,
  770. 8,9,10,11,
  771. 8,9,10,11,
  772. 12,13,10,11,
  773. 12,13,12,13
  774. };
  775. int i,j,k,err_once,di_num;
  776. u32 slot_di,slot_do;
  777. if(g_test_on == 0)
  778. {
  779. return 0;
  780. }
  781. // 5秒处理一次
  782. if(ustimer_delay_origin2(&us0,10*USTIMER_SEC) != 1)
  783. {
  784. return 0;
  785. }
  786. rt_printf("dido_test begin...\r\n");
  787. ustimer_delay(1*USTIMER_SEC);
  788. #if 1
  789. // 测试开出板、开入板
  790. // 开出板逐一开出
  791. rt_printf("dido_test single.\r\n");
  792. err_once = 0;
  793. for(i=0; i<3; i++)
  794. {
  795. slot_do = dido_test_pair[i][0];
  796. slot_di = dido_test_pair[i][1];
  797. for(j=0;j<equ_get_do_num(slot_do); j++)
  798. {
  799. dido_do(slot_do,(1<<j),1);
  800. ustimer_delay(250*USTIMER_MS);
  801. di_num = equ_get_di_num(slot_di);
  802. if(slot_di == equ_get_slot_by_type(BOARD_TYPE_AUX))
  803. {
  804. di_num -= 1;
  805. }
  806. for(k=0;k<di_num; k++)
  807. {
  808. // 是否对应的开出点
  809. if(dido_test_di[k] == j)
  810. {
  811. if((g_di[slot_di].value[0] & (1<<k)) == 0)
  812. {
  813. err_once++;
  814. error_count++;
  815. rt_printf("dido_test on err(err=%d):i=%d,j=%d,k=%d,di=0x%08lx.\r\n",err_once,i,j,k,g_di[slot_di].value[0]);
  816. }
  817. }
  818. else
  819. {
  820. if((g_di[slot_di].value[0] & (1<<k)) != 0)
  821. {
  822. err_once++;
  823. error_count++;
  824. rt_printf("dido_test off err(err=%d):i=%d,j=%d,k=%d,di=0x%08lx.\r\n",err_once,i,j,k,g_di[slot_di].value[0]);
  825. }
  826. }
  827. }
  828. dido_do(slot_do,(1<<j),0);
  829. ustimer_delay(20*USTIMER_MS);
  830. watchdog_feed_mainloop();
  831. }
  832. }
  833. #endif
  834. rt_printf("\r\n开入变位时间超出次数:%lu\r\n",di_error_count);
  835. rt_printf("name\t\t\tmin\tmax\tavg\tsum\t\tcnt\n");
  836. rt_stat_printf(&g_stat_di_delay);
  837. rt_printf("\r\n");
  838. for(i=0;i<EQU_SLOT_NUM_MAX;i++)
  839. {
  840. if(g_do_time[i].slot != 0)
  841. {
  842. rt_printf("do_time[%d]:diff_max=%lu,diff_out_count=%lu\r\n",
  843. g_do_time[i].slot,g_do_time[i].diff_max,g_do_time[i].diff_out_count);
  844. }
  845. }
  846. rt_printf("\r\n");
  847. rt_printf("dido_test end:err_once=%d,error_count=%lu!\r\n\r\n\r\n",err_once,error_count);
  848. return 0;
  849. }
  850. bool check_board_di_valid(u8 slot,u8 index)
  851. {
  852. u32 i;
  853. // 初始化取反标志
  854. index-=1;
  855. for(i=0; i< g_equ_config->di_num; i++)
  856. {
  857. if((g_equ_config_di[i].slot==1)&&(g_equ_config_di[i].index==index))
  858. {
  859. if(g_equ_config_di[i].type==0)return true;
  860. }
  861. }
  862. return false;
  863. }
  864. bool check_board_kc6_close(u8 slot,u8 index)
  865. {
  866. u32 i;
  867. // 初始化取反标志
  868. index-=1;
  869. for(i=0; i< g_equ_config->do_num; i++)
  870. {
  871. if((g_equ_config_do[i].slot==slot)&&(g_equ_config_do[i].index==index))
  872. {
  873. if(g_equ_config_do[i].type!=0)return true;
  874. }
  875. }
  876. return false;
  877. }
  878. #define DIGROUP 4
  879. #define V3_OUT_NUM 5
  880. int dido_auto_test_for_v3(char *buf,int num)
  881. {
  882. // 12个开入,用5个开出进行测试
  883. static char test_di[6][DIGROUP] =
  884. {
  885. {1, 6, 11,0},
  886. {2, 7, 12,0},
  887. {3, 8, 13,0},
  888. {4, 9, 14,0},
  889. {16, 0, 0,0},
  890. {5, 10, 15,0},
  891. };
  892. int i,j,k,err_once,flag,flag1,di_num, do_num;
  893. u32 slot_di,slot_do, di_result;
  894. u8 tmp[5],tmp_data[5];
  895. u8 di_ok[4] = {0};
  896. u8 do_errflag = 0;
  897. char dido_test_pair[num][2];
  898. unsigned long us_begin = 0;
  899. bool bkc6close=false;
  900. slot_do=0;
  901. bkc6close=check_board_kc6_close(1,6);
  902. dido_stat_reset();
  903. if(bkc6close)
  904. {
  905. dido_do(slot_do,(1<<5),1); // 开出6若焊接为常闭输出,先开出,打开节点
  906. ustimer_delay(100*USTIMER_MS);
  907. }
  908. // 取出板卡槽位
  909. for(i=0;i<(num*2);)
  910. {
  911. for(j=0;j<2;j++)
  912. {
  913. dido_test_pair[i/2][j] = buf[i];
  914. i++;
  915. }
  916. }
  917. flag = 0;
  918. flag1 = 0;
  919. memset(tmp,0,sizeof(tmp));
  920. memset(tmp_data,0,sizeof(tmp_data));
  921. memset(dido_buf,0,sizeof(dido_buf));
  922. rt_printf("dido_test begin...\r\n");
  923. err_once = 0;
  924. // 以组为循环
  925. for(i=0; i<num; i++)
  926. {
  927. slot_do = dido_test_pair[i][0];
  928. slot_di = dido_test_pair[i][1];
  929. // 槽位暂存
  930. dido_buf[i+i*13] = slot_do;
  931. dido_buf[i+i*13+5] = slot_di;
  932. // 取出对应槽位的板卡中DI和DO的数量
  933. di_num = equ_get_di_num(slot_di);
  934. do_num = equ_get_do_num(slot_do);
  935. //dido_do(slot_do,(1<<5),1); //磁保持继电器
  936. // 启动记时
  937. us_begin = ustimer_get_origin();
  938. // 逐一输出开出点
  939. for(j=0; j<V3_OUT_NUM; j++)
  940. {
  941. dido_do(slot_do,(1<<j),1);
  942. if(j==5&&bkc6close)
  943. {
  944. dido_do(slot_do,(1<<5),0); // 开出6若焊接为常闭输出,反操作为闭合
  945. }
  946. ustimer_delay(150*USTIMER_MS);
  947. memset(di_ok,0,sizeof(di_ok));
  948. do_errflag = DIGROUP;
  949. for (k=0; k<4; k++)
  950. {
  951. bool bIgnore=false;
  952. di_result = (g_di[slot_di].value[0] ^ g_di[slot_di].inv[0]);
  953. k+=i*2;
  954. if(test_di[j][k]==17)
  955. {
  956. bIgnore=check_board_di_valid(slot_di,17);
  957. }
  958. if(test_di[j][k]==18)
  959. {
  960. bIgnore=check_board_di_valid(slot_di,18);
  961. }
  962. if (!test_di[j][k]||bIgnore)
  963. {
  964. do_errflag--;
  965. }
  966. else
  967. {
  968. if (!(di_result & (1<<(test_di[j][k]-1)))) //对应开入无值
  969. {
  970. do_errflag--;
  971. di_ok[k] = test_di[j][k];
  972. }
  973. }
  974. }
  975. if (!do_errflag) //开出对应的所有开入都没有值,即代表该开出有问题
  976. {
  977. if (j<8)
  978. {
  979. dido_buf[i+i*13+1] |= (1<<j); //开出错误标志
  980. }
  981. else if (j<16)
  982. {
  983. dido_buf[i+i*13+2] |= (1<<(j-8)); //开出错误标志
  984. }
  985. rt_printf("dido_test do err:i=%d,j=%d,di=%d,di_l=0x%04lx,di_h=0x%04lx.\r\n",
  986. i,j,di_ok[0], g_di[slot_di].value[0],g_di[slot_di].value[1]);
  987. }
  988. else
  989. {
  990. for (k=0; k<4; k++)
  991. {
  992. if (!di_ok[k])
  993. continue;
  994. if ((di_ok[k]-1) < 8)
  995. {
  996. dido_buf[i+i*13+6] |= (1<<(di_ok[k]-1));
  997. }
  998. else if ((di_ok[k]-1) < 16)
  999. {
  1000. dido_buf[i+i*13+7] |= (1<<(di_ok[k]-1-8));
  1001. }
  1002. else if ((di_ok[k]-1) < 24)
  1003. {
  1004. dido_buf[i+i*13+8] |= (1<<(di_ok[k]-1-16));
  1005. }
  1006. else if ((di_ok[k]-1) < 32)
  1007. {
  1008. dido_buf[i+i*13+9] |= (1<<(di_ok[k]-1-24));
  1009. }
  1010. else if ((di_ok[k]-1) < 40)
  1011. {
  1012. dido_buf[i+i*13+10] |= (1<<(di_ok[k]-1-32));
  1013. }
  1014. else if ((di_ok[k]-1) < 48)
  1015. {
  1016. dido_buf[i+i*13+11] |= (1<<(di_ok[k]-1-40));
  1017. }
  1018. else if ((di_ok[k]-1) < 56)
  1019. {
  1020. dido_buf[i+i*13+12] |= (1<<(di_ok[k]-1-48));
  1021. }
  1022. else if ((di_ok[k]-1) < 64)
  1023. {
  1024. dido_buf[i+i*13+13] |= (1<<(di_ok[k]-1-56));
  1025. }
  1026. rt_printf("dido_test di err:i=%d,j=%d,di=%d,di_l=0x%04lx,di_h=0x%04lx.\r\n",
  1027. i,j,di_ok[k], g_di[slot_di].value[0],g_di[slot_di].value[1]);
  1028. }
  1029. }
  1030. dido_do(slot_do,(1<<j),0);
  1031. if(j==5&&bkc6close)
  1032. {
  1033. dido_do(slot_do,(1<<5),1); // 开出6若焊接为常闭输出,反操作为闭合
  1034. }
  1035. //if(j==4)
  1036. //{
  1037. //dido_do(slot_do,(1<<5),1); //磁保持继电器
  1038. //}
  1039. ustimer_delay(20*USTIMER_MS);
  1040. watchdog_feed_mainloop();
  1041. }
  1042. }
  1043. for(i=0;i<EQU_SLOT_NUM_MAX;i++)
  1044. {
  1045. if(g_do_time[i].slot != 0)
  1046. {
  1047. rt_printf("do_time[%d]:diff_max=%lu,diff_out_count=%lu\r\n",
  1048. g_do_time[i].slot,g_do_time[i].diff_max,g_do_time[i].diff_out_count);
  1049. }
  1050. }
  1051. rt_printf("dido_test end:err_once=%d,error_count=%lu!\r\n\r\n\r\n",err_once,error_count);
  1052. return 0;
  1053. }
  1054. int dido_auto_test(char *buf,int num)
  1055. {
  1056. #define KC_COUNT 11
  1057. // 12个开入,用5个开出进行测试
  1058. #if 0
  1059. static char test_di[6][DIGROUP] =
  1060. {
  1061. {1, 6, 11,0},
  1062. {2, 7, 12,0},
  1063. {3, 8, 13,0},
  1064. {4, 9, 14,0},
  1065. {16, 0, 0,0},
  1066. {5, 10, 15,0},
  1067. };
  1068. #endif
  1069. static char test_di[KC_COUNT][DIGROUP] =
  1070. {
  1071. {1, 12, 23,0},
  1072. {2, 13, 24,0},
  1073. {3, 14, 0,0},
  1074. {4, 15, 0,0},
  1075. {5, 16, 0,0},
  1076. {6, 17, 0,0},
  1077. {7, 18, 0,0},
  1078. {8, 19, 0,0},
  1079. {9, 20, 0,0},
  1080. {10,21, 0,0},
  1081. {11,22, 0,0},
  1082. // { 0, 0, 0,0}
  1083. };
  1084. u8 brd_v3[] = {22, 23};
  1085. int i,j,k,err_once,flag,flag1,di_num, do_num;
  1086. u32 slot_di,slot_do, di_result;
  1087. u8 tmp[5],tmp_data[5];
  1088. u8 di_ok[4] = {0};
  1089. u8 do_errflag = 0;
  1090. char dido_test_pair[num][2];
  1091. unsigned long us_begin = 0;
  1092. bool bkc6close=false;
  1093. rt_printf("g_brd_type_kz = %lu\r\n ", g_brd_type_kz);
  1094. rt_printf("g_equ_config->do_num = %lu\r\n ", g_equ_config->do_num);
  1095. for(i=0; i<(int)sizeof(brd_v3); i++)
  1096. {
  1097. if(g_brd_type_kz+BOARD_TYPE_DFTU_KC00==brd_v3[i])//
  1098. {
  1099. rt_printf("auto_test_for_v3\r\n ");
  1100. return (dido_auto_test_for_v3(buf, num));
  1101. }
  1102. }
  1103. rt_printf("auto_test_for_v4\r\n ");
  1104. //bkc6close=check_board_kc6_close(1,6);
  1105. dido_stat_reset();
  1106. if(bkc6close)
  1107. {
  1108. dido_do(1,(1<<5),1); // 开出6若焊接为常闭输出,先开出,打开节点
  1109. ustimer_delay(100*USTIMER_MS);
  1110. }
  1111. // 取出板卡槽位
  1112. for(i=0;i<(num*2);)
  1113. {
  1114. for(j=0;j<2;j++)
  1115. {
  1116. dido_test_pair[i/2][j] = buf[i];
  1117. i++;
  1118. }
  1119. }
  1120. flag = 0;
  1121. flag1 = 0;
  1122. memset(tmp,0,sizeof(tmp));
  1123. memset(tmp_data,0,sizeof(tmp_data));
  1124. memset(dido_buf,0,sizeof(dido_buf));
  1125. rt_printf("dido_test begin...\r\n");
  1126. err_once = 0;
  1127. // 以组为循环
  1128. for(i=0; i<num; i++)
  1129. {
  1130. slot_do = dido_test_pair[i][0];
  1131. slot_di = dido_test_pair[i][1];
  1132. // 槽位暂存
  1133. dido_buf[i+i*13] = slot_do;
  1134. dido_buf[i+i*13+5] = slot_di;
  1135. // 取出对应槽位的板卡中DI和DO的数量
  1136. di_num = equ_get_di_num(slot_di);
  1137. do_num = equ_get_do_num(slot_do);
  1138. //dido_do(slot_do,(1<<5),1); //磁保持继电器
  1139. // 启动记时
  1140. us_begin = ustimer_get_origin();
  1141. // 逐一输出开出点
  1142. for(j=0; j<KC_COUNT; j++)
  1143. {
  1144. dido_do(slot_do,(1<<j),1);
  1145. if(j==5&&bkc6close)
  1146. {
  1147. dido_do(slot_do,(1<<5),0); // 开出6若焊接为常闭输出,反操作为闭合
  1148. }
  1149. ustimer_delay(150*USTIMER_MS);
  1150. memset(di_ok,0,sizeof(di_ok));
  1151. do_errflag = DIGROUP;
  1152. for (k=0; k<4; k++)
  1153. {
  1154. bool bIgnore=false;
  1155. di_result = (g_di[slot_di].value[0] ^ g_di[slot_di].inv[0]);
  1156. k+=i*2;
  1157. if(test_di[j][k]==17)
  1158. {
  1159. bIgnore=check_board_di_valid(slot_di,17);
  1160. }
  1161. if(test_di[j][k]==18)
  1162. {
  1163. bIgnore=check_board_di_valid(slot_di,18);
  1164. }
  1165. if (!test_di[j][k]||bIgnore)
  1166. {
  1167. do_errflag--;
  1168. }
  1169. else
  1170. {
  1171. if (!(di_result & (1<<(test_di[j][k]-1)))) //对应开入无值
  1172. {
  1173. do_errflag--;
  1174. di_ok[k] = test_di[j][k];
  1175. }
  1176. }
  1177. }
  1178. if (!do_errflag) //开出对应的所有开入都没有值,即代表该开出有问题
  1179. {
  1180. if (j<8)
  1181. {
  1182. dido_buf[i+i*13+1] |= (1<<j); //开出错误标志
  1183. }
  1184. else if (j<16)
  1185. {
  1186. dido_buf[i+i*13+2] |= (1<<(j-8)); //开出错误标志
  1187. }
  1188. rt_printf("dido_test do err:i=%d,j=%d,di=%d,di_l=0x%04lx,di_h=0x%04lx.\r\n",
  1189. i,j,di_ok[0], g_di[slot_di].value[0],g_di[slot_di].value[1]);
  1190. }
  1191. else
  1192. {
  1193. for (k=0; k<4; k++)
  1194. {
  1195. if (!di_ok[k])
  1196. continue;
  1197. if ((di_ok[k]-1) < 8)
  1198. {
  1199. dido_buf[i+i*13+6] |= (1<<(di_ok[k]-1));
  1200. }
  1201. else if ((di_ok[k]-1) < 16)
  1202. {
  1203. dido_buf[i+i*13+7] |= (1<<(di_ok[k]-1-8));
  1204. }
  1205. else if ((di_ok[k]-1) < 24)
  1206. {
  1207. dido_buf[i+i*13+8] |= (1<<(di_ok[k]-1-16));
  1208. }
  1209. else if ((di_ok[k]-1) < 32)
  1210. {
  1211. dido_buf[i+i*13+9] |= (1<<(di_ok[k]-1-24));
  1212. }
  1213. else if ((di_ok[k]-1) < 40)
  1214. {
  1215. dido_buf[i+i*13+10] |= (1<<(di_ok[k]-1-32));
  1216. }
  1217. else if ((di_ok[k]-1) < 48)
  1218. {
  1219. dido_buf[i+i*13+11] |= (1<<(di_ok[k]-1-40));
  1220. }
  1221. else if ((di_ok[k]-1) < 56)
  1222. {
  1223. dido_buf[i+i*13+12] |= (1<<(di_ok[k]-1-48));
  1224. }
  1225. else if ((di_ok[k]-1) < 64)
  1226. {
  1227. dido_buf[i+i*13+13] |= (1<<(di_ok[k]-1-56));
  1228. }
  1229. rt_printf("dido_test di err:i=%d,j=%d,di=%d,di_l=0x%04lx,di_h=0x%04lx.\r\n",
  1230. i,j,di_ok[k], g_di[slot_di].value[0],g_di[slot_di].value[1]);
  1231. }
  1232. }
  1233. dido_do(slot_do,(1<<j),0);
  1234. if(j==5&&bkc6close)
  1235. {
  1236. dido_do(slot_do,(1<<5),1); // 开出6若焊接为常闭输出,反操作为闭合
  1237. }
  1238. //if(j==4)
  1239. //{
  1240. //dido_do(slot_do,(1<<5),1); //磁保持继电器
  1241. //}
  1242. ustimer_delay(20*USTIMER_MS);
  1243. watchdog_feed_mainloop();
  1244. }
  1245. }
  1246. for(i=0;i<EQU_SLOT_NUM_MAX;i++)
  1247. {
  1248. if(g_do_time[i].slot != 0)
  1249. {
  1250. rt_printf("do_time[%d]:diff_max=%lu,diff_out_count=%lu\r\n",
  1251. g_do_time[i].slot,g_do_time[i].diff_max,g_do_time[i].diff_out_count);
  1252. }
  1253. }
  1254. rt_printf("dido_test end:err_once=%d,error_count=%lu!\r\n\r\n\r\n",err_once,error_count);
  1255. return 0;
  1256. }
  1257. /*------------------------------ 文件结束 -------------------------------------
  1258. */