protocol.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: protocol.c
  4. 文件版本: 01.01
  5. 创建作者: xxxxxx
  6. 创建日期: 2015-5-5
  7. 功能说明: 规约层实现文件
  8. -------------------
  9. - APP层 -
  10. -------------------
  11. - 规约层 -
  12. -------------------
  13. - 通道层 -
  14. -------------------
  15. - 驱动层 -
  16. -------------------
  17. 其它说明:
  18. 修改记录:
  19. */
  20. #include "head.h"
  21. #include "myconf.h"
  22. #include "channel.h"
  23. #include "protocol.h"
  24. //一个帧的缓冲区大小
  25. #define FRM_BUF_SIZE 256
  26. //帧缓冲区个数
  27. #define MAX_BUF_SIZE 8
  28. //1秒计数值
  29. #define PROTOCOL_TIMEOUT 1*USTIMER_SEC
  30. //缓冲区数据结构
  31. struct protocol_buf{
  32. unsigned char cTypeCounter;
  33. unsigned char cLenth; //长度
  34. unsigned char cCnt;
  35. unsigned char src_addr;
  36. unsigned char dst_addr;
  37. unsigned char sum;
  38. unsigned char arrBuf[FRM_BUF_SIZE];
  39. };
  40. //全局信息
  41. struct protocol_info{
  42. struct protocol_buf txbuf[MAX_BUF_SIZE];
  43. struct protocol_buf rxbuf[MAX_BUF_SIZE];
  44. unsigned char tx_head;
  45. unsigned char tx_tail;
  46. unsigned char rx_head;
  47. unsigned char rx_tail;
  48. uint32_t tm; //接收超时参照时间点, 如果超过1秒没有数据,则认为帧结束
  49. T_channel *p_chan;
  50. int recvOK; //在半双工的情况下,recvOK=1表示接受一个完整的数据帧,recvOK=0表示没有收到完整的帧或数据
  51. };
  52. struct protocol_info g_info[PROTOCOL_CHNS];
  53. static int g_chan_cnt = 0; //已经使用的通道数
  54. /******************************************************************************
  55. 函数名称: protocol_reset
  56. 函数版本: 01.01
  57. 创建作者: xxxxxx
  58. 创建日期: 2015-05-05
  59. 函数说明: 解包复位处理
  60. 参数说明:
  61. p_info:全局信息指针
  62. 返回值: 无
  63. 修改记录:
  64. */
  65. static void protocol_reset(struct protocol_info *p_info)
  66. {
  67. p_info->rxbuf[p_info->rx_head].cTypeCounter = 0;
  68. p_info->rxbuf[p_info->rx_head].cCnt = 0;
  69. p_info->rxbuf[p_info->rx_head].sum = 0;
  70. p_info->recvOK = 1; //接收完成数据
  71. }
  72. /******************************************************************************
  73. 函数名称: protocol_unpacket
  74. 函数版本: 01.01
  75. 创建作者: xxxxxx
  76. 创建日期: 2015-05-05
  77. 函数说明: 解包处理
  78. 参数说明:
  79. p_info:全局信息指针
  80. byRevData: 接收的数据
  81. 返回值: 无
  82. 修改记录:
  83. */
  84. static void protocol_unpacket(struct protocol_info *p_info, unsigned char byRevData)
  85. {
  86. //将数据放到缓冲区
  87. p_info->rxbuf[p_info->rx_head].arrBuf[p_info->rxbuf[p_info->rx_head].cCnt++]= byRevData;
  88. //逐步检查帧的合法性: 启动字符(0x68)+长度+长度+启动字符(0x68)+数据+校验和+结束字符
  89. switch(p_info->rxbuf[p_info->rx_head].cTypeCounter)
  90. {
  91. case 0: //检查帧头.第一个启动字符
  92. if(byRevData==0x68)
  93. {
  94. p_info->rxbuf[p_info->rx_head].cTypeCounter=1;
  95. }
  96. else
  97. {
  98. //解包复位
  99. protocol_reset(p_info);
  100. }
  101. break;
  102. case 1: //第一个长度
  103. p_info->rxbuf[p_info->rx_head].cTypeCounter=2;
  104. p_info->rxbuf[p_info->rx_head].cLenth = byRevData;
  105. break;
  106. case 2: //第二个长度
  107. if(p_info->rxbuf[p_info->rx_head].cLenth==byRevData)
  108. {
  109. p_info->rxbuf[p_info->rx_head].cTypeCounter=3;
  110. p_info->rxbuf[p_info->rx_head].cLenth = byRevData+4;
  111. }
  112. else
  113. {
  114. //解包复位
  115. protocol_reset(p_info);
  116. }
  117. break;
  118. case 3: //第二个启动字符
  119. if(byRevData==0x68)
  120. {
  121. p_info->rxbuf[p_info->rx_head].cTypeCounter=4;
  122. p_info->rxbuf[p_info->rx_head].sum=0;
  123. }
  124. else
  125. {
  126. //解包复位
  127. protocol_reset(p_info);
  128. }
  129. break;
  130. case 4: //计算校验和,如果数据读取完毕,下一步进行校验和比较
  131. p_info->rxbuf[p_info->rx_head].sum+=byRevData;
  132. if(p_info->rxbuf[p_info->rx_head].cCnt>=p_info->rxbuf[p_info->rx_head].cLenth)
  133. {
  134. p_info->rxbuf[p_info->rx_head].cTypeCounter=5;
  135. }
  136. break;
  137. case 5: //比较校验和
  138. if(p_info->rxbuf[p_info->rx_head].sum==byRevData)
  139. {
  140. p_info->rxbuf[p_info->rx_head].cTypeCounter=6;
  141. }
  142. else
  143. {
  144. //解包复位
  145. protocol_reset(p_info);
  146. }
  147. break;
  148. case 6:
  149. //缓冲区未满
  150. if(((p_info->rx_head+1) & (MAX_BUF_SIZE - 1)) != p_info->rx_tail)
  151. {
  152. //调整缓冲区下标
  153. p_info->rx_head = (p_info->rx_head+1) & (MAX_BUF_SIZE - 1);
  154. }
  155. // else
  156. {
  157. //缓冲区满,丢弃该帧数据
  158. //解包复位
  159. protocol_reset(p_info);
  160. }
  161. // 唤醒主循环
  162. mainloop_wakeup();
  163. break;
  164. default:
  165. //解包复位
  166. protocol_reset(p_info);
  167. break;
  168. }
  169. }
  170. /******************************************************************************
  171. 函数名称: protocol_init
  172. 函数版本: 01.01
  173. 创建作者: xxxxxx
  174. 创建日期: 2015-05-05
  175. 函数说明: 初始化协议
  176. 参数说明:
  177. 返回值: 无
  178. 修改记录:
  179. */
  180. void protocol_init(void)
  181. {
  182. int i=0;
  183. g_chan_cnt = 0;
  184. memset(g_info, 0, sizeof(g_info));
  185. //初始化假设已经接收到数据
  186. for(i=0;i<PROTOCOL_CHNS;i++)
  187. {
  188. g_info[i].recvOK=1;
  189. }
  190. }
  191. /******************************************************************************
  192. 函数名称: protocol_packet
  193. 函数版本: 01.01
  194. 创建作者: xxxxxx
  195. 创建日期: 2015-05-05
  196. 函数说明: 协议组包函数
  197. 参数说明:
  198. src: 源数据
  199. count: 源数据长度
  200. srcaddr: 源地址
  201. dstaddr: 目标地址
  202. dst: 组包后的数据
  203. 返回值: 返回组包后的长度
  204. 修改记录:
  205. */
  206. int protocol_packet(unsigned char *src, int count, unsigned char srcaddr, unsigned char dstaddr, unsigned char *dst)
  207. {
  208. unsigned char i = 0;
  209. unsigned char checksum = 0;
  210. unsigned char len = (unsigned char)count;
  211. unsigned char *p=dst;
  212. *p++ = 0x68;
  213. *p++ = len;
  214. *p++ = len;
  215. *p++ = 0x68;
  216. memcpy(p, src, count);
  217. p = &dst[4];
  218. for(i=0; i<len; i++)
  219. {
  220. checksum += *p++;
  221. }
  222. *p++ = checksum;
  223. *p = 0x80 | (srcaddr << 3) | dstaddr;
  224. return (int)(len + 6);
  225. }
  226. /******************************************************************************
  227. 函数名称: protocol_add_chan
  228. 函数版本: 01.01
  229. 创建作者: xxxxxx
  230. 创建日期: 2015-05-05
  231. 函数说明: 绑定一个通道.每个通道都可以使用该规约
  232. 参数说明:
  233. h_obj: 通道指针
  234. 返回值: 成功返回0, 失败返回-1.
  235. 修改记录:
  236. */
  237. int protocol_add_chan(T_channel *h_obj)
  238. {
  239. //检查通道是否已经用完
  240. if(g_chan_cnt >= PROTOCOL_CHNS)
  241. {
  242. return -1;
  243. }
  244. //通道指针
  245. g_info[g_chan_cnt].p_chan = h_obj;
  246. //通道号
  247. g_info[g_chan_cnt].p_chan->no = g_chan_cnt;
  248. //通道计数
  249. g_chan_cnt++;
  250. return 0;
  251. }
  252. /******************************************************************************
  253. 函数名称: protocol_get_oneframe
  254. 函数版本: 01.01
  255. 创建作者: xxxxxx
  256. 创建日期: 2015-05-05
  257. 函数说明: 从通道中获取一帧数据
  258. 参数说明:
  259. h_obj: 通道指针
  260. frm_data: 帧数据
  261. 返回值: 成功返回0, 失败返回负数.
  262. 修改记录:
  263. */
  264. int protocol_get_oneframe(T_channel *h_obj, unsigned char *frm_data)
  265. {
  266. struct protocol_info *p_info = &g_info[h_obj->no];
  267. //检查参数的合法性
  268. if((!h_obj) || (!frm_data))
  269. {
  270. return -1;
  271. }
  272. //接收缓冲区没有数据
  273. if(p_info->rx_head == p_info->rx_tail)
  274. {
  275. return -2;
  276. }
  277. //拷贝数据
  278. memcpy(frm_data, p_info->rxbuf[p_info->rx_tail].arrBuf, p_info->rxbuf[p_info->rx_tail].arrBuf[1]+6);
  279. p_info->rx_tail = (p_info->rx_tail+1) & (MAX_BUF_SIZE - 1);
  280. return 0;
  281. }
  282. /******************************************************************************
  283. 函数名称: protocol_put_oneframe
  284. 函数版本: 01.01
  285. 创建作者: xxxxxx
  286. 创建日期: 2015-05-05
  287. 函数说明: 写一帧数据到通道中
  288. 参数说明:
  289. h_obj: 通道指针
  290. frm_data: 帧数据
  291. count: 帧数据长度
  292. 返回值: 成功返回0, 失败返回负数.
  293. 修改记录:
  294. */
  295. int protocol_put_oneframe(T_channel *h_obj, unsigned char *frm_data, int count)
  296. {
  297. struct protocol_info *p_info = &g_info[h_obj->no];
  298. //检查参数的合法性
  299. if((!h_obj) || (!frm_data) || (count==0))
  300. {
  301. return -1;
  302. }
  303. //缓冲去满
  304. if(((p_info->tx_head+1) & (MAX_BUF_SIZE - 1)) == p_info->tx_tail)
  305. {
  306. return -2;
  307. }
  308. //拷贝数据到发送缓冲区
  309. memcpy(p_info->txbuf[p_info->tx_head].arrBuf, frm_data, count);
  310. //要发送的字节总数
  311. p_info->txbuf[p_info->tx_head].cLenth = count;
  312. //已经发送的字节数
  313. p_info->txbuf[p_info->tx_head].cCnt = 0;
  314. //调整发送缓冲区的下标
  315. p_info->tx_head = (p_info->tx_head+1) & (MAX_BUF_SIZE - 1);
  316. return 0;
  317. }
  318. /******************************************************************************
  319. 函数名称: protocol_unpacket_task
  320. 函数版本: 01.01
  321. 创建作者: xxxxxx
  322. 创建日期: 2015-05-05
  323. 函数说明: 规约处理任务
  324. 参数说明:
  325. 返回值: 无
  326. 修改记录:
  327. */
  328. void protocol_proc_task(s8 chnl)
  329. {
  330. int i = 0;
  331. int ret = 0;
  332. char ch = 0;
  333. unsigned char cLenth=0; //长度
  334. unsigned char cCnt=0;
  335. unsigned char *p = NULL;
  336. for(i=0; i<g_chan_cnt; i++)
  337. {
  338. //从通道读取数据
  339. ret = channel_read(g_info[i].p_chan, &ch, 1);
  340. //有数据
  341. if(ret > 0)
  342. {
  343. //解包
  344. protocol_unpacket(&g_info[i], (unsigned char)ch);
  345. //接收超时参考点
  346. g_info[i].tm = ustimer_get_origin();
  347. }
  348. else
  349. {
  350. //超时无数据
  351. if(ustimer_get_duration(g_info[i].tm) >= PROTOCOL_TIMEOUT)
  352. {
  353. //解包复位
  354. protocol_reset(&g_info[i]);
  355. //接收超时参考点
  356. g_info[i].tm = ustimer_get_origin();
  357. }
  358. }
  359. //发送缓冲区有帧数据
  360. if(g_info[i].tx_head != g_info[i].tx_tail)
  361. {
  362. if(g_info[i].p_chan->halfduplex)
  363. {
  364. if(!g_info[i].recvOK)
  365. {
  366. continue;
  367. }
  368. }
  369. //数据长度
  370. cLenth = g_info[i].txbuf[g_info[i].tx_tail].cLenth;
  371. //已经发送的字节数
  372. cCnt= g_info[i].txbuf[g_info[i].tx_tail].cCnt;
  373. //要发送的数据首地址
  374. p=&g_info[i].txbuf[g_info[i].tx_tail].arrBuf[cCnt];
  375. //本次需要发送的字节数
  376. cCnt = cLenth - cCnt;
  377. //还有数据要发送
  378. if(cCnt > 0)
  379. {
  380. // 在发送第一个字节前,将485发送允许
  381. if(g_info[i].txbuf[g_info[i].tx_tail].cCnt == 0)
  382. {
  383. RS_Send_Enable(chnl);
  384. }
  385. //发送数据
  386. ret = channel_write(g_info[i].p_chan, (const char *)p, cCnt);
  387. //发送出去了
  388. if(ret > 0)
  389. {
  390. //计算发送了多少字节
  391. g_info[i].txbuf[g_info[i].tx_tail].cCnt += (unsigned char)ret;
  392. #if 0
  393. //如果数据发送完毕,则调整发送缓冲区的下标
  394. if(g_info[i].txbuf[g_info[i].tx_tail].cCnt == g_info[i].txbuf[g_info[i].tx_tail].cLenth)
  395. {
  396. //调整发送缓冲区的下标
  397. g_info[i].tx_tail = (g_info[i].tx_tail+1) & (MAX_BUF_SIZE - 1);
  398. g_info[i].recvOK=0; //置没有接收数据
  399. }
  400. #endif
  401. }
  402. }
  403. //如果数据发送完毕,则调整发送缓冲区的下标
  404. #if defined (CPU_AM335X) || defined (CPU_FUXI)
  405. else
  406. #else
  407. else if(MCF_UART_USR(chnl) & MCF_UART_USR_TXEMP)
  408. #endif
  409. {
  410. RS_Recv_Enable(chnl);
  411. //调整发送缓冲区的下标
  412. g_info[i].tx_tail = (g_info[i].tx_tail+1) & (MAX_BUF_SIZE - 1);
  413. g_info[i].recvOK=0; //置没有接收数据
  414. }
  415. }
  416. }
  417. }