协议解析-串口协议解析
#define MU_IN_BF_LEN (150)
#define MU_OUT_BF_LEN (150)
uint8_t inbuf[MU_IN_BF_LEN]={0}; //用于保存:从RX中断缓冲buffer中读出的数据
uint8_t outbuf[MU_OUT_BF_LEN]={0};//用于保存:提取出的一个完整帧
#define UART1_RX_RINGBUF_LEN (250)
static uint8_t uart1_rx_ringbuf[UART1_RX_RINGBUF_LEN]={0};
static struct rt_ringbuffer uart1_rx_ringbuffer_controller={0};
#define UART1_TX_RINGBUF_LEN (250)
static uint8_t uart1_tx_ringbuf[UART1_TX_RINGBUF_LEN]={0};
static struct rt_ringbuffer uart1_tx_ringbuffer_controller={0};
int init_uart1_link(void)
{
rt_ringbuffer_init(&uart1_rx_ringbuffer_controller,
uart1_rx_ringbuf,
UART1_RX_RINGBUF_LEN);
rt_ringbuffer_init(&uart1_tx_ringbuffer_controller,
uart1_tx_ringbuf,
UART1_TX_RINGBUF_LEN);
uart1_send_state=UART1_SEND_IDLE;
return 0;
}
/*
direct : 0->left move(low bytes out) ,1->right move(high bytes out)
len : move len */
void buffShift(unsigned char *buf,int bufLen,unsigned char direct,int moveLen)
{
int i=0;
if(direct==0)
{//left move
for(i=0;i<bufLen;i++)
{
if(i+moveLen>=bufLen)
{
buf[i]=0;
}
else
{
buf[i]=buf[i+moveLen];
}
}
}
else
{//right move
for(i=bufLen-1;i>=0;i--)
{
if(i-moveLen<0)
{
buf[i]=0;
}
else
{
buf[i]=buf[i-moveLen];
}
}
}
}
/*
start feed at buf[StartFeedAddr],StartFeedAddr++, total feedLen Bytes,
cycle loop mode
return :the real feed bytes ,should not over the DstbufMax;
*/
uint16_t buffFeed(unsigned char *Dstbuf,
unsigned char *Srcbuf,
uint16_t StartFeedAddr,
uint16_t feedLen,
uint16_t DstbufMax
)
{
uint16_t i=0;
for(i=0;i<feedLen;i++)
{
Dstbuf[StartFeedAddr+i]=Srcbuf[i];
if(StartFeedAddr+i>=DstbufMax)
{
return i;
}
}
return 0;
}
/*
brief: write one byte to the rx linkbuf
input:
databyte: UART1 rx reg data
return:
0:failed
1:success
*/
rt_inline int uart1_wr_rx_link_buffer(uint8_t *buf, int len)
{
//return rt_ringbuffer_putchar(&uart1_rx_ringbuffer_controller,databyte);
return rt_ringbuffer_put(&uart1_rx_ringbuffer_controller,buf,len);
}
/*
brief: read data from rx link buffer
input:
len: bytes amount that want to read out
output:
buf: contain the read out datas
return:
the really read out bytes amount
note:
APP call this function to read UART1 rx datas
*/
int uart1_rd_rx_link_buffer(uint8_t *buf,int len)
{
return rt_ringbuffer_get(&uart1_rx_ringbuffer_controller,buf,(rt_uint16_t)len);
}
static int multi_parse_one_multi_frame(uint8_t *frame,int multi_len)
{
OS_ERR os_err;
int j;
int dlci;
int len;
uint8_t *ptr=NULL;
//InfoPrintf("\r\n\r\n********************解析长度为%d的帧\r\n");
//--------提取出一个完整帧--------------------
#if 0
InfoPrintf("解析长度为%d的帧:",multi_len);
for(j=0;j<multi_len;j++)
InfoPrintf("%02X",frame[j]);
InfoPrintf("\r\n");
for(j=0;j<multi_len;j++)
InfoPrintf("%c",frame[j]);
InfoPrintf("\r\n");
#endif
}
/*
brief: extract one frame from the ringbuffer
input:
buf : wait for extract buf
buf_len: wait buf`s len
output:
outbuf : contain one right extracted multi frame if extract successful
outbuf_len : out buffer len,if >0 : extract one frame ok
return:
-1 : out buf length is error
others : need_shift_out_amount
*/
int multi_extract_one_rx_frame(uint8_t *buf, int inbuf_len,
uint8_t *outbuf,int *outbuf_len,
int outbuf_max_len,
int *remain_len
)
{
enum extract_multi_stp_t ems_extract_step=EMS_SEARCH_HEAD;
int i=0;
uint8_t info_len,outbuf_ptr=0;
uint8_t rx_crc,counting_crc=0;
//uint8_t add_f,ctl_f,len_f=0;
int unuseful_amount=0;
int need_shift_out_amount=0;
//InfoPrintf("当前step=%d\r\n",ems_extract_step);
/* InfoPrintf("内部读出\r\n");
InfoPrintf("当前step=%d\r\n",ems_extract_step);
InfoPrintf("将处理%d个字节:",inbuf_len);
for(i=0;i<inbuf_len;i++)
{
InfoPrintf("%02X",buf[i]);
//PrintHex(buf[i]);
}
InfoPrintf("\r\n");*/
if(outbuf_max_len < 134 || inbuf_len==0)//(134=4+128+1+1) head,addr,control,length,infoMAX...,crc,tail
{
return -1;
}
for(i=0;i<inbuf_len;i++)
{
if((ems_extract_step==EMS_SEARCH_HEAD)&&(buf[i]==EMS_HEAD))
{
info_len=0;
outbuf_ptr=0;
outbuf[outbuf_ptr++]=buf[i];
ems_extract_step=EMS_SEARCH_ADDR_FIELD;
}
else if(ems_extract_step==EMS_SEARCH_ADDR_FIELD)
{
outbuf[outbuf_ptr++]=buf[i];
ems_extract_step=EMS_SEARCH_CTL_FIELD;
//add_f=buf[i];
}
else if(ems_extract_step==EMS_SEARCH_CTL_FIELD)
{
outbuf[outbuf_ptr++]=buf[i];
ems_extract_step=EMS_SEARCH_LEN_FIELD;
//ctl_f=buf[i];
}
else if(ems_extract_step==EMS_SEARCH_LEN_FIELD)
{
outbuf[outbuf_ptr++]=buf[i];
ems_extract_step=EMS_SEARCH_INFO;
//len_f=buf[i];
info_len=buf[i]>>1;
//InfoPrintf("消息体长度=%d\r\n",info_len);
}
else if(ems_extract_step==EMS_SEARCH_INFO)
{
outbuf[outbuf_ptr++]=buf[i];
if(info_len)
{
if(info_len==1)
{
ems_extract_step=EMS_SEARCH_CRC;
}
info_len--;
}
}
else if(ems_extract_step==EMS_SEARCH_CRC)
{
outbuf[outbuf_ptr++]=buf[i];
ems_extract_step=EMS_SEARCH_TAIL;
rx_crc=buf[i];
counting_crc=mux_cal_fcs(outbuf+unuseful_amount+1,3);
//InfoPrintf("校验码=%02X\r\n",counting_crc);
if(rx_crc==counting_crc)// && rx_crc!=0x5F)//0xA9
{
//InfoPrintf("校验码正确=%02X\r\n",counting_crc);
}
else
{
//InfoPrintf("校验码错误,rx=%02X,count=%02X\r\n",rx_crc,counting_crc);
ems_extract_step=EMS_SEARCH_HEAD;
need_shift_out_amount=unuseful_amount+1;//+1:means shift out EMS_HEAD(0xF9)
return need_shift_out_amount;
}
}
else if(ems_extract_step==EMS_SEARCH_TAIL)
{
outbuf[outbuf_ptr++]=buf[i];
if(buf[i]==EMS_TAIL)
{
ems_extract_step=EMS_SEARCH_HEAD;
*outbuf_len=outbuf_ptr;
need_shift_out_amount=unuseful_amount+outbuf_ptr;
return need_shift_out_amount;
}
else
{
//TAIL ERROR
ems_extract_step=EMS_SEARCH_HEAD;
need_shift_out_amount=unuseful_amount+1;//+1:means shift out EMS_HEAD(0xF9)
return need_shift_out_amount;
}
}
else
{//unuseful bytes
unuseful_amount++;
}
}
//all inbuf data has been pro
if(unuseful_amount<inbuf_len)
{
*remain_len=inbuf_len-unuseful_amount;
//InfoPrintf("======分析完毕,存在未完整的有效数据%d字节...=====\r\n",*remain_len);
need_shift_out_amount=unuseful_amount;
return need_shift_out_amount;
}
else
{
*remain_len=0;
//InfoPrintf("======分析完毕,无有效帧=====\r\n");
need_shift_out_amount=inbuf_len;
return need_shift_out_amount;
}
}
//#define multi_pro_rx_data_print
/*
在main()中循环调用此函数:
功能:
读出RX中断的缓冲buffer里的数据,提取完整帧。
提取出完整帧后,剩余的有效数据要保留在inbuf中,下一次从RX中断的缓冲buffer里读出的
数据,将跟在上一次保留的数据后面.
*/
int multi_pro_rx_data(void)
{
int inbuf_len;
int outbuf_len;
int shift_len=0;
static int remain_len=0;//当剩余有效的数据,但未构成一个完整帧,需要下一次从ringbuffer
//读取到后续的数据后,才能构成一个完整帧时,remain_len返回>0,
//其他情况返回 0 !!!!
inbuf_len=uart1_rd_rx_link_buffer(inbuf+remain_len,MU_IN_BF_LEN-remain_len);
if(inbuf_len>0)
{
inbuf_len+=remain_len;//本次读出+上次剩余
#ifdef multi_pro_rx_data_print
InfoPrintf("读取到+上次剩余,共%d字节有效数据:\r\n",inbuf_len);
#endif
while(1)
{
#ifdef multi_pro_rx_data_print
InfoPrintf("待处理%d字节:",inbuf_len);
for(j=0;j<inbuf_len;j++)
{
InfoPrintf("%02X",inbuf[j]);
}
InfoPrintf("=====\r\n");
#endif
outbuf_len=0;
remain_len=0;
shift_len=multi_extract_one_rx_frame( inbuf,inbuf_len,outbuf,&outbuf_len,
MU_OUT_BF_LEN,
&remain_len//>0 表示:剩余不到一个完整帧的数据
//=0 表示:剩余超过一个完整帧的数据 或 剩余0字节
);
if(shift_len>=0)
{
if(outbuf_len>0)
{//提取出完整帧
multi_parse_one_multi_frame(outbuf,outbuf_len);
}
#ifdef multi_pro_rx_data_print
InfoPrintf("左移--%d--字节\r\n",shift_len);
#endif
buffShift(inbuf,MU_IN_BF_LEN,0,shift_len);
inbuf_len=inbuf_len-shift_len;
if(remain_len>0 || inbuf_len<=0)
{
#ifdef multi_pro_rx_data_print
InfoPrintf("处理完毕(剩余%d字节):",remain_len);
for(j=0;j<remain_len;j++)
{
InfoPrintf("%02X",inbuf[j]);
}
InfoPrintf("重新读取...\r\n\r\n\r\n");
#endif
break;
}
else
{
#ifdef multi_pro_rx_data_print
InfoPrintf("左移后,剩余-%d-字节,继续处理...\r\n",inbuf_len);
#endif
}
}
else
{
InfoPrintf("MULTI参数错误!!!!\r\n");
break;
}
}
}
return 0;
}
协议解析-串口协议解析相关推荐
- FPGA解析串口协议帧3.0版本,增加了错误重发功能,提供仿真文件以及源码
FPGA解析串口协议帧已经发布2个版本了,分别如下: 版本1:点击查看版本1 版本1详细介绍了串口协议帧的帧组成和设计思想,但设计粗糙,注释不详细: 版本1:点击查看版本2 版本2优化了代码,添加了详 ...
- UART串口协议基础1
Louis kaly.liu@163.com 串口协议基础 1 串口概述 串口由收发器组成.发送器是通过TxD引脚发送串行数据,接收器是通过RxD引脚接收串行数据. 发送器和接收器都利用了一个移位寄存 ...
- 超详细解析 | 一致性协议算法-2PC、3PC、Paxos、Raft、ZAB、NWR
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 来源:r6d.cn/VMW9 背景 在常见的分布式系统中, ...
- 【网络通信与信息安全】之深入解析HTTP协议的实现和原理
一.计算机网络体系结构分层 计算机网络体系结构分层示例图 计算机网络体系结构说明: 二.TCP/IP 通信传输流 ① TCP/IP 分层管理 TCP/IP 构成 应用层:决定了向用户提供应用服务时通信 ...
- 解析HTTP协议六种请求方法,get,head,put,delete,post有什么区别
转载自 解析HTTP协议六种请求方法,get,head,put,delete,post有什么区别 标准Http协议支持六种请求方法,即: 1.GET 2.POST 3.PUT 4.Delete 5. ...
- 协议簇:TCP 解析:TCP 数据传输
简介 前面,我们分别介绍了 TCP 基础知识以及连接的建立和关闭,以及最重要的 Sequence Number 的概念. 本篇文章,我们来介绍一下 TCP 如何传输数据. 系列文章 协议簇:TCP 解 ...
- 协议簇:TCP 解析: Sequence Number
简介 序列号(Sequence Number) 是 TCP 协议中非常重要的一个概念,以至于不得不专门来学习一下.这篇文章我们就来解开他的面纱. 在 TCP 的设计中,通过TCP协议发送的每个字节都对 ...
- 协议簇:TCP 解析: 连接断开
简介 接前文 协议簇:TCP 解析: 建立连接, 我们这篇文章来看看 TCP 连接断开的过程,也就是众所周知的"四次挥手"的具体流程. 系列文章 协议簇:TCP 解析:基础 协议簇 ...
- 协议簇:TCP 解析: 建立连接
简介 接前文 协议簇:TCP 解析: 基础, 我们这篇文章来看看 TCP 连接建立的过程,也就是众所周知的"三次握手"的具体流程. 系列文章 协议簇:TCP 解析:基础 协议簇:T ...
- 协议簇:TCP 解析: 基础
简介 本文我们将从 RFC 学习一下 RFC793 中描述的 TCP 协议. 这将区别于通常讲解计算机网络书籍中所描述的 TCP. 但他们必然是相统一的,不会互相冲突. 系列文章 协议簇:TCP 解析 ...
最新文章
- IBM中国开发中心吉燕勇: 通过Cloud Data Services打造新型认知计算数据分析云平台...
- 宝典9.2——海量数据的基本处理方法
- [论文泛读]Web服务组合综述相关论文1(3篇)
- iOS 10 之后权限设置
- win10一按右键就闪屏_升级Win10正式版后屏幕一直闪烁正确的解决办法
- Hadoop精华问答 | 关于Hadoop核心技术的精华问答
- mysql置信度支持度,支持度 置信度 提升度
- 关于python列表去重复后按照元列表序列输出
- 64位整数乘法(类快速幂)
- 地址解析协议(ARP)
- 分布式 | zabbix 监控 dble
- CSP内容安全策略基础版
- 手机照片误删怎么找回
- 使用Docker部署Spring-Boot-项目,带劲!
- 微信小程序座位预约,微信小程序实现订座位,餐厅座位预约小程序毕设作品
- 2017年苹果开发者账号申请——注册苹果账号
- 微信小程序之添加文章功能
- MAC Python环境配置
- mysql 存放byte_mysql 存储byte数组
- Glide加载不出图片
热门文章
- ubuntu挂载移动硬盘时提示Unable to mount
- skype在线代码 skype在线代码怎么弄?
- 易语言数字指令编程大全(发送信息代码数据集合)
- asp.net mvc 学习总结
- 马化腾的马氏建议:“小步快跑 快速迭代”
- elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
- 数据可视化--实验三:空间可视化
- linux脚本 加密失效,shell脚本加密(使用shc)
- 关闭 电脑 ctrl +alt +方向键 旋转屏幕快捷键
- Win10 Ctrl+Alt+方向键 屏幕显示翻转解决办法