| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485 |
- /******************************************************************************
- 版权所有:
- 文件名称: protocol.c
- 文件版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2015-5-5
- 功能说明: 规约层实现文件
-
- -------------------
- - APP层 -
- -------------------
- - 规约层 -
- -------------------
- - 通道层 -
- -------------------
- - 驱动层 -
- -------------------
-
-
-
- 其它说明:
- 修改记录:
- */
- #include "head.h"
- #include "myconf.h"
- #include "channel.h"
- #include "protocol.h"
- //一个帧的缓冲区大小
- #define FRM_BUF_SIZE 256
- //帧缓冲区个数
- #define MAX_BUF_SIZE 8
- //1秒计数值
- #define PROTOCOL_TIMEOUT 1*USTIMER_SEC
- //缓冲区数据结构
- struct protocol_buf{
- unsigned char cTypeCounter;
- unsigned char cLenth; //长度
- unsigned char cCnt;
- unsigned char src_addr;
- unsigned char dst_addr;
- unsigned char sum;
- unsigned char arrBuf[FRM_BUF_SIZE];
- };
- //全局信息
- struct protocol_info{
- struct protocol_buf txbuf[MAX_BUF_SIZE];
- struct protocol_buf rxbuf[MAX_BUF_SIZE];
- unsigned char tx_head;
- unsigned char tx_tail;
- unsigned char rx_head;
- unsigned char rx_tail;
- uint32_t tm; //接收超时参照时间点, 如果超过1秒没有数据,则认为帧结束
- T_channel *p_chan;
- int recvOK; //在半双工的情况下,recvOK=1表示接受一个完整的数据帧,recvOK=0表示没有收到完整的帧或数据
- };
- struct protocol_info g_info[PROTOCOL_CHNS];
- static int g_chan_cnt = 0; //已经使用的通道数
- /******************************************************************************
- 函数名称: protocol_reset
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2015-05-05
- 函数说明: 解包复位处理
- 参数说明:
- p_info:全局信息指针
- 返回值: 无
- 修改记录:
- */
- static void protocol_reset(struct protocol_info *p_info)
- {
- p_info->rxbuf[p_info->rx_head].cTypeCounter = 0;
- p_info->rxbuf[p_info->rx_head].cCnt = 0;
- p_info->rxbuf[p_info->rx_head].sum = 0;
- p_info->recvOK = 1; //接收完成数据
- }
- /******************************************************************************
- 函数名称: protocol_unpacket
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2015-05-05
- 函数说明: 解包处理
- 参数说明:
- p_info:全局信息指针
- byRevData: 接收的数据
- 返回值: 无
- 修改记录:
- */
- static void protocol_unpacket(struct protocol_info *p_info, unsigned char byRevData)
- {
- //将数据放到缓冲区
- p_info->rxbuf[p_info->rx_head].arrBuf[p_info->rxbuf[p_info->rx_head].cCnt++]= byRevData;
-
- //逐步检查帧的合法性: 启动字符(0x68)+长度+长度+启动字符(0x68)+数据+校验和+结束字符
- switch(p_info->rxbuf[p_info->rx_head].cTypeCounter)
- {
- case 0: //检查帧头.第一个启动字符
- if(byRevData==0x68)
- {
- p_info->rxbuf[p_info->rx_head].cTypeCounter=1;
- }
- else
- {
- //解包复位
- protocol_reset(p_info);
- }
- break;
- case 1: //第一个长度
- p_info->rxbuf[p_info->rx_head].cTypeCounter=2;
- p_info->rxbuf[p_info->rx_head].cLenth = byRevData;
- break;
- case 2: //第二个长度
- if(p_info->rxbuf[p_info->rx_head].cLenth==byRevData)
- {
- p_info->rxbuf[p_info->rx_head].cTypeCounter=3;
- p_info->rxbuf[p_info->rx_head].cLenth = byRevData+4;
- }
- else
- {
- //解包复位
- protocol_reset(p_info);
- }
- break;
- case 3: //第二个启动字符
- if(byRevData==0x68)
- {
- p_info->rxbuf[p_info->rx_head].cTypeCounter=4;
- p_info->rxbuf[p_info->rx_head].sum=0;
- }
- else
- {
- //解包复位
- protocol_reset(p_info);
- }
- break;
- case 4: //计算校验和,如果数据读取完毕,下一步进行校验和比较
- p_info->rxbuf[p_info->rx_head].sum+=byRevData;
- if(p_info->rxbuf[p_info->rx_head].cCnt>=p_info->rxbuf[p_info->rx_head].cLenth)
- {
- p_info->rxbuf[p_info->rx_head].cTypeCounter=5;
- }
- break;
- case 5: //比较校验和
- if(p_info->rxbuf[p_info->rx_head].sum==byRevData)
- {
- p_info->rxbuf[p_info->rx_head].cTypeCounter=6;
- }
- else
- {
- //解包复位
- protocol_reset(p_info);
- }
- break;
- case 6:
-
- //缓冲区未满
- if(((p_info->rx_head+1) & (MAX_BUF_SIZE - 1)) != p_info->rx_tail)
- {
- //调整缓冲区下标
- p_info->rx_head = (p_info->rx_head+1) & (MAX_BUF_SIZE - 1);
- }
- // else
- {
- //缓冲区满,丢弃该帧数据
- //解包复位
- protocol_reset(p_info);
- }
- // 唤醒主循环
- mainloop_wakeup();
-
- break;
- default:
- //解包复位
- protocol_reset(p_info);
- break;
- }
-
- }
- /******************************************************************************
- 函数名称: protocol_init
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2015-05-05
- 函数说明: 初始化协议
- 参数说明:
- 无
- 返回值: 无
- 修改记录:
- */
- void protocol_init(void)
- {
- int i=0;
- g_chan_cnt = 0;
- memset(g_info, 0, sizeof(g_info));
- //初始化假设已经接收到数据
- for(i=0;i<PROTOCOL_CHNS;i++)
- {
- g_info[i].recvOK=1;
- }
- }
- /******************************************************************************
- 函数名称: protocol_packet
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2015-05-05
- 函数说明: 协议组包函数
- 参数说明:
- src: 源数据
- count: 源数据长度
- srcaddr: 源地址
- dstaddr: 目标地址
- dst: 组包后的数据
- 返回值: 返回组包后的长度
- 修改记录:
- */
- int protocol_packet(unsigned char *src, int count, unsigned char srcaddr, unsigned char dstaddr, unsigned char *dst)
- {
- unsigned char i = 0;
- unsigned char checksum = 0;
- unsigned char len = (unsigned char)count;
- unsigned char *p=dst;
-
- *p++ = 0x68;
- *p++ = len;
- *p++ = len;
- *p++ = 0x68;
-
- memcpy(p, src, count);
- p = &dst[4];
-
- for(i=0; i<len; i++)
- {
- checksum += *p++;
- }
-
- *p++ = checksum;
-
- *p = 0x80 | (srcaddr << 3) | dstaddr;
-
- return (int)(len + 6);
- }
- /******************************************************************************
- 函数名称: protocol_add_chan
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2015-05-05
- 函数说明: 绑定一个通道.每个通道都可以使用该规约
- 参数说明:
- h_obj: 通道指针
- 返回值: 成功返回0, 失败返回-1.
- 修改记录:
- */
- int protocol_add_chan(T_channel *h_obj)
- {
- //检查通道是否已经用完
- if(g_chan_cnt >= PROTOCOL_CHNS)
- {
- return -1;
- }
- //通道指针
- g_info[g_chan_cnt].p_chan = h_obj;
- //通道号
- g_info[g_chan_cnt].p_chan->no = g_chan_cnt;
- //通道计数
- g_chan_cnt++;
-
- return 0;
- }
- /******************************************************************************
- 函数名称: protocol_get_oneframe
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2015-05-05
- 函数说明: 从通道中获取一帧数据
- 参数说明:
- h_obj: 通道指针
- frm_data: 帧数据
- 返回值: 成功返回0, 失败返回负数.
- 修改记录:
- */
- int protocol_get_oneframe(T_channel *h_obj, unsigned char *frm_data)
- {
- struct protocol_info *p_info = &g_info[h_obj->no];
-
- //检查参数的合法性
- if((!h_obj) || (!frm_data))
- {
- return -1;
- }
- //接收缓冲区没有数据
- if(p_info->rx_head == p_info->rx_tail)
- {
- return -2;
- }
- //拷贝数据
- memcpy(frm_data, p_info->rxbuf[p_info->rx_tail].arrBuf, p_info->rxbuf[p_info->rx_tail].arrBuf[1]+6);
- p_info->rx_tail = (p_info->rx_tail+1) & (MAX_BUF_SIZE - 1);
-
- return 0;
- }
- /******************************************************************************
- 函数名称: protocol_put_oneframe
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2015-05-05
- 函数说明: 写一帧数据到通道中
- 参数说明:
- h_obj: 通道指针
- frm_data: 帧数据
- count: 帧数据长度
- 返回值: 成功返回0, 失败返回负数.
- 修改记录:
- */
- int protocol_put_oneframe(T_channel *h_obj, unsigned char *frm_data, int count)
- {
- struct protocol_info *p_info = &g_info[h_obj->no];
-
- //检查参数的合法性
- if((!h_obj) || (!frm_data) || (count==0))
- {
- return -1;
- }
- //缓冲去满
- if(((p_info->tx_head+1) & (MAX_BUF_SIZE - 1)) == p_info->tx_tail)
- {
- return -2;
- }
- //拷贝数据到发送缓冲区
- memcpy(p_info->txbuf[p_info->tx_head].arrBuf, frm_data, count);
- //要发送的字节总数
- p_info->txbuf[p_info->tx_head].cLenth = count;
- //已经发送的字节数
- p_info->txbuf[p_info->tx_head].cCnt = 0;
- //调整发送缓冲区的下标
- p_info->tx_head = (p_info->tx_head+1) & (MAX_BUF_SIZE - 1);
-
- return 0;
- }
- /******************************************************************************
- 函数名称: protocol_unpacket_task
- 函数版本: 01.01
- 创建作者: xxxxxx
- 创建日期: 2015-05-05
- 函数说明: 规约处理任务
- 参数说明:
- 无
- 返回值: 无
- 修改记录:
- */
- void protocol_proc_task(s8 chnl)
- {
- int i = 0;
- int ret = 0;
- char ch = 0;
- unsigned char cLenth=0; //长度
- unsigned char cCnt=0;
- unsigned char *p = NULL;
- for(i=0; i<g_chan_cnt; i++)
- {
- //从通道读取数据
- ret = channel_read(g_info[i].p_chan, &ch, 1);
- //有数据
- if(ret > 0)
- {
- //解包
- protocol_unpacket(&g_info[i], (unsigned char)ch);
- //接收超时参考点
- g_info[i].tm = ustimer_get_origin();
- }
- else
- {
- //超时无数据
- if(ustimer_get_duration(g_info[i].tm) >= PROTOCOL_TIMEOUT)
- {
- //解包复位
- protocol_reset(&g_info[i]);
- //接收超时参考点
- g_info[i].tm = ustimer_get_origin();
- }
- }
- //发送缓冲区有帧数据
- if(g_info[i].tx_head != g_info[i].tx_tail)
- {
- if(g_info[i].p_chan->halfduplex)
- {
- if(!g_info[i].recvOK)
- {
- continue;
- }
- }
-
- //数据长度
- cLenth = g_info[i].txbuf[g_info[i].tx_tail].cLenth;
- //已经发送的字节数
- cCnt= g_info[i].txbuf[g_info[i].tx_tail].cCnt;
- //要发送的数据首地址
- p=&g_info[i].txbuf[g_info[i].tx_tail].arrBuf[cCnt];
- //本次需要发送的字节数
- cCnt = cLenth - cCnt;
-
- //还有数据要发送
- if(cCnt > 0)
- {
- // 在发送第一个字节前,将485发送允许
- if(g_info[i].txbuf[g_info[i].tx_tail].cCnt == 0)
- {
- RS_Send_Enable(chnl);
- }
-
-
- //发送数据
- ret = channel_write(g_info[i].p_chan, (const char *)p, cCnt);
- //发送出去了
- if(ret > 0)
- {
- //计算发送了多少字节
- g_info[i].txbuf[g_info[i].tx_tail].cCnt += (unsigned char)ret;
- #if 0
- //如果数据发送完毕,则调整发送缓冲区的下标
- if(g_info[i].txbuf[g_info[i].tx_tail].cCnt == g_info[i].txbuf[g_info[i].tx_tail].cLenth)
- {
- //调整发送缓冲区的下标
- g_info[i].tx_tail = (g_info[i].tx_tail+1) & (MAX_BUF_SIZE - 1);
- g_info[i].recvOK=0; //置没有接收数据
- }
- #endif
- }
- }
- //如果数据发送完毕,则调整发送缓冲区的下标
- #if defined (CPU_AM335X) || defined (CPU_FUXI)
- else
- #else
- else if(MCF_UART_USR(chnl) & MCF_UART_USR_TXEMP)
- #endif
- {
- RS_Recv_Enable(chnl);
- //调整发送缓冲区的下标
- g_info[i].tx_tail = (g_info[i].tx_tail+1) & (MAX_BUF_SIZE - 1);
- g_info[i].recvOK=0; //置没有接收数据
- }
- }
-
- }
-
- }
|