历史上的今天
今天是:2025年06月10日(星期二)
2020年06月10日 | 51单片机实现通讯协议的串口通讯编程
2020-06-10 来源:elecfans
我们以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上一般采取的做法是这样的,将数据存在缓冲区,接收完一帧数据后再转换成相应的数据结构,再进行分析、校验。
总体来说,这种采取状态机实时解析串口通讯数据的方式在一定程序提高了程序运行效率,使软件架构清晰明了,程序可扩展性大,有利于后续开发。
史海拾趣
|
波形显示界面 引导界面 下面把波形和参数的显示添加进去就可以了,另外一个网友已经做好了,只要把代码合起来这一块就差不多了。 按键也应该快要完成了。模拟通道基本达到预订的效果,昨天休息把两个CPU的通讯协议文本也给做出来了。根 ...… 查看全部问答> |
|
今天群里有人发了一个 stm资料链接的帖子 “史上最全stm 资料链接,建议将此网页加入收藏夹 http://www.stmsky.com/bbs/viewthread.php?tid=2103&extra=page%3D1 我一看 果然所说不虚 太强了 研讨会资料 pc软件 &nbs ...… 查看全部问答> |
|
如题,想研究下更深入的技术. 为提高代码的安全性,如何将程序封装到库文件中呢? 库接口怎么书写,怎么导出,怎么调用? 请高人指教,最好能提供例子.… 查看全部问答> |
|
驱动开发:PCI moden 驱动,多卡工作,求资料.... moden:Conexant CX11252 我是新手,刚转作驱动.....希望高手能提供一些资料,关于moden驱动的开发,给些例子什么的.我想在VC6.0 ddk 下开发..… 查看全部问答> |
|
各位大哥: 我的网卡“资源”选项内容如下:“内存范围 EE000000-EE000FFF, 输入/输出范围 C000-C03F 中断请求 11” 请问这样的状况能断定操作系统采用的分别编址模式吗?… 查看全部问答> |
|
在使用STM8S的FWLIB的时候,发现ADC1和USART2不能编译,察看了一下说明文档,有的能够使用在STM8S-32K中,而有的能使用在STM8S-128K中,怀疑ADC1和USART2就是因为只能使用在STM8S-32K中,所以不能编译了。想问一下,这里的32K和128K的区别在于 ...… 查看全部问答> |
|
修改JOYSTICKMOUSE发送数据,前4字节正确后4错误 各位大大,我想问一下,我想修改JOYSTICK MOUSE程序,源程序是一次发送4字节,我想改为发送8字节,可是改完后抓包发现发送的前4个字节是正确的,后四个自己却是错误的,请问为什么? 修改的地方:SetEPTxCount(ENDP1, 8); UserToPMABufferC ...… 查看全部问答> |




