串口驱动框架的设计思考

嵌入式资讯精选 2021-03-11 00:00

1.本文概述

串口驱动不简单,在实际工作中,往往串口驱动框架的设计都是需要考虑的非常清楚的,特别是实际的项目中。比如基于串口模块功能的协议开发,以及基于串口模块的网络数据收发等等,都是一些值得好好设计和思考的问题。本文目的是总结一下目前我见到过的常用的几种模型,并且对这些设计提出自己的一些想法。

2.简易串口协议设计

简单的串口的使用就是收发数据,当串口数据到来后,通过中断通知,拷贝到一个内存固定数组中,下次协议需要处理的时候,直接从该数组中去取数据。

这种设计的思维逻辑是比较理想化的模型,这种模型的思考主要是主从设备的考虑,按照下面的逻辑来进行:

1.主机发送数据到模块

2.等待一定时间后,模块回复数据给主机

3.此时MCU会通过串口中断接收到一帧数据,然后拷贝到固定的数组中

4.MCU去处理固定数组中的数据,然后清空数组

以上的设计从原理上没问题,似乎没有任何漏洞。但是实际上,真实设备的通信往往不会那么完美,会出现以下的情况:

1.模块发过来的数据,可能有断帧的情况,明明模块只需要一帧回复就可以,但是因为一些原因导致程序分为前后两帧数据发过来,这样导致第二帧覆盖了数据,导致数据不准确。

2.设备的外部电平干扰,这种情况发生在主机给从机发送完成后,等待从机回复后,缓冲区中的数据没有及时取走,外部信号导致主机认为一帧数据的到来,从而破坏了缓冲区中的数据。

3.主机发送数据后,等待从机回复数据的时间不确定,有可能导致处理数据时还在接收数据。

这三种风险的存在,使得往往真实的设备上出现了许许多多问题,导致设备的使用体验不佳,或者程序出现频频的bug。为了解决这些问题,不同的嵌入式程序员在上面思考了很多解决办法。

3.基于固定缓冲区的设计

这种设计就是因为看到了模块的数据发送的特点,以及数据没及时取走就被覆盖的问题,于是设计了一个带有接收数量的缓冲区模型。

前面一种是基于串口的帧数据模型,而缓冲区考虑的是串口的字节模型。帧数据模型一般就是串口接收的时候,发生串口接收中断,把数据放到缓冲区,当一帧数据接收完成后会发生空闲中断,或者DMA完成中断,或者是采用定时器时定时器中断,这样判定接收到一帧数据。而循环缓冲区则不需要考虑一帧数据完成的中断,这种设计都是在软件中完成。

这种设计都会采用一个USART_RX_STA接收状态寄存器的变量来表明接收数据的状态,通用的设计规则是

1.USART_RX_STA的0~14位用于存储串口接收数据的个数,每次接收完成都会将USART_RX_STA++

2.USART_RX_STA的15,16两位表示接收的1状态,简而言之,比如接收状态0x4000表示接收到了0x0d,而0x8000则表示接收完成。

数据处理在任务中,当判断数据接收完成时,处理缓冲区中的数据即可。这种设计很多开发板例程有,所以很多人直接拿开发板例程做项目时经常可以看到。

问题也是很明确,当做协议处理,十分不友好,需要及时去取数据,否则会掉帧。当数据接收的很快时,也会出现问题。

4.基于报文的处理解析

这种我只在轨道交通某些程序上看到这种设计,设计是基于报文格式,这种报文处理方式的好处很明显,可以一个字节一个字节的处理,比如可以判断报头是0x10,第二个报文是0x02等等,然后依次往数据包中处理写数据,判断结尾帧后,一次性交给其他程序处理数据包。

这个数据包的处理放在串口接收中断里面,然后去解析报文,获取相关的信息。

基于报文的解析规则,需要的串口波特率比较低,比如9600以下等等,并且采用485等进行数据传输。这样可靠性有一定的保障,但是数据的发送一定需要在比较低的波特率下进行。而且两帧数据之间需要有一定时间的间隔。

5.循环缓冲区的使用

这一种设计需要一个read_index指针和write_index指针。

设计的关键点在于读写分离,每次去读数据的时候,不用关注是否一帧数据,直接从循环buffer中去取数据就可以了。当read_index=write_index的时候,表示buffer中的数据已经处理干净了。

