0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FIFO队列的串口数据收发方法

FPGA之家 来源:FPGA之家 作者:FPGA之家 2022-07-12 09:16 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

01

前言

嵌入式软件的开发中,串口是十分常用且基础的功能。在需要批量发送数据的场合,可以使用while循环等待发送完成标志位的方式,但是这种方式会占据主循环,影响效率。也可以采用dma的方式,但是dma在发送数据时非常高效,但是批量接收数据时,就很不灵活,特别是一些在串口数据中解析某种协议格式时,很不方便。下面介绍一种利用串口中断结合FIFO队列的串口数据收发方法,结合了不阻塞批量发与灵活接收的优点,特别适用于串口协议收发的使用场景。

02

FIFO队列

FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成。相比于一个同等缓存大小的数值,FIFO就是多管理了一个先进先出的功能,方便串口数据的存入和读出。

Fifo在带操作系统嵌入式软件中都有现成的实现,但是在基础的嵌入软件中,我们可以自己实现一个。

#define UART1_IN_FIFO_SIZE   100 //接收串口队列的深度#define UART1_OUT_FIFO_SIZE 250 //发送串口队列的深度
//头文件函数列表FIFO_EXT u8 uart1infifo_data[UART1_IN_FIFO_SIZE];#define uart1infifo_count (uart1infifo_GetCount())FIFO_EXT u16 uart1infifo_front;FIFO_EXT u16 uart1infifo_rear;FIFO_EXT void uart1infifo_Clear(void);FIFO_EXT void uart1infifo_DataIn(u8 d);FIFO_EXT u8 uart1infifo_DataOut(void);FIFO_EXT u16 uart1infifo_GetSpace(void);FIFO_EXT u16 uart1infifo_GetCount(void);
//获取串口1接收队列缓存数u16 uart1infifo_GetCount(void){  u16 countR,countF;  countR = uart1infifo_rear;  countF = uart1infifo_front;  if (countR >=  countF)  {    return(countR - countF);  }  else  {    return(UART1_IN_FIFO_SIZE + countR - countF);  }}//清空串口1接收队列void uart1infifo_Clear(void){  uart1infifo_front = UART1_IN_FIFO_SIZE -1;  uart1infifo_rear = uart1infifo_front;//  uart1infifo_count = 0;}//串口1接收队列入数据void uart1infifo_DataIn(u8 d){  if (uart1infifo_count < UART1_IN_FIFO_SIZE)  {    uart1infifo_rear = (uart1infifo_rear +1) % UART1_IN_FIFO_SIZE;      uart1infifo_data[uart1infifo_rear] = d;  }}//串口1接收队列出数据u8 uart1infifo_DataOut(void){  if (uart1infifo_rear !=  uart1infifo_front)  {    uart1infifo_front = (uart1infifo_front +1) % UART1_IN_FIFO_SIZE;    return(uart1infifo_data[uart1infifo_front]);  }  else  {    return(0xff);  }}

为了节省篇幅,串口1发送队列就不详细描述了,在接收队列的基础上稍加修改即可。

03

中断收发串口

//串口发送函数 void SendDataToUart1(u8 * pData, u16 len){  u8i;  //串口发送队列将慢,等待一下数据发送  while(1){  if(uart1outfifo_GetSpace()>len+5)  {        break;      }      else      {        i = 0;      }    }    USART_ITConfig(USART1, USART_IT_TXE, DISABLE);  //关闭中断,防止队列的进出会同时进行    while (len --)    {          uart1outfifo_DataIn(*pData);      pData ++;    }      USART_ITConfig(USART1, USART_IT_TXE, ENABLE);}
//串口处理函数void USART1_IRQHandler(void){  if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE))  {    uart1infifo_DataIn(USART_ReceiveData(USART1));//接收数据并放入串口接收队列  //串口数据处理flag  }  else if (USART_GetFlagStatus(USART1, USART_FLAG_TXE))  {    if (uart1outfifo_count > 0)    {      USART_SendData(USART1, uart1outfifo_DataOut());//发队列取出数据放入串口发送寄存器}else {      USART_ITConfig(USART1, USART_IT_TXE, DISABLE);    }  }}

04

串口数据处理

不定长数据包超时处理

在上节的“串口数据处理flag”处,加入超时的标记g_uartTimeOut = n;并在定时器中断中倒计时g_uartTimeOut,减到0后,产生数据包处理标志gb_needDealUartPkg = 1。主循环扫到gb_needDealUartPkg是1后,读出uart1infifo中的全部数据进行解包处理。

不定长数据包按内容格式处理

在上节的“串口数据处理flag”处,加入比对数据包格式的函数,当格式满足要求时,将整个数据包存入数据包队列(参照前面的串口数据接收函数,写一个接收队列,接收的数据为数据包结构体)。主循环扫描数据包队列的缓存数,有就去处理。

定长数据包处理

主循环中扫描uart1infifo_count,当达到定长后,读出uart1infifo中的定长数据进行解包处理。

原文标题:嵌入式软件中的串口收发队列设计方法

文章出处:【微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

审核编辑:彭静

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 操作系统
    +关注

    关注

    37

    文章

    7328

    浏览量

    128625
  • fifo
    +关注

    关注

    3

    文章

    406

    浏览量

    45491
  • 串口数据
    +关注

    关注

    0

    文章

    34

    浏览量

    14232

