Modbus.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384
  1. /********************************************************************
  2. 版权所有:
  3. 文件版本: V1.00
  4. 文件名称: Modbus.c
  5. 生成日期: 2008年11月13日
  6. 作 者:xxxxxx
  7. 使用范围:
  8. 功 能: Modbus规约处理,为节省RAM空间,MODBUS规约处理,借用了103规约的结构定义
  9. 更新信息:
  10. 更新日志1:
  11. 修改者:
  12. 修改日期:
  13. 修改内容:
  14. 修改原因:
  15. *********************************************************************/
  16. #include "head.h"
  17. struct MODBUS_CMD_LEN
  18. {
  19. u8 cmd;
  20. u8 len;
  21. }; // 16*2
  22. struct MODBUS_CMD_LEN tModbusCmd[]=
  23. {
  24. {0x01,0},
  25. {0x02,0},
  26. {0x03,0},
  27. {0x04,0},
  28. {0x05,4},
  29. {0x06,4},
  30. {0x07,1},
  31. {0x0b,1},
  32. {0x0c,0},
  33. {0x0F,4},
  34. {0x10,4},
  35. {0x11,0},
  36. {0x85,1},
  37. };
  38. int modbus_cmd_num=sizeof(tModbusCmd)/sizeof(tModbusCmd[0]);
  39. BYTE MoDusCRCtableHi[] = // Modbus 高位校验码
  40. {
  41. 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
  42. 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
  43. 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
  44. 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
  45. 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
  46. 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
  47. 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
  48. 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
  49. 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
  50. 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
  51. 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
  52. 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
  53. 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
  54. 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
  55. 0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
  56. 0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40
  57. } ;
  58. //-------------------------------------------------------------
  59. //@@***********************************************************
  60. // MoDus CRC 低位字节值表
  61. //@@***********************************************************
  62. //-------------------------------------------------------------
  63. BYTE MoDusCRCtableLo[] =
  64. {
  65. 0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,0x04,
  66. 0xCC,0x0C,0x0D,0xCD,0x0F,0xCF,0xCE,0x0E,0x0A,0xCA,0xCB,0x0B,0xC9,0x09,0x08,0xC8,
  67. 0xD8,0x18,0x19,0xD9,0x1B,0xDB,0xDA,0x1A,0x1E,0xDE,0xDF,0x1F,0xDD,0x1D,0x1C,0xDC,
  68. 0x14,0xD4,0xD5,0x15,0xD7,0x17,0x16,0xD6,0xD2,0x12,0x13,0xD3,0x11,0xD1,0xD0,0x10,
  69. 0xF0,0x30,0x31,0xF1,0x33,0xF3,0xF2,0x32,0x36,0xF6,0xF7,0x37,0xF5,0x35,0x34,0xF4,
  70. 0x3C,0xFC,0xFD,0x3D,0xFF,0x3F,0x3E,0xFE,0xFA,0x3A,0x3B,0xFB,0x39,0xF9,0xF8,0x38,
  71. 0x28,0xE8,0xE9,0x29,0xEB,0x2B,0x2A,0xEA,0xEE,0x2E,0x2F,0xEF,0x2D,0xED,0xEC,0x2C,
  72. 0xE4,0x24,0x25,0xE5,0x27,0xE7,0xE6,0x26,0x22,0xE2,0xE3,0x23,0xE1,0x21,0x20,0xE0,
  73. 0xA0,0x60,0x61,0xA1,0x63,0xA3,0xA2,0x62,0x66,0xA6,0xA7,0x67,0xA5,0x65,0x64,0xA4,
  74. 0x6C,0xAC,0xAD,0x6D,0xAF,0x6F,0x6E,0xAE,0xAA,0x6A,0x6B,0xAB,0x69,0xA9,0xA8,0x68,
  75. 0x78,0xB8,0xB9,0x79,0xBB,0x7B,0x7A,0xBA,0xBE,0x7E,0x7F,0xBF,0x7D,0xBD,0xBC,0x7C,
  76. 0xB4,0x74,0x75,0xB5,0x77,0xB7,0xB6,0x76,0x72,0xB2,0xB3,0x73,0xB1,0x71,0x70,0xB0,
  77. 0x50,0x90,0x91,0x51,0x93,0x53,0x52,0x92,0x96,0x56,0x57,0x97,0x55,0x95,0x94,0x54,
  78. 0x9C,0x5C,0x5D,0x9D,0x5F,0x9F,0x9E,0x5E,0x5A,0x9A,0x9B,0x5B,0x99,0x59,0x58,0x98,
  79. 0x88,0x48,0x49,0x89,0x4B,0x8B,0x8A,0x4A,0x4E,0x8E,0x8F,0x4F,0x8D,0x4D,0x4C,0x8C,
  80. 0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40
  81. } ;
  82. /**************************************************************************
  83. 函数名称:Modbus_CRC16
  84. 函数版本:1.00
  85. 作者:
  86. 创建日期:2008.11.15
  87. 函数功能说明:Modbus规约的CRC校验
  88. 输入参数:
  89. 输出参数:
  90. 返回值:
  91. 更新信息:
  92. 更新日志1:
  93. 日期:
  94. 修改者:
  95. 修改内容:
  96. 修改原因:
  97. ***************************************************************************/
  98. WORD Modbus_CRC16(BYTE *inbytes, WORD CRCnumber) // 返回,低字节在高位
  99. {
  100. BYTE crcbyteHi = 0xFF ;
  101. BYTE crcbyteLo = 0xFF ;
  102. BYTE uIndex ;
  103. while (CRCnumber--)
  104. {
  105. uIndex = crcbyteHi ^ *inbytes++ ;
  106. crcbyteHi = crcbyteLo ^ MoDusCRCtableHi[uIndex] ;
  107. crcbyteLo = MoDusCRCtableLo[uIndex] ;
  108. }
  109. return ( (crcbyteHi << 8) | crcbyteLo ) ;
  110. }
  111. int _getslaveaddr(char *buf)
  112. {
  113. char *str,str1[6];
  114. int val=0;
  115. str=strstr(buf,"_slave");
  116. if(str)
  117. {
  118. memcpy(str1,&str[6],2);
  119. str1[2]='\0';
  120. val=strtoul(str1,NULL,10);
  121. }
  122. return val;
  123. }
  124. static void _getmodbusinf(MODBUS_DEF *pt,u8 *filestr)
  125. {
  126. u8 str[64];
  127. if(filestr[0]=='[') // 是规约类型
  128. {
  129. pt->bcfg=false;
  130. sprintf(str,"[COM%d_MODBUS]",pt->chnl);
  131. if(strcmp(filestr,"[MODBUS_ALL]")==0||strcmp(filestr,str)==0)
  132. {
  133. pt->bcfg=true;
  134. }
  135. return;
  136. }
  137. if(!pt->bcfg)return;
  138. if(strstr(filestr,"yxcmd")) // 遥信命令码
  139. {
  140. pt->yxcmd=getstrval(filestr);
  141. }
  142. else if(strstr(filestr,"yccmd")) //
  143. {
  144. pt->yccmd=getstrval(filestr);
  145. }
  146. else if(strstr(filestr,"ykcmd")) //
  147. {
  148. pt->ykcmd=getstrval(filestr);
  149. }
  150. else if(strstr(filestr,"ddcmd")) //
  151. {
  152. pt->ddcmd=getstrval(filestr);
  153. }
  154. else if(strstr(filestr,"yxreadbit")) //
  155. {
  156. pt->readbit=getstrval(filestr);
  157. }
  158. else if(strstr(filestr,"yxbytes")) //
  159. {
  160. pt->yxbitbytes=getstrval(filestr);
  161. }
  162. else if(strstr(filestr,"ycbytes")) //
  163. {
  164. pt->ycbitbytes=getstrval(filestr);
  165. }
  166. else if(strstr(filestr,"ykbytes")) //
  167. {
  168. pt->ykbitbytes=getstrval(filestr);
  169. }
  170. else if(strstr(filestr,"ddbytes")) //
  171. {
  172. pt->ddbitbytes=getstrval(filestr);
  173. }
  174. else if(strstr(filestr,"ykval_h")) //
  175. {
  176. pt->ykval_h=getstrval(filestr);
  177. }
  178. else if(strstr(filestr,"ykval_f")) //
  179. {
  180. pt->ykval_f=getstrval(filestr);
  181. }
  182. else if(strstr(filestr,"retrytime")) //
  183. {
  184. pt->retrytime=getstrval(filestr)*SAM_FREQUENCY; // 单位秒,转为dTcounter 值
  185. }
  186. else if(strstr(filestr,"sendinteraltime")) //
  187. {
  188. pt->sendinteraltime=getstrval(filestr)*SAMFREQ/20; // 单位毫秒,转为dTcounter值
  189. }
  190. else if(strstr(filestr,"coiladdr")) //
  191. {
  192. pt->coiladdr=getstrval(filestr); // 线圈地址
  193. }
  194. else if(strstr(filestr,"cmd_dinum")) //
  195. {
  196. pt->cmd_dinum=getstrval(filestr); // 点号长度
  197. }
  198. else if(strstr(filestr,"cmd_datnum")) //
  199. {
  200. pt->cmd_datnum=getstrval(filestr); // 数据长度
  201. }
  202. else if(strstr(filestr,"dat_dir")) //
  203. {
  204. pt->dat_dir=getstrval(filestr); //数据方向
  205. }
  206. else if(strstr(filestr,"yxdi")) //
  207. {
  208. pt->tinf[pt->infnum].slaveaddr=_getslaveaddr(filestr);
  209. pt->tinf[pt->infnum].val=getstrval(filestr);
  210. pt->tinf[pt->infnum].type=((MODBUS_TYPE_YX<<4)|MODBUS_INF_DI);
  211. pt->infnum++;
  212. if(pt->infnum>=MODBUS_INF_MAX)pt->infnum=MODBUS_INF_MAX-1;
  213. }
  214. else if(strstr(filestr,"ycdi")) //
  215. {
  216. pt->tinf[pt->infnum].slaveaddr=_getslaveaddr(filestr);
  217. pt->tinf[pt->infnum].val=getstrval(filestr);
  218. pt->tinf[pt->infnum].type=((MODBUS_TYPE_YC<<4)|MODBUS_INF_DI);
  219. pt->infnum++;
  220. if(pt->infnum>=MODBUS_INF_MAX)pt->infnum=MODBUS_INF_MAX-1;
  221. }
  222. else if(strstr(filestr,"dddi")) //
  223. {
  224. pt->tinf[pt->infnum].slaveaddr=_getslaveaddr(filestr);
  225. pt->tinf[pt->infnum].val=getstrval(filestr);
  226. pt->tinf[pt->infnum].type=((MODBUS_TYPE_DD<<4)|MODBUS_INF_DI);
  227. pt->infnum++;
  228. if(pt->infnum>=MODBUS_INF_MAX)pt->infnum=MODBUS_INF_MAX-1;
  229. }
  230. else if(strstr(filestr,"yxnum")) //
  231. {
  232. pt->tinf[pt->infnum].slaveaddr=_getslaveaddr(filestr);
  233. pt->tinf[pt->infnum].val=getstrval(filestr);
  234. pt->tinf[pt->infnum].type=((MODBUS_TYPE_YX<<4)|MODBUS_INF_NUM);
  235. pt->infnum++;
  236. if(pt->infnum>=MODBUS_INF_MAX)pt->infnum=MODBUS_INF_MAX-1;
  237. }
  238. else if(strstr(filestr,"ycnum")) //
  239. {
  240. pt->tinf[pt->infnum].slaveaddr=_getslaveaddr(filestr);
  241. pt->tinf[pt->infnum].val=getstrval(filestr);
  242. pt->tinf[pt->infnum].type=((MODBUS_TYPE_YC<<4)|MODBUS_INF_NUM);
  243. pt->infnum++;
  244. if(pt->infnum>=MODBUS_INF_MAX)pt->infnum=MODBUS_INF_MAX-1;
  245. }
  246. else if(strstr(filestr,"ddnum")) //
  247. {
  248. pt->tinf[pt->infnum].slaveaddr=_getslaveaddr(filestr);
  249. pt->tinf[pt->infnum].val=getstrval(filestr);
  250. pt->tinf[pt->infnum].type=((MODBUS_TYPE_DD<<4)|MODBUS_INF_NUM);
  251. pt->infnum++;
  252. if(pt->infnum>=MODBUS_INF_MAX)pt->infnum=MODBUS_INF_MAX-1;
  253. }
  254. else if(strstr(filestr,"yxbit")) //
  255. {
  256. pt->tinf[pt->infnum].slaveaddr=_getslaveaddr(filestr);
  257. pt->tinf[pt->infnum].val=getstrval(filestr);
  258. pt->tinf[pt->infnum].type=((MODBUS_TYPE_YX<<4)|MODBUS_INF_BITS);
  259. pt->infnum++;
  260. if(pt->infnum>=MODBUS_INF_MAX)pt->infnum=MODBUS_INF_MAX-1;
  261. }
  262. else if(strstr(filestr,"sendaddr")) //
  263. {
  264. pt->tinf[pt->infnum].slaveaddr=_getslaveaddr(filestr);
  265. pt->tinf[pt->infnum].val=getstrval(filestr);
  266. pt->tinf[pt->infnum].type=MODBUS_INF_SENDADDR;
  267. pt->infnum++;
  268. if(pt->infnum>=MODBUS_INF_MAX)pt->infnum=MODBUS_INF_MAX-1;
  269. }
  270. else if(strstr(filestr,"ycrate")) //
  271. {
  272. pt->yc_rate=getstrval(filestr);
  273. }
  274. #ifdef MODBUS_YX_REG_NUM
  275. else if(strstr(filestr,"yxregnum")) //
  276. {
  277. pt->yxregnum=getstrval(filestr);
  278. }
  279. #endif
  280. }
  281. static int modbus_init_inf(MODBUS_DEF *pt)
  282. {
  283. u32 i,file_length;
  284. struct file * pfile;
  285. u8 *filebuf;
  286. u8 filestr[128],*pstr,strlenth;
  287. loff_t pos;
  288. // 打开文件
  289. pfile = rt_file_open("/app/data/pcolcfg.ini",O_RDONLY ,0);
  290. if(IS_ERR(pfile))
  291. {
  292. dp_err_n_c_rt("error! 无法打开 pcolcfg.ini\r\n");
  293. return -1;
  294. }
  295. // 得到文件长度
  296. file_length = rt_file_getfile_size(pfile);
  297. if(file_length <= 0)
  298. {
  299. rt_file_close(pfile,0);
  300. return -2;
  301. }
  302. // 分配内存
  303. filebuf = rt_malloc(file_length);
  304. if((filebuf) == NULL)
  305. {
  306. rt_file_close(pfile,0);
  307. return -3;
  308. }
  309. pos = 0;
  310. if(rt_file_read(pfile,filebuf,file_length,&pos) != file_length)
  311. {
  312. rt_file_close(pfile,0);
  313. rt_free(filebuf);
  314. return -4;
  315. }
  316. pstr = filestr;
  317. strlenth=0; // 纠错处理
  318. //找到\r\n位置,得到一行长度
  319. for(i = 0; i < file_length; i++)
  320. {
  321. *pstr++=filebuf[i];
  322. strlenth++;
  323. if(filebuf[i] == 0x0a||strlenth>=128)
  324. {
  325. int j;
  326. pstr = filestr;
  327. for(j=0;j<strlenth;j++)
  328. {
  329. if(*pstr==' '||*pstr=='\t') // 取空格或tab 前的字符
  330. {
  331. *pstr='\0';
  332. break;
  333. }
  334. pstr++;
  335. }
  336. *pstr='\0';
  337. _getmodbusinf(pt,filestr);
  338. pstr=filestr;
  339. strlenth=0;
  340. }
  341. }
  342. rt_file_close(pfile,0); // 关闭文件
  343. rt_free(filebuf); // 释放内存
  344. return 0;
  345. }
  346. typedef struct MODBUS_SLAVE_DEF
  347. {
  348. u8 cmd;
  349. u8 type;
  350. u8 dinum;
  351. u8 bitbytes;
  352. u8 readbit;
  353. #ifdef MODBUS_YX_REG_NUM
  354. u8 yxregnum;
  355. #endif
  356. WORD dimin;
  357. WORD dimax;
  358. WORD slaveaddr;
  359. }MODBUS_SLAVE_DEF;
  360. void modbus_count_slaveaddr(MODBUS_DEF *pt,u8 chnl,LINK_TABLE* lt,u32 num,BYTE cmd,BYTE bitbytes,BYTE readbit,BYTE type)
  361. {
  362. u8 ch;
  363. u8 addr=0;
  364. u16 di;
  365. MODBUS_SLAVE_DEF tms[32];
  366. int i,j,slavenum;
  367. #ifdef MODBUS_YX_REG_NUM
  368. BYTE yxregnum = pt->yxregnum;
  369. WORD yx_dimin=0,yx_dimax=0;
  370. #endif
  371. memset(&tms,0,sizeof(tms));
  372. slavenum=0;
  373. for(j=0;j<num;j++)
  374. {
  375. ch=(u8)((lt->cp_s>>21)&0x0f);
  376. addr=(u8)((lt->cp_s>>16)&0x1f);
  377. di=(u16)lt->cp_s;
  378. if(addr>0&&(ch==chnl)) // 通道相符
  379. {
  380. if(slavenum==0)
  381. {
  382. tms[slavenum].slaveaddr=addr;
  383. tms[slavenum].dimax=di;
  384. tms[slavenum].dimin=di;
  385. tms[slavenum].cmd=cmd;
  386. tms[slavenum].bitbytes=bitbytes;
  387. tms[slavenum].readbit=readbit;
  388. tms[slavenum].type=type;
  389. tms[slavenum].dinum=1;
  390. #ifdef MODBUS_YX_REG_NUM
  391. tms[slavenum].yxregnum=yxregnum;
  392. #endif
  393. slavenum++;
  394. }
  395. else
  396. {
  397. for(i=0;i<slavenum;i++)
  398. {
  399. if(tms[i].slaveaddr==addr&& (tms[i].type==type) )// 同一类型,同一子站地址
  400. {
  401. if(di<tms[i].dimin)
  402. {
  403. tms[i].dimin=di;
  404. }
  405. if(di>tms[i].dimax)
  406. {
  407. tms[i].dimax=di;
  408. }
  409. tms[i].dinum++; // 个数加1
  410. break;
  411. }
  412. }
  413. if(i==slavenum)
  414. {
  415. tms[slavenum].slaveaddr=addr;
  416. tms[slavenum].dimax=di;
  417. tms[slavenum].dimin=di;
  418. tms[slavenum].cmd=cmd;
  419. tms[slavenum].bitbytes=bitbytes;
  420. tms[slavenum].readbit=readbit;
  421. tms[slavenum].type=type;
  422. tms[slavenum].dinum=1;
  423. #ifdef MODBUS_YX_REG_NUM
  424. tms[slavenum].yxregnum=yxregnum;
  425. #endif
  426. slavenum++;
  427. }
  428. }
  429. }
  430. lt++;
  431. }
  432. for(i=0;i<slavenum;i++)
  433. {
  434. WORD maxsmin;
  435. for(j=0;j<pt->infnum;j++) // 判断字节数类型,是否有重新定义
  436. {
  437. if(tms[i].slaveaddr==pt->tinf[j].slaveaddr)
  438. {
  439. if(((pt->tinf[j].type>>4)&0x0f)==tms[i].type)
  440. {
  441. if((pt->tinf[j].type&0x0f)==MODBUS_INF_BITS)
  442. {
  443. tms[i].readbit=pt->tinf[j].val;
  444. }
  445. }
  446. }
  447. }
  448. #ifdef MODBUS_YX_REG_NUM
  449. yx_dimax = tms[i].dimax;
  450. yx_dimin = tms[i].dimin;
  451. #endif
  452. if(type==MODBUS_TYPE_YX && tms[i].readbit==1 && tms[i].dimin!=0) // 遥信且按bit取值
  453. {
  454. #ifndef LINK_MODBUS_YX_CP
  455. tms[i].dimax>>=4; // 最低4bit为 位序号
  456. tms[i].dimin>>=4; // 最低4bit为 位序号
  457. #endif
  458. }
  459. pt->tcmd[pt->cmdnum].slaveaddr=tms[i].slaveaddr;
  460. pt->tcmd[pt->cmdnum].cmd=tms[i].cmd;
  461. pt->tcmd[pt->cmdnum].bitbytes=tms[i].bitbytes;;
  462. pt->tcmd[pt->cmdnum].readbit=tms[i].readbit;;
  463. pt->tcmd[pt->cmdnum].di=tms[i].dimin;
  464. pt->tcmd[pt->cmdnum].type=tms[i].type;
  465. maxsmin=tms[i].dimax-tms[i].dimin+1;
  466. #ifdef MODBUS_YX_REG_NUM
  467. if((type==MODBUS_TYPE_YX&&tms[i].readbit==1))
  468. {
  469. if(tms[i].yxregnum==0)
  470. {
  471. pt->tcmd[pt->cmdnum].num=(yx_dimax-yx_dimin+1)%16?(yx_dimax-yx_dimin+1)/16+1:(yx_dimax-yx_dimin+1)/16;
  472. }
  473. else
  474. {
  475. pt->tcmd[pt->cmdnum].num=yx_dimax-yx_dimin+1;
  476. }
  477. }
  478. else
  479. {
  480. pt->tcmd[pt->cmdnum].num=(maxsmin>tms[i].dinum)?maxsmin:tms[i].dinum; // 取个数大的为寄存器个数
  481. }
  482. #else
  483. pt->tcmd[pt->cmdnum].num=(maxsmin>tms[i].dinum)?maxsmin:tms[i].dinum; // 取个数大的为寄存器个数
  484. #endif
  485. pt->tcmd[pt->cmdnum].byxfirst=false;
  486. if(tms[i].bitbytes==4||tms[i].bitbytes==13) // 四个字节或浮点数
  487. {
  488. pt->tcmd[pt->cmdnum].num*=2; // 寄存器个数加倍
  489. }
  490. for(j=0;j<pt->infnum;j++) // 更新重新定义的点号和召唤个数
  491. {
  492. if(pt->tcmd[pt->cmdnum].slaveaddr==pt->tinf[j].slaveaddr)
  493. {
  494. if(((pt->tinf[j].type>>4)&0x0f)==pt->tcmd[pt->cmdnum].type)
  495. {
  496. if((pt->tinf[j].type&0x0f)==MODBUS_INF_DI)
  497. {
  498. pt->tcmd[pt->cmdnum].di=pt->tinf[j].val;
  499. }
  500. else if((pt->tinf[j].type&0x0f)==MODBUS_INF_NUM)
  501. {
  502. pt->tcmd[pt->cmdnum].num=pt->tinf[j].val;
  503. }
  504. }
  505. }
  506. }
  507. pt->cmdnum++;
  508. if(pt->cmdnum>=MODBUS_CMD_NUM)
  509. {
  510. pt->cmdnum=MODBUS_CMD_NUM-1;
  511. }
  512. }
  513. }
  514. void modbus_sendaddr_init(MODBUS_DEF *pt)
  515. {
  516. int i;
  517. for(i=0;i<pt->cmdnum;i++)
  518. {
  519. int j;
  520. pt->tcmd[i].sendaddr=pt->tcmd[i].slaveaddr;
  521. for(j=0;j<pt->infnum;j++)
  522. {
  523. if((pt->tinf[j].type==MODBUS_INF_SENDADDR)&&(pt->tinf[j].slaveaddr==pt->tcmd[i].slaveaddr))
  524. {
  525. pt->tcmd[i].sendaddr=pt->tinf[j].val;
  526. }
  527. }
  528. }
  529. }
  530. /**************************************************************************
  531. 函数名称:Modbus_Init
  532. 函数版本:1.00
  533. 作者:
  534. 创建日期:2008.9.1
  535. 函数功能说明:Modbus规约初始化
  536. 输入参数:
  537. 输出参数:
  538. 返回值:
  539. 更新信息:
  540. 更新日志1:
  541. 日期:
  542. 修改者:
  543. 修改内容:
  544. 修改原因:
  545. ***************************************************************************/
  546. void modbus_Init(MODBUS_DEF *pt,BYTE chnl)
  547. {
  548. int i;
  549. memset(pt,0,sizeof(MODBUS_DEF));
  550. pt->type=IEC_MODBUS_M;
  551. pt->chnl=chnl;
  552. pt->bData=false;
  553. pt->sendbuf=g_tRsComm[chnl].sendbuf;
  554. pt->dsendtime=dTCounter;
  555. pt->yxcmd=2;
  556. pt->yccmd=3;
  557. pt->ykcmd=5;
  558. pt->ddcmd=4;
  559. pt->yxbitbytes=1;
  560. pt->ycbitbytes=2;
  561. pt->ykbitbytes=2;
  562. pt->ddbitbytes=4;
  563. pt->ykval_h=0xff00;
  564. pt->ykval_f=0x0000;
  565. pt->coiladdr=0;
  566. pt->readbit=0;
  567. pt->cmd_datnum=2;
  568. pt->cmd_dinum=2;
  569. pt->dat_dir=0;
  570. pt->yc_rate=1;
  571. modbus_init_inf(pt);
  572. modbus_count_slaveaddr(pt,chnl+2,&g_lt_di[0],g_lt_di_num,pt->yxcmd,pt->yxbitbytes,pt->readbit,MODBUS_TYPE_YX);
  573. modbus_count_slaveaddr(pt,chnl+2,&g_lt_ac[0],g_lt_ac_num,pt->yccmd,pt->ycbitbytes,0,MODBUS_TYPE_YC);
  574. modbus_count_slaveaddr(pt,chnl+2,&g_lt_dd[0],g_lt_dd_num,pt->ddcmd,pt->ddbitbytes,0,MODBUS_TYPE_DD);
  575. modbus_sendaddr_init(pt);
  576. rt_printf("\r\nmodbus_init(channel=%d):\r\n",chnl);
  577. for(i=0;i<pt->cmdnum;i++)
  578. {
  579. rt_printf("chnl=%d addr=%d sendaddr=%d di=%04x cmd=%d num=%d type=%d bitbytes=%d readbit=%d\r\n",chnl,pt->tcmd[i].slaveaddr,pt->tcmd[i].sendaddr,pt->tcmd[i].di,pt->tcmd[i].cmd,pt->tcmd[i].num,pt->tcmd[i].type,pt->tcmd[i].bitbytes,pt->tcmd[i].readbit);
  580. }
  581. }
  582. /**************************************************************************
  583. 函数名称:Modbus_Recv_Rst
  584. 函数版本:1.00
  585. 作者:
  586. 创建日期:2008.11.15
  587. 函数功能说明:复归数据的接受
  588. 输入参数:
  589. 输出参数:
  590. 返回值:
  591. 更新信息:
  592. 更新日志1:
  593. 日期:
  594. 修改者:
  595. 修改内容:
  596. 修改原因:
  597. ***************************************************************************/
  598. void modbus_recv_rst(MODBUS_DEF *pt)
  599. {
  600. pt->nTypeCounter=0;
  601. pt->nRecvLenth=0;
  602. pt->nRecvCounter=0;
  603. pt->dWaitTime=dTCounter;
  604. }
  605. int get_cmd_len(u8 cmd)
  606. {
  607. int i;
  608. for(i=0;i<modbus_cmd_num;i++)
  609. {
  610. if(tModbusCmd[i].cmd==cmd)
  611. {
  612. return tModbusCmd[i].len;
  613. }
  614. }
  615. return -1;
  616. }
  617. /**************************************************************************
  618. 函数名称:Modbus_Recv
  619. 函数版本:1.00
  620. 作者:
  621. 创建日期:2008.11.15
  622. 函数功能说明:Modbus规约的数据接收处理,此处有3.5位的时间判断处理
  623. 输入参数:
  624. 输出参数:
  625. 返回值:
  626. 更新信息:
  627. 更新日志1:
  628. 日期:
  629. 修改者:
  630. 修改内容:
  631. 修改原因:
  632. ***************************************************************************/
  633. void modbus_Recv(MODBUS_DEF *pt,unsigned char byRevData)
  634. {
  635. int len;
  636. if(pt->bData)return ;
  637. if(dTCounter-pt->dWaitTime>T_5ms) //检测到空闲间隔 3.5个字符
  638. {
  639. pt->recvbuf[pt->nRecvCounter++]=byRevData;
  640. switch(pt->nTypeCounter)
  641. {
  642. case 0: // 子站地址
  643. if(byRevData==pt->slaveaddr)
  644. {
  645. pt->nTypeCounter++;
  646. }
  647. else
  648. {
  649. modbus_recv_rst(pt);
  650. }
  651. break;
  652. case 1: //功能码
  653. pt->nTypeCounter++;
  654. break;
  655. case 2: //字节数
  656. len=get_cmd_len(pt->recvbuf[1]);
  657. pt->nTypeCounter++;
  658. pt->nRecvCnt=0;
  659. if(len==0)
  660. {
  661. pt->nRecvLenth=byRevData+2;
  662. }
  663. else if(len>0)
  664. {
  665. pt->nRecvLenth=len+1;
  666. }
  667. else
  668. {
  669. modbus_recv_rst(pt);
  670. }
  671. break;
  672. case 3: // CRC L 或其他数据
  673. pt->nRecvCnt++;
  674. if(pt->nRecvCnt>=pt->nRecvLenth)
  675. {
  676. modbus_recv_rst(pt);
  677. pt->bData=true;
  678. }
  679. break;
  680. default:
  681. modbus_recv_rst(pt);
  682. break;
  683. }
  684. }
  685. else //奇偶校验出错,舍弃已接收的数据
  686. {
  687. modbus_recv_rst(pt);
  688. }
  689. }
  690. /**************************************************************************
  691. 函数名称:Modbus_ErrorEcho
  692. 函数版本:1.00
  693. 作者:
  694. 创建日期:2008.11.15
  695. 函数功能说明:Modbus规约错误帧应答
  696. 输入参数:
  697. 输出参数:
  698. 返回值:
  699. 更新信息:
  700. 更新日志1:
  701. 日期:
  702. 修改者:
  703. 修改内容:
  704. 修改原因:
  705. ***************************************************************************/
  706. void modbus_errorecho(MODBUS_DEF *pt,unsigned char *ps,unsigned char err)
  707. {
  708. BYTE *pd=pt->sendbuf;
  709. WORD crc;
  710. pd[0]=5;
  711. pd[1]=pt->tcmd[pt->bCurrent].slaveaddr; // 地址
  712. pd[2]=ps[1]|0x80; // 命令码
  713. pd[3]=err; // 错误码
  714. crc=Modbus_CRC16(&pd[1],3);
  715. pd[4]=(BYTE)(crc>>8);
  716. pd[5]=(BYTE)(crc);
  717. }
  718. /**************************************************************************
  719. 函数名称:Modbus_ReadData
  720. 函数版本:1.00
  721. 作者:
  722. 创建日期:2008.11.15
  723. 函数功能说明:Modbus规约读数据应答,响应 02 03命令
  724. 输入参数:
  725. 输出参数:
  726. 返回值:
  727. 更新信息:
  728. 更新日志1:
  729. 日期:
  730. 修改者:
  731. 修改内容:
  732. 修改原因:
  733. ***************************************************************************/
  734. void modbus_send(MODBUS_DEF *pt)
  735. {
  736. if(g_print_lnk && (g_print_port & (1<<pt->chnl)))
  737. {
  738. print_msg("TX_MODBUS:",&g_tRsComm[pt->chnl].sendbuf[1],g_tRsComm[pt->chnl].sendbuf[0]);
  739. }
  740. RS_Send_Enable(pt->chnl);
  741. g_tRsComm[pt->chnl].nSendCnt=1; // 发送缓冲区的第一个字节为发送长度
  742. g_tRsComm[pt->chnl].bSend=true;
  743. pt->slaveaddr=g_tRsComm[pt->chnl].sendbuf[1];
  744. if(!g_bCommLed)g_bCommLed=true;
  745. //统计发送帧数
  746. }
  747. void modbus_read(MODBUS_DEF *pt,BYTE index)
  748. {
  749. BYTE *pd=pt->sendbuf;
  750. int num=0;
  751. WORD crc;
  752. pt->readdi=pt->tcmd[index].di;
  753. pd[num++]=0;
  754. pd[num++]=pt->tcmd[index].slaveaddr; // 地址
  755. pd[num++]=pt->tcmd[index].cmd; // 命令码
  756. if(pt->cmd_dinum>1) pd[num++]=(BYTE)(pt->tcmd[index].di>>8);
  757. pd[num++]=(BYTE)(pt->tcmd[index].di);
  758. if(pt->cmd_datnum>1) pd[num++]=(BYTE)(pt->tcmd[index].num>>8);
  759. pd[num++]=(BYTE)(pt->tcmd[index].num);
  760. crc=Modbus_CRC16(&pd[1],num-1);
  761. pd[num++]=(BYTE)(crc>>8);
  762. pd[num++]=(BYTE)(crc);
  763. pd[0]=num-1;
  764. modbus_send(pt);
  765. }
  766. void modbus_write(MODBUS_DEF *pt,BYTE addr,WORD di,BYTE num,BYTE *pdat)
  767. {
  768. BYTE *pd=pt->sendbuf;
  769. WORD crc;
  770. int i,j;
  771. BYTE slaveaddr=addr;
  772. int cnt=0;
  773. for(j=0;j<pt->infnum;j++)
  774. {
  775. if((pt->tinf[j].type==MODBUS_INF_SENDADDR)&&(pt->tinf[j].slaveaddr==addr))
  776. {
  777. slaveaddr=pt->tinf[j].val;
  778. }
  779. }
  780. pt->readdi=di;
  781. pd[cnt++]=0;
  782. pd[cnt++]=slaveaddr; // 地址
  783. pd[cnt++]=pt->ykcmd; // 命令码
  784. if(pt->cmd_dinum>1) pd[cnt++]=(BYTE)(di>>8);
  785. pd[cnt++]=(BYTE)(di);
  786. for(i=0;i<num;i++)
  787. {
  788. pd[cnt++]=*pdat++;
  789. }
  790. crc=Modbus_CRC16(&pd[1],cnt-1);
  791. pd[cnt++]=(BYTE)(crc>>8);
  792. pd[cnt++]=(BYTE)(crc);
  793. pd[0]=cnt-1;
  794. modbus_send(pt);
  795. }
  796. void modbus_slave_yk(u8 ch,u8 ti,u8 cot,u8 v,u16 cp ,u8 yktype)
  797. {
  798. LINK_TABLE * lt;
  799. struct do_table *dt;
  800. LINKYK_DEF *yk;
  801. char buf[128];
  802. // 查找点表,如果找到,保存。
  803. lt = tbl_link_do(ch,cp);
  804. if(lt)
  805. {
  806. dt = &g_do_table[lt->tbl_index];
  807. yk = &g_lnk_yk[dt->owner];
  808. if(cp != yk->cp_s)
  809. {
  810. rt_printf_time("lnk_slave_yk err:cp=%04x,cp_s=%04x",cp,yk->cp_s);
  811. return;
  812. }
  813. if((cot&0x3f)==IEC_COT_ACT)
  814. {
  815. cot=IEC_COT_ACTCON|(cot&0xc0);
  816. }
  817. else if((cot&0x3f)==IEC_COT_DEACT)
  818. {
  819. cot=IEC_COT_DEACTCON|(cot&0xc0);
  820. }
  821. yk->data[yktype].ti=ti;
  822. yk->data[yktype].cot=cot;
  823. yk->data[yktype].v=v;
  824. yk->flag[yktype] = true;
  825. sprintf(buf,"级联遥控上行:(ch=%d,cp_s=%04x,cp_m=%04x,ti=%02x,cot=%02x,v=%02x)",ch,lt->cp_s,dt->cp,ti,cot,v);
  826. log_str_time(LOG_OPERATE,buf,0,0);
  827. rt_printf_time("%s\r\n",buf);
  828. }
  829. else
  830. {
  831. rt_printf_time("lnk_slave_yk:查找级联表失败 ch=%d,cp=%04x.\r\n",ch,cp);
  832. }
  833. }
  834. /**************************************************************************
  835. 函数名称:Modbus_Applay
  836. 函数版本:1.00
  837. 作者:
  838. 创建日期:2008.11.15
  839. 函数功能说明:Modbus规约应用数据处理
  840. 输入参数:
  841. 输出参数:
  842. 返回值:
  843. 更新信息:
  844. 更新日志1:
  845. 日期:
  846. 修改者:
  847. 修改内容:
  848. 修改原因:
  849. ***************************************************************************/
  850. void modbus_Applay(MODBUS_DEF *pt)
  851. {
  852. BYTE *pd;
  853. WORD crc,crc1;
  854. BYTE cmd;
  855. int len;
  856. if(!pt->bData)return;
  857. cmd=pt->recvbuf[1];
  858. len=get_cmd_len(cmd);
  859. if(len==0) //带字节数的报文 如 1 2 3 4
  860. {
  861. len=pt->recvbuf[2]+1; // 含字节数本身
  862. pd=&pt->recvbuf[3]; // 数据
  863. }
  864. else if(len>0) // 不带字节数的报文,如 5 0x0f 0x10等
  865. {
  866. pd=&pt->recvbuf[2]; // 数据
  867. }
  868. else
  869. {
  870. pt->bData=false;
  871. return;
  872. }
  873. if(g_print_lnk && (g_print_port & (1<<pt->chnl)))
  874. {
  875. print_msg("RX_MODBUS:",pt->recvbuf,(len+4));
  876. }
  877. crc=(WORD)(pt->recvbuf[len+2]<<8)+pt->recvbuf[len+3];
  878. crc1=Modbus_CRC16(&pt->recvbuf[0],len+2);
  879. if(crc==crc1) //crc校验通过,若不通过,不应答
  880. {
  881. MODBUS_CMD_DEF *pcmd;
  882. pcmd=&pt->tcmd[pt->bCurrent];
  883. if(cmd==pcmd->cmd)
  884. {
  885. int i;
  886. u16 ch,cp;
  887. LINK_TABLE * lt;
  888. ch=((pt->chnl+2)<<5)+pcmd->slaveaddr;
  889. switch(pcmd->type) // 判断命令码
  890. {
  891. case MODBUS_TYPE_YX: //
  892. {
  893. WORD dat;
  894. //struct di_table *dt;
  895. if(pcmd->readbit==1) // 按位取遥信
  896. {
  897. int bytenum=1;
  898. if(pcmd->bitbytes==2)
  899. {
  900. bytenum=2;
  901. }
  902. for(i=0;i<len/bytenum;i++)
  903. {
  904. int j,k=8;
  905. if(bytenum==2) // 按字读
  906. {
  907. if(!pt->dat_dir)
  908. {
  909. dat=(pd[0]<<8) | (pd[1]<<0);
  910. }
  911. else
  912. {
  913. dat=(pd[1]<<8) | (pd[0]<<0);
  914. }
  915. pd+=2;
  916. k=16;
  917. }
  918. else
  919. {
  920. dat=*pd++;
  921. }
  922. for(j=0;j<k;j++) //刷新遥信
  923. {
  924. //cp=(((pcmd->di+i)<<4)|j); // 将bit 位加入点号中
  925. #ifdef LINK_MODBUS_YX_CP
  926. cp=(pcmd->di+(k*i))+j;
  927. #else
  928. cp=((pcmd->di<<4)+(k*i))+j; // 将bit 位加入点号中
  929. #endif
  930. lt = tbl_link_di(ch,cp);
  931. if(lt)
  932. {
  933. int cpv,v;
  934. //dt = &g_di_table[lt->tbl_index];
  935. cpv=sw_di_get(lt->owner,lt->indexno);
  936. v=((dat>>j)&0x01)+1;
  937. sw_di_set(lt->owner,lt->indexno,v); //转为双点保存
  938. if(cpv>=0&&pcmd->byxfirst) // 遥信已初始化过,产生soe
  939. {
  940. //rt_printf("%s:i=%d,j=%d,cp=%04x,lt->cp=%04x,cpv=%d,v=%d,dat=%x\r\n",__func__,i,j,cp,lt->cp,cpv,v,dat);
  941. if(v!=cpv)
  942. {
  943. struct timespec ts;
  944. clk_time_get(&ts);
  945. v = lt->is_inverse ? ((~v)&0x03) : v;
  946. soe_record_lnk(lt->cp ,v,&ts,(s32)lt,lt->is_mix,lt->cp_s);
  947. }
  948. }
  949. }
  950. }
  951. }
  952. }
  953. else // 按字节取遥信
  954. {
  955. for(i=0;i<len;i++)
  956. {
  957. dat=*pd++;
  958. cp=pcmd->di+i; // 将bit 位加入点号中
  959. lt = tbl_link_di(ch,cp);
  960. if(lt)
  961. {
  962. int cpv,v;
  963. //dt = &g_di_table[lt->tbl_index];
  964. cpv=sw_di_get(lt->owner,lt->indexno);
  965. v=dat+1;
  966. sw_di_set(lt->owner,lt->indexno,v);
  967. if(cpv>=0&&pcmd->byxfirst) // 遥信已初始化过,产生soe
  968. {
  969. if(v!=cpv)
  970. {
  971. struct timespec ts;
  972. clk_time_get(&ts);
  973. v = lt->is_inverse ? ((~v)&0x03) : v;
  974. soe_record_lnk(lt->cp ,v,&ts,(s32)lt,lt->is_mix,lt->cp_s);
  975. }
  976. }
  977. }
  978. }
  979. }
  980. pcmd->byxfirst=true;
  981. }
  982. break;
  983. case MODBUS_TYPE_YC: //
  984. case MODBUS_TYPE_DD: //
  985. {
  986. BYTE num;
  987. struct ac_table *at;
  988. struct dd_table *dt;
  989. qs16 v;
  990. float fv;
  991. if(pcmd->bitbytes==13||pcmd->bitbytes==4) //浮点
  992. {
  993. num=len/4;
  994. }
  995. else // 整形 2字节
  996. {
  997. num=len/2;
  998. }
  999. for(i=0;i<num;i++)
  1000. {
  1001. if(pcmd->bitbytes==13)
  1002. {
  1003. union{
  1004. float ff;
  1005. u8 tt[4];
  1006. }ff;
  1007. // 浮点
  1008. if(!pt->dat_dir)
  1009. {
  1010. #ifdef MODE_LITTLE_ENDIAN
  1011. ff.tt[3]=*pd++;
  1012. ff.tt[2]=*pd++;
  1013. ff.tt[1]=*pd++;
  1014. ff.tt[0]=*pd++;
  1015. #else
  1016. ff.tt[0]=*pd++;
  1017. ff.tt[1]=*pd++;
  1018. ff.tt[2]=*pd++;
  1019. ff.tt[3]=*pd++;
  1020. #endif
  1021. }
  1022. else
  1023. {
  1024. pd += CopySwap(ff.tt,pd,4,false);
  1025. }
  1026. fv = ff.ff;
  1027. v=fv;
  1028. }
  1029. else if(pcmd->bitbytes==4)
  1030. {
  1031. if(!pt->dat_dir)
  1032. {
  1033. v = (pd[0]<<24) | (pd[1]<<16) |(pd[2]<<8) | (pd[3]<<0); // 高字节在前
  1034. }
  1035. else
  1036. {
  1037. v = (pd[3]<<24) | (pd[2]<<16) |(pd[1]<<8) | (pd[0]<<0); // 高字节在前
  1038. }
  1039. pd += 4;
  1040. fv=v;
  1041. }
  1042. else
  1043. {
  1044. if(!pt->dat_dir)
  1045. {
  1046. v = (pd[0]<<8) | (pd[1]<<0);
  1047. }
  1048. else
  1049. {
  1050. v = (pd[1]<<8) | (pd[0]<<0);
  1051. }
  1052. pd += 2;
  1053. fv=v;
  1054. }
  1055. cp=pcmd->di+i;
  1056. if(pcmd->type==MODBUS_TYPE_YC)
  1057. {
  1058. int divbase=pt->yc_rate;
  1059. if(divbase==0)divbase=1;
  1060. v*=(Q16_BASE/divbase);
  1061. lt = tbl_link_ac(ch,cp);
  1062. if(lt)
  1063. {
  1064. at = &g_ac_table[lt->tbl_index];
  1065. if(at->owner == 0)
  1066. {
  1067. g_sw_pub.ac_in[at->indexno-1] = v;
  1068. }
  1069. else
  1070. {
  1071. g_sw[at->owner-1].ac_in[at->indexno-1] = v;
  1072. }
  1073. }
  1074. }
  1075. else
  1076. {
  1077. lt = tbl_link_dd(ch,cp);
  1078. if(lt)
  1079. {
  1080. dt = &g_dd_table[lt->tbl_index];
  1081. if(dt->owner >0)
  1082. {
  1083. g_sw[dt->owner-1].dd[dt->indexno-1].fv= fv;
  1084. g_sw[dt->owner-1].dd[dt->indexno-1].bchanged= 0;
  1085. }
  1086. }
  1087. }
  1088. }
  1089. }
  1090. break;
  1091. default:break;
  1092. }
  1093. }
  1094. else if(cmd==pt->ykcmd) // 遥控应答
  1095. {
  1096. LINKYK_DEF *yk;
  1097. yk = &g_lnk_yk[pt->yksendindex];
  1098. modbus_slave_yk(yk->chnl,yk->data[IECLINK_YK_SND].ti,7,yk->data[IECLINK_YK_SND].v,yk->cp_s,IECLINK_YK_ACK);
  1099. modbus_slave_yk(yk->chnl,yk->data[IECLINK_YK_SND].ti,10,yk->data[IECLINK_YK_SND].v,yk->cp_s,IECLINK_YK_END);
  1100. }
  1101. pt->bRecvOk=true;
  1102. pt->dsendtime=dTCounter;
  1103. }
  1104. else
  1105. {
  1106. rt_printf("\r\n modbus 接收报文crc校验错误 !\r\n");
  1107. }
  1108. pt->bData=false;
  1109. modbus_recv_rst(pt);
  1110. }
  1111. /**************************************************************************
  1112. 函数名称:Modbus_AutoTime
  1113. 函数版本:1.00
  1114. 作者:
  1115. 创建日期:2008.11.15
  1116. 函数功能说明:Modbus规约定时处理函数,主要是超时处理
  1117. 输入参数:
  1118. 输出参数:
  1119. 返回值:
  1120. 更新信息:
  1121. 更新日志1:
  1122. 日期:
  1123. 修改者:
  1124. 修改内容:
  1125. 修改原因:
  1126. ***************************************************************************/
  1127. void modbus_AutoTimer(MODBUS_DEF *pt)
  1128. {
  1129. if((dTCounter-pt->dsendtime>pt->retrytime)||(pt->bRecvOk&&(dTCounter-pt->dsendtime>pt->sendinteraltime)))// 超时处理或接收到报文后延时sendinteraltime
  1130. {
  1131. pt->dsendtime=dTCounter;
  1132. pt->bRecvOk=false;
  1133. // 遥控
  1134. if(pt->yk_send_flag)
  1135. {
  1136. int i;
  1137. for(i=0;i<SWITCH_NUM_EXT_PUB;i++)
  1138. {
  1139. if(pt->yk_send_flag & (1<<i))
  1140. {
  1141. u16 val;
  1142. u8 v,cot,ti,dat[8];
  1143. LINKYK_DEF *yk = &g_lnk_yk[i];
  1144. v=yk->data[IECLINK_YK_SND].v;
  1145. cot=yk->data[IECLINK_YK_SND].cot;
  1146. ti=yk->data[IECLINK_YK_SND].ti;
  1147. if(v&0x80) // 遥控选择,遥控撤销,直接回复应答
  1148. {
  1149. if(pt->tyk.yk_st!= YK_STATUS_NONE && pt->tyk.yk_st!= YK_STATUS_TIMEOUT)
  1150. {
  1151. //已经有遥控命令选择或在执行
  1152. cot|=IEC_COT_PN;
  1153. memset(&pt->tyk,0,sizeof(REMOTEYKSTATUS));
  1154. }
  1155. else
  1156. {
  1157. // 记录选择动作
  1158. pt->tyk.yk_st=YK_STATUS_SEL;
  1159. pt->tyk.no=ti;
  1160. pt->tyk.val=(v&0x3f);
  1161. pt->tyk.wMaster=yk->cp_s;
  1162. pt->tyk.dTStart=dTCounter;
  1163. }
  1164. modbus_slave_yk(yk->chnl,ti,cot,v,yk->cp_s,IECLINK_YK_ACK);
  1165. pt->bRecvOk=true;
  1166. }
  1167. else if(cot==IEC_COT_DEACT) // 遥控选择,遥控撤销,直接回复应答
  1168. {
  1169. if(pt->tyk.yk_st!= YK_STATUS_SEL)
  1170. {
  1171. cot|=IEC_COT_PN;
  1172. }
  1173. modbus_slave_yk(yk->chnl,ti,cot,v,yk->cp_s,IECLINK_YK_ACK);
  1174. pt->bRecvOk=true;
  1175. memset(&pt->tyk,0,sizeof(REMOTEYKSTATUS));
  1176. }
  1177. else // 遥控执行
  1178. {
  1179. if((ti != 0xff)
  1180. && ((pt->tyk.yk_st!= YK_STATUS_SEL) // 和遥控选择的数据不对应
  1181. ||(v !=pt->tyk.val)
  1182. ||(yk->cp_s !=pt->tyk.wMaster)
  1183. ||(ti != pt->tyk.no)))
  1184. {
  1185. cot|=IEC_COT_PN;
  1186. modbus_slave_yk(yk->chnl,ti,cot,v,yk->cp_s,IECLINK_YK_ACK);
  1187. pt->bRecvOk=true;
  1188. }
  1189. else
  1190. {
  1191. u8 num=0;
  1192. pt->tyk.yk_st=YK_STATUS_EXE;
  1193. pt->tyk.dTStart=dTCounter;
  1194. if(ti==45)v+=1; // 单点转为双点 2=合 1=分
  1195. if(v==2) //遥控合
  1196. {
  1197. val=pt->ykval_h;
  1198. }
  1199. else
  1200. {
  1201. val=pt->ykval_f;
  1202. }
  1203. if(pt->ykcmd==0x0f||pt->ykcmd==0x10) // 0F和10命令,需增加线圈地址
  1204. {
  1205. dat[0]=(u8)(pt->coiladdr>>8);
  1206. dat[1]=(u8)(pt->coiladdr);
  1207. dat[2]=pt->ykbitbytes; //个数
  1208. dat[3]=(u8)(val>>8);
  1209. dat[4]=(u8)(val>>0);
  1210. num=pt->ykbitbytes+3;
  1211. }
  1212. else
  1213. {
  1214. dat[0]=(u8)(val>>8);
  1215. dat[1]=(u8)(val>>0);
  1216. num=pt->ykbitbytes;
  1217. }
  1218. #ifdef LINK_MODBUS_YK_MERGE
  1219. if(v==2) //遥控合
  1220. {
  1221. modbus_write(pt,(yk->chnl&0x1f),yk->cp_s+1,num,dat);
  1222. }
  1223. else
  1224. {
  1225. modbus_write(pt,(yk->chnl&0x1f),yk->cp_s,num,dat);
  1226. }
  1227. #else
  1228. modbus_write(pt,(yk->chnl&0x1f),yk->cp_s,num,dat);
  1229. #endif
  1230. pt->yksendindex=i; //保存发送 g_lnk_yk 索引
  1231. }
  1232. memset(&pt->tyk,0,sizeof(REMOTEYKSTATUS));
  1233. }
  1234. // 清除标志
  1235. g_lnk_yk[i].flag[IECLINK_YK_SND]=false;
  1236. pt->yk_send_flag &= ~(1<<i);
  1237. }
  1238. }
  1239. }
  1240. else if(pt->cmdnum>0)
  1241. {
  1242. pt->bCurrent++;
  1243. if(pt->bCurrent>=pt->cmdnum)pt->bCurrent=0;
  1244. modbus_read(pt,pt->bCurrent);
  1245. }
  1246. }
  1247. if(pt->tyk.yk_st==YK_STATUS_SEL)
  1248. {
  1249. if(dTCounter- pt->tyk.dTStart>=tRunPara.dYKTime)//遥控选择超时
  1250. {
  1251. memset(&pt->tyk,0,sizeof(REMOTEYKSTATUS));
  1252. // 置遥控超时状态,方便用户查看
  1253. pt->tyk.yk_st = YK_STATUS_TIMEOUT;
  1254. }
  1255. }
  1256. }
  1257. /**************************endfile****************************************/