这种读写分离的设计考虑可以参见rt-thread物联网操作系统的serial框架设计。

这种设计从一定程度上,避免了数据丢包的情况,但是在读数据的时候,如果出现了连包的情况,处理起来也比较的复杂。特别是在不定长数据协议栈的处理上,也会显的无力。

对于收发有序的逻辑处理比较好,但是不定期发送数据,处理起来也需要一定工作量。

6.基于帧处理的串口框架

目前,正在做一个基于物联网的通用系统模型,所以思考了一下基于物联网上面的串口模块使用的架构,最后设计了一个可以使用的框架。当前不一定很完善,但是还是把自己思考的部分分享出来。

由于物联网模块的AT指令都是不定长的,而且时一帧一帧的数据,而且实际透传模式时,收发没有固定的逻辑,都是随机的,所以针对这种特性设计以下的模型。

其设计思想基于串口中间件的考虑,上层应用不直接访问串口驱动硬件。每次都调用同样的接口去包管理器中去取一帧数据,所以这种设计的出发点是基于一帧数据的模型。关于确保一帧数据的机制,可以使用定时器去判断,如果在一定的时间里面没有收到数据,发生了定时器中断,那么就认为这一帧数据的结束。如果这个假设出现了太多问题,那么这个设计也是不行的。

而通用接口又不用关注是否有数据到来的问题,直接调用接口,有数据则返回数据信息,没有数据则告诉没有数据。

所有的数据包管理在一个对象结构体中进行,读数据时,将data_r_index向后偏移,比如最大定义8个pkgs,那么达到8时再回到0,然后去读对应index的数据。并且读数据,会有rest_size,表示这个里面还剩下多少数据没有读完,下次调用读函数时,直接去处理没读完的数据就好了,而不用去找到第二帧数据。

int uart_buffer_read(char *uart_buf, uint16_t len)
{   
    int ret = 0;
    //两者相等,无数据
    if(uart_manage.data_w_index == uart_manage.data_r_index)
    {
        ret = 0;
    }
    else
    {
        if(len >= uart_pkg[uart_manage.data_r_index].rest_size)
        {
            len = uart_pkg[uart_manage.data_r_index].rest_size;
            rt_memcpy(uart_buf, uart_pkg[uart_manage.data_r_index].user_data + (uart_pkg[uart_manage.data_r_index].recv_size - uart_pkg[uart_manage.data_r_index].rest_size), len);
            uart_pkg[uart_manage.data_r_index].rest_size = 0;
            ret = len;
            
            uart_pkg[uart_manage.data_r_index].recv_size = 0;
            
            if(uart_manage.data_r_index < 7)
            {
                uart_manage.data_r_index = uart_manage.data_r_index + 1;
            }
            else
            {
                uart_manage.data_r_index = 0;
            }
        }
        else
        {
            rt_memcpy(uart_buf, uart_pkg[uart_manage.data_r_index].user_data + (uart_pkg[uart_manage.data_r_index].recv_size - uart_pkg[uart_manage.data_r_index].rest_size), len);
            uart_pkg[uart_manage.data_r_index].rest_size = uart_pkg[uart_manage.data_r_index].rest_size - len;
            ret = len;
        }
    }
    return ret;
}

对于串口写数据的设计,则是由接收到一帧数据后触发,由中断触发,此时一帧数据接收完成,会有一定的休息时间,所以一般足够将收到的数据写到对应的包中。

int uart_buffer_write(char *uart_buf, uint16_t len)
{
    if(len > 512)
    {
        rt_kprintf("write buffer too big!\n");
        return 0;
    }
    rt_memset(uart_pkg[uart_manage.data_w_index].user_data, 0512);
    uart_pkg[uart_manage.data_w_index].recv_size = len;
    uart_pkg[uart_manage.data_w_index].rest_size = len;
    rt_memcpy(uart_pkg[uart_manage.data_w_index].user_data, uart_buf, len);
    uart_manage.buff = &uart_pkg[uart_manage.data_w_index];

    if(uart_manage.data_w_index < 7)
    {
        uart_manage.data_w_index = uart_manage.data_w_index + 1;
    }
    else
    {
        uart_manage.data_w_index = 0;
    }
    return len;
}

通过上述的设计逻辑,很好的处理了一帧数据包的问题,同时每帧数据都带有长度信息和相关的读写状态信息,也能够不丢帧。同时采用循环index的机制,能够不干扰数据正常的存取的情况下,保障的数据的可靠性。