原文标题:嵌入式软件中的串口收发队列设计方法

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    优先级队列介绍

    队列(Queue)的知识点:「概念」:队列是一种先进先出(FIFO)的数据结构,类似于排队的概念。「基本操作」:enqueue(item): 将元素添加到
    发表于 11-26 07:56

    基于环形队列的UART收发回显实验

    在实际项目开发中,由于有些串口不具备FIFO(如SCI1和SCI2)或FIFO的buffer比较小,这可能会在数据处理速度小于数据接收速度的
    的头像 发表于 10-27 13:51 1690次阅读
    基于环形<b class='flag-5'>队列</b>的UART<b class='flag-5'>收发</b>回显实验

    【CW32】uart_obj_fw 轻量级串口框架

    队列实现,进行简化处理,保留最核心的功能,对于数据FIFO操作,分析了拷贝原数据的劣势,采用了类似拷贝指针的方式,减少内存占用,提高效率。同时
    的头像 发表于 09-29 18:02 7428次阅读

    GD32的串口DMA收发数据失败怎么解决?

    我在使用RTT的GD32F303的BSP时,配置使用串口DMA收发(rt_device_open),发现错误,最终无法收发数据,对比了STM32的BSP发现在drv_usart.c中
    发表于 09-17 06:04

    rtt vision board openmv串口收发数据,接收到的是乱码,为什么?

    利用ttl转Usb ,利用电脑上的串口调试助手发送或者接收数据,接收到的是乱码,将板子上的rx,tx短接,可以正常收发
    发表于 09-15 06:09

    求助,关于串口设备驱动fifo问题

    现象,一包数据包含两包; 2、大数据包出现断包现象,从未收到完整包; 自己查看认为:串口设备驱动中的fifo不是环形buf,调用rt_serial_read();并没有把buf中的字节
    发表于 09-12 08:18

    【RA4M2-SENSOR】—— 13.串口实现循环队列

    上节我已经讲解并实现了使用串口实现不定长度数据的接收,本篇帖子我来采用环形队列来实现不定长度数据的接收和发送。 循环队列在嵌入式当中应用的十
    发表于 09-01 11:46

    【RA-Eco-RA6M4开发板评测】串口收发测试与基于FIFO串口驱动

    基于FIFO串口驱动。接收中断接收数据FIFO,读接口从FIFO取数,这样解耦了应用层底层操作。发送也是类似,简单起见这里发送使用查询方
    发表于 07-19 22:19

    NVME控制器之队列管理模块

    队列管理模块是整个NVMe Host控制器的核心模块,该模块实现了提交队列与完成队列的管理,多队列请求的仲裁判决等功能。队列管理模块中含有
    的头像 发表于 05-03 15:32 423次阅读
    NVME控制器之<b class='flag-5'>队列</b>管理模块

    智多晶FIFO_Generator IP介绍

    FIFO_Generator是智多晶设计的一款通用型FIFO IP。当前发布的FIFO_Generator IP是2.0版本,相比之前的1.1版本主要新增了非等比输入输出数据位宽支持和
    的头像 发表于 04-25 17:24 1469次阅读
    智多晶<b class='flag-5'>FIFO</b>_Generator IP介绍

    基于FPGA的FIFO实现

    FIFO(First in First out)为先进先出队列,具有存储功能,可用于不同时钟域间传输数据以及不同的数据宽度进行数据匹配。如其
    的头像 发表于 04-09 09:55 1171次阅读
    基于FPGA的<b class='flag-5'>FIFO</b>实现

    AXI接口FIFO简介

    AXI接口FIFO是从Native接口FIFO派生而来的。AXI内存映射接口提供了三种样式:AXI4、AXI3和AXI4-Lite。除了Native接口FIFO支持的应用外,AXI FIFO
    的头像 发表于 03-17 10:31 1776次阅读
    AXI接口<b class='flag-5'>FIFO</b>简介

    解锁TSMaster fifo函数:报文读取的高效方法

    前言:TSMaster目前有两种读取报文的模式:回调函数模式和fifo模式。fifo函数是TSMaster近期新增的函数,本文将重点介绍fifo模块。关于回调函数的使用方法可以参考帮助
    的头像 发表于 03-14 20:04 938次阅读
    解锁TSMaster <b class='flag-5'>fifo</b>函数:报文读取的高效<b class='flag-5'>方法</b>

    FIFO IP核的使用教程

    在数字设计中,利用FIFO进行数据处理是非常普遍的应用,例如,实现时钟域交叉、低延时存储器缓存、总线位宽调整等。下图给出了FIFO生成器支持的一种可能配置。
    的头像 发表于 01-03 09:36 4016次阅读
    <b class='flag-5'>FIFO</b> IP核的使用教程

    串口通讯异常处理方法 串口设备连接方式

    串口通信异常处理方法 1. 异常检测 在串口通信中,首先需要能够检测到异常情况。异常检测可以通过以下几种方式实现: 硬件检测 :利用串口硬件的中断和状态寄存器来检测异常,如接收到错误帧
    的头像 发表于 12-27 09:53 5491次阅读