14719|8

337

帖子

0

TA的资源

裸片初长成(中级)

楼主
 

抛砖引玉----基于51串口通讯编程软件架构剖析 [复制链接]

前言: 串口通讯对于所有的嵌入式工程师十分常见,对于一个与外界交互的系统必须依赖一些手段,比如串口、USB、红外、GPRS之类的数据通讯传输方式。而串口作为一种廉价的短距离可靠的通讯方式得到了广泛应用。 废话少说了,就此打住,进入正题。 本文主要从软件结构上讲解如何在资源比较缺乏的系统上实现通讯协议的串口通讯编程,以及如何优化程序效率,从而使系统更快、更稳定运行。 正文: 我们以51单片机为例。51中一般针对串口通讯编程,通常采取中断接受查询发送的方式。中断函数在接受数据到达时被重复调用,其实是个重复入栈的过程,所以不宜将函数写的太长,函数太长一般会导致栈太深占用系统资源,二是处理时间过长,可能导致通讯出错。为了防止在处理数据过程中不受干扰,通常在处理接受数据前关闭中断,处理完后再开。 通常的的编程方式如下: static void UartInterruptService(void) interrupt 4 { ES = 0; RI = 0; uart_process(SBUF); ES=1; } 下面重点介绍数据处理函数 uart_process(SBUF); 其实很多时候,对于通讯传输的数据处理才是关键,尤其对于设计通讯协议而言。笔者在刚刚做的一个系统上就碰到这样的问题,当系统庞大了,资源十分有限的情况下,数据处理一旦占用资源太多,效率太低将导致系统崩溃而无法运行。 到了这里,很多工程师可能会考虑开个大的缓冲区FIFO将接收到的数据保存在缓冲区,然后对其进行解析、判断进行下一步程序编写,当然这在系统资源比较丰富的情况下是没有问题的,ARM上采取的就是这样的方式。但如何系统庞大呢,留给的资源缺乏则不行。这样做的一个很大缺点必须是将数据帧接收完了才能够判断,降低了效率和运行速度。 其实还有另外的方式,可以采取在每接收一个字节就对其解析,解析完判断转到下一个状态,并将其中的有用数据存储在相应的数据结构中去,可以采取状态机实现。 将状态机设计为两个控制状态,一是串口状态——uart_state ,一是命令类型状态——cmd_state . (1)状态机开始状态:串口状态为CMD_NO (2)接受到STX_CMD,状态变为CMD_START. (3)接下来将自动进入接受命令帧的状态,再开启命令状态的状态机,对发送来的有用数据进行解析,保存,校验等。处理完毕后将uart_state设为CMD_END状态进行下一步的接受完毕判断,将cmd_state设置为初始的NO_CMD状态。 (4)最后进行ETX_CMD判断,判断数据接收是否完毕。 void uart_process(U8 u8) { if(uart_state == CMD_NO) { if(u8 == STX_CMD) { uart_state = CMD_START; } } else if(uart_state == CMD_START) { switch(cmd_state) { case NO_CMD: cmd_state = u8; break; case COST_CMD: //解析存储有用数据到相应数据结构中 //进行CRC校验 …… uart_state = CMD_END; cmd_state = NO_CMD; CRC = 0; break; …… } …… } else if(uart_state == CMD_END) { uart_state = CMD_NO; if(u8 == ETX_CMD) { //接受完毕 //可以考虑抛出一个消息main函数循环中进行响应处理。 } } } 接下来我们要讨论解析后我们数据存储的问题,其实在资源比较足够的情况下或者能够挤出data区的情况下可以考虑用结构体,我们构造好相应结构体,将接收到的数据存储进去,要应用的时候就十分方便。但这也有个矛盾,一般c51定义的结构体都被存储在data区,一般通讯的字节量大空间必然不够,存在一个矛盾,可以采用联合体union进行存储效果会好一点。当然也可以在保存数据时采用定义在xdata区(片外)的buffer来存储。这样在一定程序上优化了程序的执行效率,在程序处理立即抛出消息处理,提高了通讯数据的处理速度。对于通常资源比较丰富的系统,比如ARM上一般采取的做法是这样的,将数据存在缓冲区,接收完一帧数据后再转换成相应的数据结构,再进行分析、校验。 总体来说,这种采取状态机实时解析串口通讯数据的方式在一定程序提高了程序运行效率,使软件架构清晰明了,程序可扩展性大,有利于后续开发。以上是笔者的一点愚见,欢迎指教。
此帖出自51单片机论坛

最新回复

如果外部数据存储区够大,还是喜欢用分层的结构 采用环型缓冲区,中断只负责收数到缓冲区以及从发送缓冲区中取字节数据发送。 这种方式可以将程序分成物理层,链路层,(传输层),应用层等多个独立的层面,方便重用和修改。  详情 回复 发表于 2007-8-29 10:49
点赞 关注
 

回复
举报

337

帖子

0

TA的资源

裸片初长成(中级)

沙发
 

回复:抛砖引玉----基于51串口通讯编程软件架构剖析

自己顶一下
此帖出自51单片机论坛
 
 
 

回复

20

帖子

0

TA的资源

一粒金砂(中级)

板凳
 

回复:抛砖引玉----基于51串口通讯编程软件架构剖析

接收数据的同时,进行数据帧的解析,思路可取 数据接收时,根据数据包的格式进行解析,完全正确时,将有用的数据体存放到待处理的数据区,遇到错误时跳出解析过程,从头开始并将出错信息反馈到上位机。楼主的程序用Case作跳转也许会更直观些,总是if else看多了就晕了。
此帖出自51单片机论坛
 
 
 

回复

337

帖子

0

TA的资源

裸片初长成(中级)

4
 

回复:抛砖引玉----基于51串口通讯编程软件架构剖析

全部用case跳转更好一些,因为当时MCU资源紧张,所以在解析的时候对stx和etx并没有保存…… 直接用一个状态机实现是更好的……
此帖出自51单片机论坛
 
 
 

回复

337

帖子

0

TA的资源

裸片初长成(中级)

5
 

回复:抛砖引玉----基于51串口通讯编程软件架构剖析

看到论坛上很多人因为串口通讯出问题,而且程序结构写的很不好,所以写了这篇东西,希望对大家有用……其实对于51,实现串口通讯协议比ARM要考虑的更多,要求也更高,所以很多程序在ARM上没有问题可能到51上出问题,这个时候可能要思考下自己程序的问题了……说着跑题了……呵呵
此帖出自51单片机论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

6
 

回复:抛砖引玉----基于51串口通讯编程软件架构剖析

串口用 状态机 比较好
此帖出自51单片机论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

7
 

回复:抛砖引玉----基于51串口通讯编程软件架构剖析

这种方式容易出现数据丢失 协议上要做一些补充
此帖出自51单片机论坛
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(初级)

8
 

回复:抛砖引玉----基于51串口通讯编程软件架构剖析

关于串口 记得 汽车电子 有过一个比较好的协议 前几天想找来用,没找到, 好久前的贴,用了2131,AVR的,
此帖出自51单片机论坛
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

9
 

回复:抛砖引玉----基于51串口通讯编程软件架构剖析

如果外部数据存储区够大,还是喜欢用分层的结构 采用环型缓冲区,中断只负责收数到缓冲区以及从发送缓冲区中取字节数据发送。 这种方式可以将程序分成物理层,链路层,(传输层),应用层等多个独立的层面,方便重用和修改。
此帖出自51单片机论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表