当然,这种设计的前提是保证一帧数据的完整性与可靠性的比例很高,如果断帧的情况比较严重,那还是采用循环buffer,通过字节管理的方式进行设计。

7.总结

对于串口框架的设计,是需要好好思考的,设计串口驱动程序时,不要认为串口驱动简单,在做协议时,也不能太过于数据传输的理想化,应该综合考虑连包、断帧、超时、干扰等等因素,这样设计的驱动才会更加的稳定,上文只是简单的描述常见的一些处理串口数据的逻辑,应该还有更多的,更好的设计框架值得去学习理解,也希望有更多的人提出一些更好的设计模型。

1.2021年第3期《单片机与嵌入式系统应用》电子刊新鲜出炉!

2.MCU为什么内部不集成晶振?

3.MCU开发中,你选”裸奔“还是RTOS?

4.MIT发布2021年10大突破性技术~

5.Google重磅发布Flutter 2!一套代码横扫 5 大系统

6.硬件工程师常用的5V转3.3V的方法

免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。

嵌入式资讯精选 掌握最鲜资讯,尽领行业新风
评论
  • RDDI-DAP错误通常与调试接口相关,特别是在使用CMSIS-DAP协议进行嵌入式系统开发时。以下是一些可能的原因和解决方法: 1. 硬件连接问题:     检查调试器(如ST-Link)与目标板之间的连接是否牢固。     确保所有必要的引脚都已正确连接,没有松动或短路。 2. 电源问题:     确保目标板和调试器都有足够的电源供应。     检查电源电压是否符合目标板的规格要求。 3. 固件问题: &n
    丙丁先生 2024-12-01 17:37 109浏览
  • 艾迈斯欧司朗全新“样片申请”小程序,逾160种LED、传感器、多芯片组合等产品样片一触即达。轻松3步完成申请,境内免费包邮到家!本期热荐性能显著提升的OSLON® Optimal,GF CSSRML.24ams OSRAM 基于最新芯片技术推出全新LED产品OSLON® Optimal系列,实现了显著的性能升级。该系列提供五种不同颜色的光源选项,包括Hyper Red(660 nm,PDN)、Red(640 nm)、Deep Blue(450 nm,PDN)、Far Red(730 nm)及Ho
    艾迈斯欧司朗 2024-11-29 16:55 181浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2024-12-02 10:40 134浏览
  • 概述 说明(三)探讨的是比较器一般带有滞回(Hysteresis)功能,为了解决输入信号转换速率不够的问题。前文还提到,即便使能滞回(Hysteresis)功能,还是无法解决SiPM读出测试系统需要解决的问题。本文在说明(三)的基础上,继续探讨为SiPM读出测试系统寻求合适的模拟脉冲检出方案。前四代SiPM使用的高速比较器指标缺陷 由于前端模拟信号属于典型的指数脉冲,所以下降沿转换速率(Slew Rate)过慢,导致比较器检出出现不必要的问题。尽管比较器可以使能滞回(Hysteresis)模块功
    coyoo 2024-12-03 12:20 153浏览
  • 11-29学习笔记11-29学习笔记习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-02 23:58 88浏览
  • TOF多区传感器: ND06   ND06是一款微型多区高集成度ToF测距传感器,其支持24个区域(6 x 4)同步测距,测距范围远达5m,具有测距范围广、精度高、测距稳定等特点。适用于投影仪的无感自动对焦和梯形校正、AIoT、手势识别、智能面板和智能灯具等多种场景。                 如果用ND06进行手势识别,只需要经过三个步骤: 第一步&
    esad0 2024-12-04 11:20 88浏览
  • 学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&
    youyeye 2024-11-30 14:30 85浏览
  • 戴上XR眼镜去“追龙”是种什么体验?2024年11月30日,由上海自然博物馆(上海科技馆分馆)与三湘印象联合出品、三湘印象旗下观印象艺术发展有限公司(下简称“观印象”)承制的《又见恐龙》XR嘉年华在上海自然博物馆重磅开幕。该体验项目将于12月1日正式对公众开放,持续至2025年3月30日。双向奔赴,恐龙IP撞上元宇宙不久前,上海市经济和信息化委员会等部门联合印发了《上海市超高清视听产业发展行动方案》,特别提到“支持博物馆、主题乐园等场所推动超高清视听技术应用,丰富线下文旅消费体验”。作为上海自然
    电子与消费 2024-11-30 22:03 103浏览
  • 最近几年,新能源汽车愈发受到消费者的青睐,其销量也是一路走高。据中汽协公布的数据显示,2024年10月,新能源汽车产销分别完成146.3万辆和143万辆,同比分别增长48%和49.6%。而结合各家新能源车企所公布的销量数据来看,比亚迪再度夺得了销冠宝座,其10月新能源汽车销量达到了502657辆,同比增长66.53%。众所周知,比亚迪是新能源汽车领域的重要参与者,其一举一动向来为外界所关注。日前,比亚迪汽车旗下品牌方程豹汽车推出了新车方程豹豹8,该款车型一上市就迅速吸引了消费者的目光,成为SUV
    刘旷 2024-12-02 09:32 131浏览
  • 作为优秀工程师的你,已身经百战、阅板无数!请先醒醒,新的项目来了,这是一个既要、又要、还要的产品需求,ARM核心板中一个处理器怎么能实现这么丰富的外围接口?踌躇之际,你偶阅此文。于是,“潘多拉”的魔盒打开了!没错,USB资源就是你打开新世界得钥匙,它能做哪些扩展呢?1.1  USB扩网口通用ARM处理器大多带两路网口,如果项目中有多路网路接口的需求,一般会选择在主板外部加交换机/路由器。当然,出于成本考虑,也可以将Switch芯片集成到ARM核心板或底板上,如KSZ9897、
    万象奥科 2024-12-03 10:24 86浏览
  • 遇到部分串口工具不支持1500000波特率,这时候就需要进行修改,本文以触觉智能RK3562开发板修改系统波特率为115200为例,介绍瑞芯微方案主板Linux修改系统串口波特率教程。温馨提示:瑞芯微方案主板/开发板串口波特率只支持115200或1500000。修改Loader打印波特率查看对应芯片的MINIALL.ini确定要修改的bin文件#查看对应芯片的MINIALL.ini cat rkbin/RKBOOT/RK3562MINIALL.ini修改uart baudrate参数修改以下目
    Industio_触觉智能 2024-12-03 11:28 104浏览
  •         温度传感器的精度受哪些因素影响,要先看所用的温度传感器输出哪种信号,不同信号输出的温度传感器影响精度的因素也不同。        现在常用的温度传感器输出信号有以下几种:电阻信号、电流信号、电压信号、数字信号等。以输出电阻信号的温度传感器为例,还细分为正温度系数温度传感器和负温度系数温度传感器,常用的铂电阻PT100/1000温度传感器就是正温度系数,就是说随着温度的升高,输出的电阻值会增大。对于输出
    锦正茂科技 2024-12-03 11:50 135浏览
  • 当前,智能汽车产业迎来重大变局,随着人工智能、5G、大数据等新一代信息技术的迅猛发展,智能网联汽车正呈现强劲发展势头。11月26日,在2024紫光展锐全球合作伙伴大会汽车电子生态论坛上,紫光展锐与上汽海外出行联合发布搭载紫光展锐A7870的上汽海外MG量产车型,并发布A7710系列UWB数字钥匙解决方案平台,可应用于数字钥匙、活体检测、脚踢雷达、自动泊车等多种智能汽车场景。 联合发布量产车型,推动汽车智能化出海紫光展锐与上汽海外出行达成战略合作,联合发布搭载紫光展锐A7870的量产车型
    紫光展锐 2024-12-03 11:38 121浏览
  • 《高速PCB设计经验规则应用实践》+PCB绘制学习与验证读书首先看目录,我感兴趣的是这一节;作者在书中列举了一条经典规则,然后进行详细分析,通过公式推导图表列举说明了传统的这一规则是受到电容加工特点影响的,在使用了MLCC陶瓷电容后这一条规则已经不再实用了。图书还列举了高速PCB设计需要的专业工具和仿真软件,当然由于篇幅所限,只是介绍了一点点设计步骤;我最感兴趣的部分还是元件布局的经验规则,在这里列举如下:在这里,演示一下,我根据书本知识进行电机驱动的布局:这也算知行合一吧。对于布局书中有一句:
    wuyu2009 2024-11-30 20:30 141浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