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. */
  181. void protocol_init(void)
  182. {
  183. int i=0;
  184. g_chan_cnt = 0;
  185. memset(g_info, 0, sizeof(g_info));
  186. //初始化假设已经接收到数据
  187. for(i=0;i<PROTOCOL_CHNS;i++)
  188. {
  189. g_info[i].recvOK=1;
  190. }
  191. }
  192. /******************************************************************************
  193. 函数名称: protocol_packet
  194. 函数版本: 01.01
  195. 创建作者: xxxxxx
  196. 创建日期: 2015-05-05
  197. 函数说明: 协议组包函数
  198. 参数说明:
  199. src: 源数据
  200. count: 源数据长度
  201. srcaddr: 源地址
  202. dstaddr: 目标地址
  203. dst: 组包后的数据
  204. 返回值: 返回组包后的长度
  205. 修改记录:
  206. */
  207. int protocol_packet(unsigned char *src, int count, unsigned char srcaddr, unsigned char dstaddr, unsigned char *dst)
  208. {
  209. unsigned char i = 0;
  210. unsigned char checksum = 0;
  211. unsigned char len = (unsigned char)count;
  212. unsigned char *p=dst;
  213. *p++ = 0x68;
  214. *p++ = len;
  215. *p++ = len;
  216. *p++ = 0x68;
  217. memcpy(p, src, count);
  218. p = &dst[4];
  219. for(i=0; i<len; i++)
  220. {
  221. checksum += *p++;
  222. }
  223. *p++ = checksum;
  224. *p = 0x80 | (srcaddr << 3) | dstaddr;
  225. return (int)(len + 6);
  226. }
  227. /******************************************************************************
  228. 函数名称: protocol_add_chan
  229. 函数版本: 01.01
  230. 创建作者: xxxxxx
  231. 创建日期: 2015-05-05
  232. 函数说明: 绑定一个通道.每个通道都可以使用该规约
  233. 参数说明:
  234. h_obj: 通道指针
  235. 返回值: 成功返回0, 失败返回-1.
  236. 修改记录:
  237. */
  238. int protocol_add_chan(T_channel *h_obj)
  239. {
  240. //检查通道是否已经用完
  241. if(g_chan_cnt >= PROTOCOL_CHNS)
  242. {
  243. return -1;
  244. }
  245. //通道指针
  246. g_info[g_chan_cnt].p_chan = h_obj;
  247. //通道号
  248. g_info[g_chan_cnt].p_chan->no = g_chan_cnt;
  249. //通道计数
  250. g_chan_cnt++;
  251. return 0;
  252. }
  253. /******************************************************************************
  254. 函数名称: protocol_get_oneframe
  255. 函数版本: 01.01
  256. 创建作者: xxxxxx
  257. 创建日期: 2015-05-05
  258. 函数说明: 从通道中获取一帧数据
  259. 参数说明:
  260. h_obj: 通道指针
  261. frm_data: 帧数据
  262. 返回值: 成功返回0, 失败返回负数.
  263. 修改记录:
  264. */
  265. int protocol_get_oneframe(T_channel *h_obj, unsigned char *frm_data)
  266. {
  267. struct protocol_info *p_info = &g_info[h_obj->no];
  268. //检查参数的合法性
  269. if((!h_obj) || (!frm_data))
  270. {
  271. return -1;
  272. }
  273. //接收缓冲区没有数据
  274. if(p_info->rx_head == p_info->rx_tail)
  275. {
  276. return -2;
  277. }
  278. //拷贝数据
  279. memcpy(frm_data, p_info->rxbuf[p_info->rx_tail].arrBuf, p_info->rxbuf[p_info->rx_tail].arrBuf[1]+6);
  280. p_info->rx_tail = (p_info->rx_tail+1) & (MAX_BUF_SIZE - 1);
  281. return 0;
  282. }
  283. /******************************************************************************
  284. 函数名称: protocol_put_oneframe
  285. 函数版本: 01.01
  286. 创建作者: xxxxxx
  287. 创建日期: 2015-05-05
  288. 函数说明: 写一帧数据到通道中
  289. 参数说明:
  290. h_obj: 通道指针
  291. frm_data: 帧数据
  292. count: 帧数据长度
  293. 返回值: 成功返回0, 失败返回负数.
  294. 修改记录:
  295. */
  296. int protocol_put_oneframe(T_channel *h_obj, unsigned char *frm_data, int count)
  297. {
  298. struct protocol_info *p_info = &g_info[h_obj->no];
  299. //检查参数的合法性
  300. if((!h_obj) || (!frm_data) || (count==0))
  301. {
  302. return -1;
  303. }
  304. //缓冲去满
  305. if(((p_info->tx_head+1) & (MAX_BUF_SIZE - 1)) == p_info->tx_tail)
  306. {
  307. return -2;
  308. }
  309. //拷贝数据到发送缓冲区
  310. memcpy(p_info->txbuf[p_info->tx_head].arrBuf, frm_data, count);
  311. //要发送的字节总数
  312. p_info->txbuf[p_info->tx_head].cLenth = count;
  313. //已经发送的字节数
  314. p_info->txbuf[p_info->tx_head].cCnt = 0;
  315. //调整发送缓冲区的下标
  316. p_info->tx_head = (p_info->tx_head+1) & (MAX_BUF_SIZE - 1);
  317. return 0;
  318. }
  319. /******************************************************************************
  320. 函数名称: protocol_unpacket_task
  321. 函数版本: 01.01
  322. 创建作者: xxxxxx
  323. 创建日期: 2015-05-05
  324. 函数说明: 规约处理任务
  325. 参数说明:
  326. 无
  327. 返回值: 无
  328. 修改记录:
  329. */
  330. void protocol_proc_task(s8 chnl)
  331. {
  332. int i = 0;
  333. int ret = 0;
  334. char ch = 0;
  335. unsigned char cLenth=0; //长度
  336. unsigned char cCnt=0;
  337. unsigned char *p = NULL;
  338. for(i=0; i<g_chan_cnt; i++)
  339. {
  340. //从通道读取数据
  341. ret = channel_read(g_info[i].p_chan, &ch, 1);
  342. //有数据
  343. if(ret > 0)
  344. {
  345. //解包
  346. protocol_unpacket(&g_info[i], (unsigned char)ch);
  347. //接收超时参考点
  348. g_info[i].tm = ustimer_get_origin();
  349. }
  350. else
  351. {
  352. //超时无数据
  353. if(ustimer_get_duration(g_info[i].tm) >= PROTOCOL_TIMEOUT)
  354. {
  355. //解包复位
  356. protocol_reset(&g_info[i]);
  357. //接收超时参考点
  358. g_info[i].tm = ustimer_get_origin();
  359. }
  360. }
  361. //发送缓冲区有帧数据
  362. if(g_info[i].tx_head != g_info[i].tx_tail)
  363. {
  364. if(g_info[i].p_chan->halfduplex)
  365. {
  366. if(!g_info[i].recvOK)
  367. {
  368. continue;
  369. }
  370. }
  371. //数据长度
  372. cLenth = g_info[i].txbuf[g_info[i].tx_tail].cLenth;
  373. //已经发送的字节数
  374. cCnt= g_info[i].txbuf[g_info[i].tx_tail].cCnt;
  375. //要发送的数据首地址
  376. p=&g_info[i].txbuf[g_info[i].tx_tail].arrBuf[cCnt];
  377. //本次需要发送的字节数
  378. cCnt = cLenth - cCnt;
  379. //还有数据要发送
  380. if(cCnt > 0)
  381. {
  382. // 在发送第一个字节前,将485发送允许
  383. if(g_info[i].txbuf[g_info[i].tx_tail].cCnt == 0)
  384. {
  385. RS_Send_Enable(chnl);
  386. }
  387. //发送数据
  388. ret = channel_write(g_info[i].p_chan, (const char *)p, cCnt);
  389. //发送出去了
  390. if(ret > 0)
  391. {
  392. //计算发送了多少字节
  393. g_info[i].txbuf[g_info[i].tx_tail].cCnt += (unsigned char)ret;
  394. #if 0
  395. //如果数据发送完毕,则调整发送缓冲区的下标
  396. if(g_info[i].txbuf[g_info[i].tx_tail].cCnt == g_info[i].txbuf[g_info[i].tx_tail].cLenth)
  397. {
  398. //调整发送缓冲区的下标
  399. g_info[i].tx_tail = (g_info[i].tx_tail+1) & (MAX_BUF_SIZE - 1);
  400. g_info[i].recvOK=0; //置没有接收数据
  401. }
  402. #endif
  403. }
  404. }
  405. //如果数据发送完毕,则调整发送缓冲区的下标
  406. #if defined (CPU_AM335X) || defined (CPU_FUXI)
  407. else
  408. #else
  409. else if(MCF_UART_USR(chnl) & MCF_UART_USR_TXEMP)
  410. #endif
  411. {
  412. RS_Recv_Enable(chnl);
  413. //调整发送缓冲区的下标
  414. g_info[i].tx_tail = (g_info[i].tx_tail+1) & (MAX_BUF_SIZE - 1);
  415. g_info[i].recvOK=0; //置没有接收数据
  416. }
  417. }
  418. }
  419. }