dido.c 28 KB

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