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

    文章

    6793

    浏览量

    123275
  • fifo
    +关注

    关注

    3

    文章

    387

    浏览量

    43634
  • 串口数据
    +关注

    关注

    0

    文章

    33

    浏览量

    13880

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

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

收藏 人收藏

    评论

    相关推荐

    JavaWeb消息队列使用指南

    用程序的通信方法,允许异步传输消息,并且具有存储和转发消息的能力。它主要解决以下问题: 异步处理 :允许系统组件异步处理任务,提高响应速度。 解耦系统 :不同系统组件之间通过消息队列通信,降低耦合度。 流量削峰 :在高流量情况下,消息
    的头像 发表于 11-25 09:27 136次阅读

    tlv320aic3016配置好以后然后打开中断允许,没有录音数据的输入,到队列fifo的数是0吗?

    配置好以后然后打开中断允许如果没有录音数据的输入,那么到队列fifo的数是0吗,level的值会变化吗?
    发表于 10-28 07:11

    嵌入式环形队列与消息队列的实现原理

    嵌入式环形队列,也称为环形缓冲区或循环队列,是一种先进先出(FIFO)的数据结构,用于在固定大小的存储区域中高效地存储和访问数据。其主要特点
    的头像 发表于 09-02 15:29 451次阅读

    玩转RT-Thread之消息队列的应用

    在嵌入式系统开发中,实时处理串口和ADC数据是一项重要的任务。本文将介绍如何在RT-Thread实时操作系统中,利用消息队列来同时处理来自串口和ADC的
    的头像 发表于 07-23 08:11 602次阅读
    玩转RT-Thread之消息<b class='flag-5'>队列</b>的应用

    EPS32-C3使用USB串口收发数据,在发送长度为64的数据时,上位机串口工具无法接收到数据怎么解决?

    EPS32-C3 使用USB串口收发数据 结果发现使用int usb_serial_jtag_write_bytes(const void* src, size_t size, TickType_t
    发表于 06-06 06:12

    同步FIFO和异步FIFO区别介绍

    1. FIFO简介 FIFO是一种先进先出数据缓存器,它与普通存储器的区别是没有外部读写地址线,使用起来非常简单,缺点是只能顺序读写,而不能随机读写。 2. 使用场景 数据缓冲:也就是
    的头像 发表于 06-04 14:27 1547次阅读
    同步<b class='flag-5'>FIFO</b>和异步<b class='flag-5'>FIFO</b>区别介绍

    STM32串口1同时收发数据卡在回调函数中怎么解决?

    只能正常收发几次,卡住后进入不了user_main_program 同时使用了串口2连接esp8266进行数据收发
    发表于 05-29 06:34

    freertos串口接收数据后如何发送给任务?

    正在学freertos。串口中断接收一帧数据后,放到数组里,如何将数据发送给任务呢? 如果用消息队列,是否建立的消息队列需要是数组类型的?
    发表于 04-18 06:36

    TC397 asclin做串口收发数据有乱码怎么解决?

    在做串口测试时,将rxfifo的中断模式设置成BATCH模式,发现每次进入中断后从FIFO中读出的数据偶尔会有乱码,请问各位大神又遇到过类似问题的吗
    发表于 02-06 08:27

    TC1728如何用FIFO发送和接收数据,如何配置和调用?

    配置好并不能收到数据,请问前面如何配置才能收发数据? 如果要用FIFO方式收发一个报文如 Data1[8] ={0x00
    发表于 02-04 09:33

    串口中断函数中,接收的数据量已经超过了FIFO的长度,会不会造成数据丢失呀?

    如果在串口中断函数中,正在读缓冲区的中的数据(还没有读完),这个时候,串口又接收到新的数据,接收的数据量已经超过了
    发表于 01-17 08:14

    如何用DMA的方式读写串口数据

    串口接收(或者发送)的数据比较大,如果用中断逐字节从FIFO数据太耗时了,光盘里的找不到有关DMA读写串口的demo
    发表于 01-17 07:35

    labview 队列最前端插入的应用

    LabVIEW是一种用于实时测试、测量和控制系统的高级系统设计软件。它采用了数据流编程方式,提供了一种直观、可视化的方法来构建复杂的测试和测量应用程序。其中一个重要的功能是队列,它可以在软件设计中
    的头像 发表于 01-08 11:45 1177次阅读

    labview怎么清除串口缓存的数据

    LabVIEW 是一款功能强大的图形化编程软件,常用于控制、监测和数据采集等应用。当我们使用串口进行数据通信时,有时会遇到串口缓存的数据无法
    的头像 发表于 01-08 11:30 3757次阅读

    labview队列有什么实际作用

    LabVIEW队列是一种数据结构,常用于解决多任务并发处理的问题。它被广泛应用于科学研究、工程项目和自动化控制等领域。在LabVIEW中,队列提供了一种高效、方便的方式来处理不同任务之间的数据
    的头像 发表于 01-05 16:42 1576次阅读