/****************************************************************************** 版权所有: 文件名称: 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) { 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 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; //置没有接收数据 } } } }