IEC101.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918
  1. #include "IEC101.h"
  2. #include "usart.h"
  3. #include "timer.h"
  4. uint8_t flgDIR, flgPRM, flgFCB = 0, flgFCV, flgACD;
  5. uint8_t LINK_ADDRESS = 0x01; //定义链路地址
  6. uint8_t ProtocolRxBuffer[64] = {0}; //存储主站发过来的命令
  7. uint8_t TxBuffer[64] = {0};
  8. uint8_t TxAppBuffer[64] = {0};
  9. uint8_t RxControlField = 0; //接收到数据中的控制域
  10. uint8_t RxDIR, RxPRM, RxFCB, RxFCV, RxFunctionCode;
  11. uint8_t LastFCB;
  12. uint8_t TxDIR, TxPRM, TxFCB, TxFCV, TxFunctionCode;
  13. TimeStructure NowTimeStruct;
  14. uint16_t LastType;
  15. uint8_t Info[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //开关量数量 0/1/2 跌落 3跌落状态 4温度状态 5 欠压 6/7/8/9 漏保
  16. uint8_t InfoTemp[8]; //温度
  17. uint8_t DataFromGPRSBuffer[128];
  18. uint8_t moduleMaskEn; // 模块故障MASK
  19. /*
  20. ****************************************************************************************************
  21. * 功能描述:初始化链路层参数
  22. * 输入参数:
  23. * 返回参数:
  24. * 说 明:
  25. ****************************************************************************************************
  26. */
  27. void LinkInit(void) {
  28. RxDIR = M2S_DIR; //固定值,从站接收到主站的数据时DIR为0,
  29. RxPRM = 0; //非固定值
  30. TxPRM = 0; //非固定值
  31. RxFCB = 0;
  32. RxFCV = 0;
  33. TxDIR = S2M_DIR; //固定值从站发出数据时DIR为1
  34. }
  35. //此函数用于CheckSum函数之后,即已经判断为有效帧后再校验地址是否正确
  36. //返回SUCCESS地址正确,返回ERROR地址不正确
  37. uint8_t CheckLinkAddress(uint8_t* pBuffer) {
  38. uint16_t LinkAddress = 0;
  39. if (pBuffer[0] == 0x10) {
  40. LinkAddress = (uint16_t)pBuffer[2];
  41. }
  42. else if (pBuffer[0] == 0x68) {
  43. LinkAddress = (uint16_t)pBuffer[5];
  44. }
  45. else {
  46. return ERROR; //链路地址不正确
  47. }
  48. if (LinkAddress == LINK_ADDRESS) {
  49. return SUCCESS; //链路地址正确
  50. }
  51. else {
  52. return ERROR; //链路地址不正确
  53. }
  54. }
  55. /*
  56. ****************************************************************************************************
  57. * 功能描述:
  58. * 输入参数:
  59. * 返回参数:校验和的值
  60. * 说 明:
  61. ****************************************************************************************************
  62. */
  63. uint8_t GetCheckSum(uint8_t* pBuffer) {
  64. uint8_t i;
  65. uint8_t TempSum = 0;
  66. uint8_t DataLength = 0;
  67. if (pBuffer[0] == 0x10)
  68. TempSum = pBuffer[1] + pBuffer[2];
  69. else if (pBuffer[0] == 0x68) {
  70. DataLength = pBuffer[1]; //获取可变帧数据长度
  71. for (i = 0; i < DataLength; i++)
  72. TempSum += pBuffer[i + 4];
  73. }
  74. else
  75. TempSum = 0;
  76. return TempSum;
  77. //////////////////////////////////////////////////////////////////////////
  78. }
  79. /*
  80. ****************************************************************************************************
  81. * 功能描述:
  82. * 输入参数:
  83. * 返回参数:
  84. * 说 明:
  85. ****************************************************************************************************
  86. */
  87. uint8_t CheckError(uint8_t* pBuffer) {
  88. uint8_t Length1, Length2;
  89. if ((pBuffer[0] == 0x68) && (pBuffer[3] == 0x68)) {
  90. //可变帧长
  91. Length1 = pBuffer[1];
  92. Length2 = pBuffer[2];
  93. if (Length1 != Length2)
  94. return 0; //两个长度字节不相等,返回错误
  95. else
  96. //校验和相等且最后一个字节为0x16
  97. if ((GetCheckSum(pBuffer) == pBuffer[4 + Length1]) && (pBuffer[5 + Length1] == 0x16)) {
  98. RxControlField = pBuffer[4]; //帧校验成功后取得控制域数据
  99. return VARIABLE_DATA;
  100. }
  101. else
  102. return 0;
  103. }
  104. /* 固定帧长第一字节和最后字节校验 */
  105. else if ((pBuffer[0] == 0x10) && (pBuffer[5] == 0x16)) {
  106. //检验和是否相等
  107. if (GetCheckSum(pBuffer) == pBuffer[3]) {
  108. RxControlField = pBuffer[1]; //取得控制域数据
  109. return STABLE_DATA;
  110. }
  111. else
  112. return 0;
  113. }
  114. else
  115. //无效帧,丢弃
  116. return 0;
  117. }
  118. /*
  119. ****************************************************************************************************
  120. * 功能描述:
  121. * 输入参数:
  122. * 返回参数:
  123. * 说 明:
  124. ****************************************************************************************************
  125. */
  126. uint8_t Protocol101_RxLink(void) {
  127. RxDIR = (RxControlField >> 7) & 0x01; //取得DIR位
  128. RxPRM = (RxControlField >> 6) & 0x01; //取得PRM位
  129. RxFCB = (RxControlField >> 5) & 0x01; //取得FCB位
  130. RxFCV = (RxControlField >> 4) & 0x01; //取得FCV位
  131. RxFunctionCode = RxControlField & 0x0F; //取得功能码
  132. if ((RxDIR == M2S_DIR) && (RxPRM == 1))
  133. return SUCCESS; //接收标志位判断
  134. else {
  135. // newFrame = 1;
  136. LastFCB = RxFCB;
  137. return ERROR;
  138. }
  139. }
  140. /*
  141. ****************************************************************************************************
  142. * 功能描述:
  143. * 输入参数:
  144. * 返回参数:
  145. * 说 明:
  146. ****************************************************************************************************
  147. */
  148. uint8_t SetTxControlField(uint8_t PRM, uint8_t FCB, uint8_t FCV, uint8_t FuncCode) {
  149. uint8_t Temp = 0;
  150. Temp |= ((S2M_DIR & 0x01) << 7);
  151. Temp |= ((PRM & 0x01) << 6);
  152. Temp |= ((FCB & 0x01) << 5);
  153. Temp |= ((FCV & 0x01) << 4);
  154. Temp |= (FuncCode & 0x0F);
  155. return Temp;
  156. }
  157. void SendStableData(uint8_t PRM, uint8_t FCB, uint8_t FCV, uint8_t FuncCode) {
  158. uint8_t TxCrtlField = 0;
  159. uint8_t CheckSum = 0;
  160. uint8_t FrameData[6] = {0x00};
  161. TxCrtlField = SetTxControlField(PRM, FCB, FCV, FuncCode);
  162. FrameData[0] = 0x10;
  163. FrameData[1] = TxCrtlField;
  164. FrameData[2] = LINK_ADDRESS;
  165. CheckSum = FrameData[1] + FrameData[2];
  166. FrameData[3] = CheckSum;
  167. FrameData[4] = 0x16;
  168. SendData(FrameData, 5); //串口发送
  169. }
  170. #if 0
  171. void SendVariableData( uint8_t PRM, uint8_t FCB, uint8_t FCV, uint8_t FuncCode, uint8_t* pBuffer )
  172. {
  173. ASDU_DataStructure ASDU_DataStruct;
  174. ASDU_DataStruct.TypeID = 100;
  175. ASDU_DataStruct.Qualifier = 1;
  176. ASDU_DataStruct.Reason = 7;
  177. ASDU_DataStruct.ASDU_Address = LINK_ADDRESS;
  178. ASDU_DataStruct.InfoAddress1 = 0x0000;
  179. ASDU_DataStruct.InfoData1 = 0X14;
  180. ASDU_Init( ASDU_DataStruct, TxAppBuffer );
  181. }
  182. #endif
  183. #if 0
  184. /*
  185. ****************************************************************************************************
  186. * 功能描述:
  187. * 输入参数:TxAppLength:应用层数据不为0,指的是ASDU的长度,发送的是可变帧长数据
  188. * pTxBuffer:链路层数据缓存,最后通过物理通道发送出去
  189. * pTxAppBuffer:应用层数据缓冲区,会在应用层将数据转移到pTxBuffer中
  190. * 返回参数:无
  191. * 说 明:
  192. ****************************************************************************************************
  193. */
  194. void Protocol101_TxLink( uint8_t TxAppLength, uint8_t* pTxBuffer, uint8_t* pTxAppBuffer )
  195. {
  196. uint8_t i;
  197. uint8_t TempSum = 0;
  198. uint8_t TxCounter = 0;
  199. //如果应用层数据不为0,则表示发送的是可变帧长数据
  200. if ( TxAppLength != 0 ) {
  201. pTxBuffer[0] = 0x68;
  202. pTxBuffer[1] = TxAppLength + 3;
  203. pTxBuffer[2] = TxAppLength + 3;
  204. pTxBuffer[3] = 0x68;
  205. pTxBuffer[4] = SetTxControlField();
  206. TempSum += pTxBuffer[4];
  207. pTxBuffer[5] = LINK_ADDRESS & 0xff;
  208. TempSum += pTxBuffer[5];
  209. pTxBuffer[6] = ( LINK_ADDRESS >> 8 ) & 0xff;
  210. TempSum += pTxBuffer[6];
  211. TxCounter = 7;
  212. for ( i = 0; i <= TxAppLength - 1; i++ ) {
  213. pTxBuffer[TxCounter] = pTxAppBuffer[i];
  214. TempSum += pTxBuffer[TxCounter++];
  215. }
  216. TempSum &= 0xff;
  217. pTxBuffer[TxCounter++] = TempSum;
  218. pTxBuffer[TxCounter++] = 0x16;
  219. } else {
  220. pTxBuffer[0] = 0x10;
  221. pTxBuffer[1] = GetTxControlField();
  222. pTxBuffer[2] = LINK_ADDRESS & 0xff;
  223. pTxBuffer[3] = ( LINK_ADDRESS >> 8 ) & 0xff;
  224. //计算校验和
  225. for ( i = 1; i < 4; i++ )
  226. TempSum += pTxBuffer[i];
  227. pTxBuffer[4] = TempSum;
  228. pTxBuffer[5] = 0x16;
  229. TxCounter = 6;
  230. }
  231. SendData( pTxBuffer, TxCounter ); //串口发送
  232. }
  233. #endif
  234. uint8_t ASDU_Init(ASDU_DataStructure* ASDU_Struct, uint8_t NumOfInfo, uint8_t* pBuffer) {
  235. uint8_t i = 0;
  236. uint8_t ASDU_Length = 0;
  237. uint8_t ASDU_AddressLow = 0;
  238. uint8_t ASDU_AddressHigh = 0;
  239. ASDU_AddressLow = LINK_ADDRESS;
  240. ASDU_AddressHigh = (LINK_ADDRESS >> 8);
  241. pBuffer[0] = ASDU_Struct->TypeID;
  242. pBuffer[1] = ASDU_Struct->Qualifier;
  243. pBuffer[2] = ASDU_Struct->Reason & 0xff;
  244. pBuffer[3] = ASDU_Struct->Reason >> 8;
  245. pBuffer[4] = ASDU_Struct->ASDU_Address & 0xff;
  246. pBuffer[5] = ASDU_Struct->ASDU_Address >> 8;
  247. pBuffer[6] = ASDU_Struct->InfoAddress & 0xFF;
  248. pBuffer[7] = ASDU_Struct->InfoAddress >> 8;
  249. pBuffer[8] = ASDU_Struct->InfoAddress >> 16;
  250. ASDU_Length = 9;
  251. while (NumOfInfo--) {
  252. pBuffer[i + 9] = ASDU_Struct->InfoData[i];
  253. ASDU_Length += 1;
  254. i++;
  255. }
  256. return ASDU_Length;
  257. }
  258. #if 0
  259. /*
  260. ****************************************************************************************************
  261. * 功能描述:
  262. * 输入参数:
  263. *
  264. *
  265. *
  266. * 返回参数:
  267. * 说 明:
  268. ****************************************************************************************************
  269. */
  270. void Protocol101_TxApp( uint8_t TypeID, uint8_t Qual, uint8_t SendReason, uint8_t Func, uint8_t TxAppLength )
  271. {
  272. TxFunctionCode = Func & 0x0F;
  273. if ( TxAppLength != 0 ) {
  274. TxAppBuffer[0] = TypeID; //类型标识
  275. TxAppBuffer[1] = Qual; //信息体数量
  276. TxAppBuffer[2] = ( SendReason & 0xff );
  277. TxAppBuffer[3] = LINK_ADDRESS & 0xFF; //公共地址低位
  278. TxAppBuffer[4] = ( LINK_ADDRESS >> 8 ) & 0xFF; //公共地址高位
  279. }
  280. Protocol101_TxLink( TxAppLength, TxBuffer, TxAppBuffer );
  281. }
  282. #endif
  283. uint8_t ResponseLinkStatus(void) {
  284. uint8_t Temp = 11;
  285. // txAppLength = 0;
  286. // i = linkState;
  287. Temp &= 0x0F;
  288. switch (Temp) {
  289. case 11:
  290. TxFCB = 0;
  291. SendStableData(0, 0, 0, 11);
  292. // Protocol101_TxApp(0,0,0,0x0b,0); /* 0x0b 链路状态响应 */
  293. break;
  294. case 14:
  295. // Protocol101_TxApp(0,0,0,0x0e,0); /* 0x0e 链路服务未工作 */
  296. break;
  297. default:
  298. // Protocol101_TxApp(0,0,0,0x0f,0); /* 0x0f 链路服务未完成 */
  299. break;
  300. }
  301. // linkState = 0;
  302. return 1;
  303. }
  304. //主站复位远方链路
  305. uint8_t ResponseResetRemoteLink(void) {
  306. SendStableData(0, 0, 0, 0);
  307. return SUCCESS;
  308. }
  309. // 发送1级数据, 掉用函数,查看当前所有的信息
  310. void Data1Frame(){
  311. }
  312. // 发送2级数据, 掉用函数,查看当前所有的信息
  313. void Data2Frame(){
  314. }
  315. // 激活结束帧
  316. void overFrame(){
  317. uint8_t data[32];
  318. data[0] = data[3] = 0x68;
  319. data[1] = data[2] = 0x0C;
  320. data[4] = 0x08;
  321. data[5] = LINK_ADDRESS;
  322. data[6] = LastType >> 8;
  323. data[7] = 0x01;
  324. data[8] = 0x0A;
  325. data[9] = 0x00;
  326. data[10] = data[11] = 0xFF;
  327. data[12] = data[13] = data[14] = 0x00;
  328. if(LastType >> 8 == 0x64)
  329. data[15] = 0x14;// 结束全局召唤
  330. else if(LastType >> 8 == 0x65)
  331. data[15] = 0x05;// 结束召唤电度
  332. uint8_t crc = 0;
  333. for(uint8_t i = 0; i < 12; i++){
  334. crc += data[i + 4];
  335. }
  336. data[16] = crc;
  337. data[17] = 0x16;
  338. SendData(data, 18); //串口发送
  339. }
  340. //确认帧
  341. uint8_t ConfirmFrame(void) {
  342. uint8_t TxCtrlField = 0;
  343. uint8_t CheckSum = 0;
  344. uint8_t FrameData[6] = {0x00};
  345. TxCtrlField |= ((M2S_DIR & 0x01) << 7);
  346. TxCtrlField |= ((0 & 0x01) << 6);
  347. TxCtrlField |= ((1 & 0x01) << 5);
  348. TxCtrlField |= ((0 & 0x01) << 4);
  349. TxCtrlField |= (0 & 0x0F);
  350. FrameData[0] = 0x10;
  351. FrameData[1] = TxCtrlField;
  352. FrameData[2] = LINK_ADDRESS;
  353. CheckSum = FrameData[1] + FrameData[2];
  354. FrameData[3] = CheckSum;
  355. FrameData[4] = 0x16;
  356. SendData(FrameData, 5); //串口发送
  357. }
  358. //确认总召唤
  359. uint8_t ResponseCallAll(void) {
  360. uint8_t i = 0;
  361. uint8_t TxCtrlField = 0;
  362. uint8_t TempCallAllBuf[64] = {0x00};
  363. uint8_t TempASDU_Buf[32] = {0x00};
  364. uint8_t ASDU_Length = 0; // ASDU的长度,并非可变帧长中的L值
  365. // uint8_t SendLength = 0; //可变帧长总长度,最后通过串口发送
  366. uint8_t CheckSum = 0;
  367. ASDU_DataStructure ASDU_DataStruct;
  368. //获取控制域的值
  369. TxCtrlField |= ((M2S_DIR & 0x01) << 7);
  370. TxCtrlField |= ((0 & 0x01) << 6);
  371. TxCtrlField |= ((1 & 0x01) << 5);
  372. TxCtrlField |= ((0 & 0x01) << 4);
  373. TxCtrlField |= (8 & 0x0F);
  374. ASDU_DataStruct.TypeID = 0x64;
  375. ASDU_DataStruct.Qualifier = 0x01;
  376. ASDU_DataStruct.Reason = 0x0007;
  377. ASDU_DataStruct.ASDU_Address = 0xffff;
  378. ASDU_DataStruct.InfoAddress = 0x000000;
  379. ASDU_DataStruct.InfoData[0] = 0x14;
  380. ASDU_Length = ASDU_Init(&ASDU_DataStruct, 1,
  381. TempASDU_Buf); //填充ASDU数据并返回ASDU的长度(此值并非L)
  382. TempCallAllBuf[0] = 0x68;
  383. TempCallAllBuf[1] = ASDU_Length + 2;
  384. TempCallAllBuf[2] = ASDU_Length + 2;
  385. TempCallAllBuf[3] = 0x68;
  386. TempCallAllBuf[4] = TxCtrlField;
  387. TempCallAllBuf[5] = LINK_ADDRESS;
  388. for (i = 0; i < ASDU_Length; i++)
  389. TempCallAllBuf[i + 6] = TempASDU_Buf[i];
  390. for (i = 0; i < (ASDU_Length + 2); i++)
  391. CheckSum += TempCallAllBuf[i + 4]; //计算校验和
  392. TempCallAllBuf[ASDU_Length + 6] = CheckSum;
  393. TempCallAllBuf[ASDU_Length + 7] = 0x16;
  394. SendData(TempCallAllBuf, (ASDU_Length + 8));
  395. return 1;
  396. }
  397. void UpdateDataForCallAll(void) {
  398. uint8_t i = 0;
  399. uint8_t TxCtrlField = 0;
  400. uint8_t TempCallAllBuf[64] = {0x00};
  401. uint8_t TempASDU_Buf[32] = {0x00};
  402. uint8_t ASDU_Length = 0; // ASDU的长度,并非可变帧长中的L值
  403. // uint8_t SendLength = 0; //可变帧长总长度,最后通过串口发送
  404. uint8_t CheckSum = 0;
  405. ASDU_DataStructure ASDU_DataStruct;
  406. //获取控制域的值
  407. TxCtrlField = SetTxControlField(0, 0, 0, 0x00);
  408. ASDU_DataStruct.TypeID = 0x1; //无时标的单点信息
  409. ASDU_DataStruct.Qualifier = 0x8a; //单地址,6个数据
  410. ASDU_DataStruct.Reason = 0x14; //响应总召唤
  411. ASDU_DataStruct.ASDU_Address = LINK_ADDRESS;
  412. ASDU_DataStruct.InfoAddress = 0x0001;
  413. if (moduleMaskEn == 0) { //非屏蔽状态及时发送状态
  414. ASDU_DataStruct.InfoData[0] = Info[0];
  415. ASDU_DataStruct.InfoData[1] = Info[1];
  416. ASDU_DataStruct.InfoData[2] = Info[2];
  417. ASDU_DataStruct.InfoData[3] = Info[3];
  418. ASDU_DataStruct.InfoData[4] = Info[4];
  419. ASDU_DataStruct.InfoData[5] = Info[5];
  420. ASDU_DataStruct.InfoData[6] = Info[6]; //漏保1
  421. ASDU_DataStruct.InfoData[7] = Info[7]; //漏保2
  422. ASDU_DataStruct.InfoData[8] = Info[8]; //漏保3
  423. ASDU_DataStruct.InfoData[9] = Info[9]; //漏保4
  424. }
  425. else {
  426. ASDU_DataStruct.InfoData[0] = 0; //屏蔽状态都按正常处理
  427. ASDU_DataStruct.InfoData[1] = 0; //屏蔽状态都按正常处理
  428. ASDU_DataStruct.InfoData[2] = 0; //屏蔽状态都按正常处理
  429. ASDU_DataStruct.InfoData[3] = 0; //屏蔽状态都按正常处理
  430. ASDU_DataStruct.InfoData[4] = 0; //屏蔽状态都按正常处理
  431. ASDU_DataStruct.InfoData[5] = 0; //屏蔽状态都按正常处理
  432. ASDU_DataStruct.InfoData[6] = 0; //漏保1
  433. ASDU_DataStruct.InfoData[7] = 0; //漏保2
  434. ASDU_DataStruct.InfoData[8] = 0; //漏保3
  435. ASDU_DataStruct.InfoData[9] = 0; //漏保4
  436. }
  437. TxCtrlField = SetTxControlField(0, 0, 0, 0x00);
  438. ASDU_Length = ASDU_Init(&ASDU_DataStruct, 10,
  439. TempASDU_Buf); //填充ASDU数据并返回ASDU的长度(此值并非L)
  440. TempCallAllBuf[0] = 0x68;
  441. TempCallAllBuf[1] = ASDU_Length + 3;
  442. TempCallAllBuf[2] = ASDU_Length + 3;
  443. TempCallAllBuf[3] = 0x68;
  444. TempCallAllBuf[4] = TxCtrlField;
  445. TempCallAllBuf[5] = LINK_ADDRESS & 0xFF;
  446. TempCallAllBuf[6] = LINK_ADDRESS >> 8;
  447. for (i = 0; i < ASDU_Length; i++)
  448. TempCallAllBuf[i + 7] = TempASDU_Buf[i];
  449. for (i = 0; i < (ASDU_Length + 3); i++)
  450. CheckSum += TempCallAllBuf[i + 4]; //计算校验和
  451. TempCallAllBuf[ASDU_Length + 7] = CheckSum;
  452. TempCallAllBuf[ASDU_Length + 8] = 0x16;
  453. SendData(TempCallAllBuf, (ASDU_Length + 9));
  454. }
  455. ///遥测1:温度
  456. void UpdateTempForCallAll(void) {
  457. uint8_t i = 0;
  458. uint8_t TempCallAllBuf[64] = {0x00};
  459. uint8_t TxCtrlField = 0;
  460. ASDU_DataStructure ASDU_DataStruct;
  461. uint8_t TempASDU_Buf[32] = {0x00};
  462. uint8_t ASDU_Length = 0; // ASDU的长度,并非可变帧长中的L值
  463. uint8_t CheckSum = 0;
  464. //获取控制域的值
  465. TxCtrlField = SetTxControlField(0, 0, 0, 0x00);
  466. ASDU_DataStruct.TypeID = 0x15; //类型标示,不带品质因数的遥测量
  467. ASDU_DataStruct.Qualifier = 0x83; //品质因数,单地址3个数据
  468. ASDU_DataStruct.Reason = 0x14; //响应总召
  469. ASDU_DataStruct.ASDU_Address = LINK_ADDRESS;
  470. ASDU_DataStruct.InfoAddress = 0x0001;
  471. if (moduleMaskEn == 0) { //非屏蔽状态及时发送状态
  472. ASDU_DataStruct.InfoData[0] = InfoTemp[0];
  473. ASDU_DataStruct.InfoData[1] = InfoTemp[1];
  474. ASDU_DataStruct.InfoData[2] = InfoTemp[2];
  475. }
  476. else {
  477. ASDU_DataStruct.InfoData[0] = 20; //屏蔽状态都按正常处理
  478. ASDU_DataStruct.InfoData[1] = 20; //屏蔽状态都按正常处理
  479. ASDU_DataStruct.InfoData[2] = 20; //屏蔽状态都按正常处理
  480. }
  481. TxCtrlField = SetTxControlField(0, 0, 0, 0x00);
  482. ASDU_Length = ASDU_Init(&ASDU_DataStruct, 3,
  483. TempASDU_Buf); //填充ASDU数据并返回ASDU的长度(此值并非L)
  484. TempCallAllBuf[0] = 0x68;
  485. TempCallAllBuf[1] = ASDU_Length + 3;
  486. TempCallAllBuf[2] = ASDU_Length + 3;
  487. TempCallAllBuf[3] = 0x68;
  488. TempCallAllBuf[4] = TxCtrlField;
  489. TempCallAllBuf[5] = LINK_ADDRESS & 0xFF;
  490. TempCallAllBuf[6] = LINK_ADDRESS >> 8;
  491. for (i = 0; i < ASDU_Length; i++)
  492. TempCallAllBuf[i + 7] = TempASDU_Buf[i];
  493. for (i = 0; i < (ASDU_Length + 3); i++)
  494. CheckSum += TempCallAllBuf[i + 4]; //计算校验和
  495. TempCallAllBuf[ASDU_Length + 7] = CheckSum;
  496. TempCallAllBuf[ASDU_Length + 8] = 0x16;
  497. SendData(TempCallAllBuf, (ASDU_Length + 9));
  498. }
  499. void EndOfCallAll(void) {
  500. uint8_t i = 0;
  501. uint8_t TxCtrlField = 0;
  502. uint8_t TempCallAllBuf[64] = {0x00};
  503. uint8_t TempASDU_Buf[32] = {0x00};
  504. uint8_t ASDU_Length = 0; // ASDU的长度,并非可变帧长中的L值
  505. // uint8_t SendLength = 0; //可变帧长总长度,最后通过串口发送
  506. uint8_t CheckSum = 0;
  507. ASDU_DataStructure ASDU_DataStruct;
  508. //获取控制域的值
  509. TxCtrlField = SetTxControlField(0, 0, 0, 0x00);
  510. ASDU_DataStruct.TypeID = 0x64;
  511. ASDU_DataStruct.Qualifier = 0x01;
  512. ASDU_DataStruct.Reason = 0x0A;
  513. ASDU_DataStruct.ASDU_Address = LINK_ADDRESS;
  514. ASDU_DataStruct.InfoAddress = 0x0000;
  515. ASDU_DataStruct.InfoData[0] = 0x14;
  516. ASDU_Length = ASDU_Init(&ASDU_DataStruct, 1,
  517. TempASDU_Buf); //填充ASDU数据并返回ASDU的长度(此值并非L)
  518. TempCallAllBuf[0] = 0x68;
  519. TempCallAllBuf[1] = ASDU_Length + 3;
  520. TempCallAllBuf[2] = ASDU_Length + 3;
  521. TempCallAllBuf[3] = 0x68;
  522. TempCallAllBuf[4] = TxCtrlField;
  523. TempCallAllBuf[5] = LINK_ADDRESS & 0xFF;
  524. TempCallAllBuf[6] = LINK_ADDRESS >> 8;
  525. for (i = 0; i < ASDU_Length; i++)
  526. TempCallAllBuf[i + 7] = TempASDU_Buf[i];
  527. for (i = 0; i < (ASDU_Length + 3); i++)
  528. CheckSum += TempCallAllBuf[i + 4]; //计算校验和
  529. TempCallAllBuf[ASDU_Length + 7] = CheckSum;
  530. TempCallAllBuf[ASDU_Length + 8] = 0x16;
  531. SendData(TempCallAllBuf, (ASDU_Length + 9));
  532. }
  533. void GetClockFromServer(TimeStructure* TimeStruct, uint8_t* pBuffer) {
  534. uint16_t Temp = 0;
  535. Temp = pBuffer[15] << 8;
  536. Temp += pBuffer[14];
  537. TimeStruct->MilliSec = (Temp % 1000);
  538. TimeStruct->Sec = (uint8_t)(Temp / 1000);
  539. TimeStruct->Min = pBuffer[16];
  540. TimeStruct->Hour = pBuffer[17];
  541. TimeStruct->Day = pBuffer[18];
  542. TimeStruct->Month = pBuffer[19];
  543. TimeStruct->Year = pBuffer[20];
  544. }
  545. // InfoAdress -- 上单元编号:1~6
  546. // Info -- 上单元状态:0-正常;1-跌落
  547. //*Time -- 时间结构体
  548. void ChangeUpdate(uint16_t InfoAdress, uint8_t Info, TimeStructure* Time) {
  549. uint8_t i;
  550. uint8_t CheckSum = 0;
  551. uint8_t InfoArray[32] = {0x00};
  552. // static uint8_t PreInfo = 0;
  553. // static uint16_t PreInfoAdress = 0;
  554. // if ((PreInfoAdress != InfoAdress) || (PreInfo != Info))
  555. //{
  556. InfoArray[0] = 0x68;
  557. InfoArray[1] = 0x12;
  558. InfoArray[2] = 0x12;
  559. InfoArray[3] = 0x68;
  560. InfoArray[4] = SetTxControlField(1, 0, 0, 3);
  561. InfoArray[5] = LINK_ADDRESS & 0xFF;
  562. InfoArray[6] = LINK_ADDRESS >> 8;
  563. InfoArray[7] = 0x1E; // 0x1E==30,带CP56Time2a时标的单点信息
  564. InfoArray[8] = 0x01;
  565. InfoArray[9] = 0x03; //传送原因:突发
  566. InfoArray[10] = LINK_ADDRESS & 0xFF;
  567. InfoArray[11] = LINK_ADDRESS >> 8;
  568. InfoArray[12] = InfoAdress & 0xFF;
  569. InfoArray[13] = InfoAdress >> 8;
  570. InfoArray[14] = Info;
  571. InfoArray[15] = (uint8_t)((Time->Sec * 1000) + Time->MilliSec);
  572. InfoArray[16] = ((Time->Sec * 1000) + Time->MilliSec) >> 8;
  573. InfoArray[17] = Time->Min;
  574. InfoArray[18] = Time->Hour;
  575. InfoArray[19] = Time->Day;
  576. InfoArray[20] = Time->Month;
  577. InfoArray[21] = Time->Year;
  578. for (i = 0; i < 0x12; i++)
  579. CheckSum += InfoArray[i + 4];
  580. InfoArray[22] = CheckSum;
  581. InfoArray[23] = 0x16;
  582. // PreInfoAdress = InfoAdress;
  583. // PreInfo = Info;
  584. SendData(InfoArray, 24);
  585. // }
  586. }
  587. void TempChangeUpdate(uint16_t InfoAdress, uint8_t Info, TimeStructure* Time) {
  588. uint8_t i;
  589. uint8_t CheckSum = 0;
  590. uint8_t InfoArray[32] = {0x00};
  591. static uint8_t PreInfo = 0;
  592. static uint16_t PreInfoAdress = 0;
  593. if ((PreInfoAdress != InfoAdress) || (PreInfo != Info)) {
  594. InfoArray[0] = 0x68;
  595. InfoArray[1] = 0x12;
  596. InfoArray[2] = 0x12;
  597. InfoArray[3] = 0x68;
  598. InfoArray[4] = SetTxControlField(1, 0, 0, 3);
  599. InfoArray[5] = LINK_ADDRESS & 0xFF;
  600. InfoArray[6] = LINK_ADDRESS >> 8;
  601. InfoArray[7] = 0x23; // 0x23==35,带CP56Time2a时标的测量标量值
  602. InfoArray[8] = 0x01;
  603. InfoArray[9] = 0x03; //传送原因:突发
  604. InfoArray[10] = LINK_ADDRESS & 0xFF;
  605. InfoArray[11] = LINK_ADDRESS >> 8;
  606. InfoArray[12] = InfoAdress & 0xFF;
  607. InfoArray[13] = InfoAdress >> 8;
  608. InfoArray[14] = Info;
  609. InfoArray[15] = (uint8_t)((Time->Sec * 1000) + Time->MilliSec);
  610. InfoArray[16] = ((Time->Sec * 1000) + Time->MilliSec) >> 8;
  611. InfoArray[17] = Time->Min;
  612. InfoArray[18] = Time->Hour;
  613. InfoArray[19] = Time->Day;
  614. InfoArray[20] = Time->Month;
  615. InfoArray[21] = Time->Year;
  616. for (i = 0; i < 0x12; i++)
  617. CheckSum += InfoArray[i + 4];
  618. InfoArray[22] = CheckSum;
  619. InfoArray[23] = 0x16;
  620. PreInfoAdress = InfoAdress;
  621. PreInfo = Info;
  622. SendData(InfoArray, 24);
  623. }
  624. }
  625. void ResponseTimeSynchronous(void) {
  626. uint8_t i = 0;
  627. uint8_t CheckSum = 0;
  628. uint16_t Temp = 0;
  629. uint8_t Time[32] = {0x00};
  630. Temp = NowTimeStruct.Sec * 1000 + NowTimeStruct.MilliSec;
  631. Time[0] = 0x68;
  632. Time[1] = 0x11;
  633. Time[2] = 0x11;
  634. Time[3] = 0x68;
  635. Time[4] = SetTxControlField(0, 0, 0, 0);
  636. Time[5] = LINK_ADDRESS & 0xFF;
  637. Time[6] = LINK_ADDRESS >> 8;
  638. Time[7] = 0x67;
  639. Time[8] = 0x01;
  640. Time[9] = 0x07; //激活确认
  641. Time[10] = LINK_ADDRESS & 0xFF;
  642. Time[11] = LINK_ADDRESS >> 8;
  643. Time[12] = 0x00;
  644. Time[13] = 0x00;
  645. Time[14] = Temp & 0xFF;
  646. Time[15] = Temp >> 8;
  647. Time[16] = NowTimeStruct.Min;
  648. Time[17] = NowTimeStruct.Hour;
  649. Time[18] = NowTimeStruct.Day;
  650. Time[19] = NowTimeStruct.Month;
  651. Time[20] = NowTimeStruct.Year;
  652. for (i = 0; i < 17; i++)
  653. CheckSum += Time[i + 4];
  654. Time[21] = CheckSum;
  655. Time[22] = 0x16;
  656. SendData(Time, 23);
  657. }
  658. /*
  659. 更改这个结构,以实现通过GPRS发送一个数据时
  660. */
  661. uint8_t DataProcess(void) {
  662. uint8_t TempRxFunctionCode = 0;
  663. if (CheckLinkAddress(rx_232_Buffer) == SUCCESS) {
  664. if (CheckError(rx_232_Buffer) == SUCCESS) {
  665. //数据校验通过,可以开始处理数据
  666. if (Protocol101_RxLink() == SUCCESS) {
  667. TempRxFunctionCode = RxFunctionCode;
  668. switch (TempRxFunctionCode) {
  669. case 0: //主站复位远方链路
  670. ResponseResetRemoteLink();
  671. break;
  672. case 1: //主站复位用户进程
  673. break;
  674. case 2: //发送\确认链路测试功能
  675. break;
  676. case 3: //发送\确认用户数据
  677. if ((rx_232_Buffer[7] == 0x64) && ((rx_232_Buffer[14] == 0x14) || (rx_232_Buffer[15] == 0x14))) {
  678. ResponseCallAll();
  679. // SysDelay(1000);
  680. UpdateDataForCallAll();
  681. UpdateTempForCallAll(); // SysDelay(1000);
  682. EndOfCallAll();
  683. }
  684. if (rx_232_Buffer[7] == 0x67) {
  685. // //获取时间
  686. // GetClockFromServer(&NowTimeStruct, ProtocolRxBuffer);
  687. // //将时间写入时钟芯片
  688. // Time_Data[0] = NowTimeStruct.Year;
  689. // Time_Data[1] = NowTimeStruct.Month;
  690. // Time_Data[2] = NowTimeStruct.Day;
  691. // Time_Data[3] = NowTimeStruct.Hour;
  692. // Time_Data[4] = NowTimeStruct.Min;
  693. // Time_Data[5] = NowTimeStruct.Sec;
  694. // //回复确认帧
  695. // ResponseTimeSynchronous();
  696. }
  697. break;
  698. case 4: //发送\无回答用户数据
  699. break;
  700. case 9: //主站请求链路状态
  701. ResponseLinkStatus();
  702. break;
  703. case 10://请求1级用户数据
  704. break;
  705. case 11://请求2级用户数据
  706. break;
  707. }
  708. return SUCCESS;
  709. }
  710. }
  711. }
  712. return ERROR;
  713. }
  714. //判断属于哪条命令
  715. uint8_t IEC_Protocol(uint8_t* pBuffer) {
  716. uint8_t pCheckErrorResult;
  717. pCheckErrorResult = CheckError(pBuffer);
  718. if (pCheckErrorResult == STABLE_DATA) {
  719. if (CheckLinkAddress(pBuffer) == 1) {
  720. if (pBuffer[1] == 0x49) {
  721. ResponseLinkStatus();
  722. }
  723. else if (pBuffer[1] == 0x40) {
  724. ResponseResetRemoteLink();
  725. }
  726. //固定帧
  727. return STABLE_DATA;
  728. }
  729. }
  730. else if (pCheckErrorResult == VARIABLE_DATA) {
  731. if (CheckLinkAddress(pBuffer) == 1) {
  732. if ((pBuffer[7] == 0x64) && (pBuffer[14] == 0x14)) //总召命令
  733. {
  734. ResponseCallAll();
  735. }
  736. //可变帧长
  737. return VARIABLE_DATA;
  738. }
  739. }
  740. else {
  741. return INVALID_DATA;
  742. }
  743. return INVALID_DATA;
  744. }
  745. //////////////////////////////////////////
  746. // //
  747. // 测试功能函数 //
  748. // //
  749. //////////////////////////////////////////
  750. static void test(void const* arg) {
  751. while (1)
  752. {
  753. while(recv_232_done == 0) delay_ms(100);// 轮询到232串口接收到数据
  754. recv_232_done = 0;
  755. // 先判断是固定帧还是可变帧,并储存控制域->RxControlField
  756. if(CheckError(rx_232_Buffer) == STABLE_DATA){// 固定帧
  757. if (CheckLinkAddress(rx_232_Buffer) == SUCCESS) {
  758. if (Protocol101_RxLink() == SUCCESS) { // 取得功能码RxFunctionCode
  759. if (rx_232_Buffer[1] == 0x49)// 请求链路
  760. ResponseLinkStatus();
  761. else if (rx_232_Buffer[1] == 0x40)// 复位链路
  762. ResponseResetRemoteLink();
  763. // 请求1级数据 FCB位每次取反,这里没做FCB的取反判断
  764. else if (rx_232_Buffer[1] == 0x7A || rx_232_Buffer[1] == 0x5A)
  765. {
  766. if(LastType == 0x6406)// 回应总召唤
  767. {
  768. ResponseCallAll();
  769. LastType = 0x6407;
  770. }
  771. else if(LastType == 0x6407)// 回应已有的1级数据
  772. {
  773. uint8_t have_data = 0;//后续调用函数,查看当前所有的数据
  774. if(have_data) Data1Frame();//判断是否还有数据
  775. else overFrame();
  776. }
  777. if(LastType == 0x6506)// 回应电度召唤
  778. {
  779. ResponseCallAll();
  780. LastType = 0x6507;
  781. }
  782. else if(LastType == 0x6507)// 回应已有的1级数据
  783. {
  784. uint8_t have_data = 0;//后续调用函数,查看当前所有的数据
  785. if(have_data) Data2Frame();//判断是否还有数据
  786. else overFrame();
  787. }
  788. }
  789. else if (rx_232_Buffer[1] == 0x7B || rx_232_Buffer[1] == 0x5B)// 请求2级数据 FCB位每次取反
  790. {
  791. uint8_t noneData = 0xE5;
  792. SendData(&noneData,1);
  793. }
  794. }//Protocol101_RxLink
  795. }//CheckLinkAddress
  796. }//CheckError
  797. else if(CheckError(rx_232_Buffer) == VARIABLE_DATA)// 可变帧
  798. {
  799. if (CheckLinkAddress(rx_232_Buffer) == SUCCESS) {
  800. if (Protocol101_RxLink() == SUCCESS) { // 取得功能码RxFunctionCode
  801. if ((rx_232_Buffer[6] == 0x64) && rx_232_Buffer[8] == 0x06 && (rx_232_Buffer[15] == 0x14)) //总召命令激活
  802. {
  803. LastType = 0x6406;
  804. ConfirmFrame();
  805. }
  806. if ((rx_232_Buffer[6] == 0x65) && rx_232_Buffer[8] == 0x06 && (rx_232_Buffer[15] == 0x05)) //总召命令激活
  807. {
  808. LastType = 0x6506;
  809. ConfirmFrame();
  810. }
  811. }//Protocol101_RxLink
  812. }//CheckLinkAddress
  813. }//CheckError
  814. } //while
  815. } //test
  816. void creatTest(void)
  817. {
  818. osThreadDef(IEC, test, osPriorityNormal, 0, configMINIMAL_STACK_SIZE * 4);
  819. osThreadCreate (osThread(IEC), NULL);
  820. }