UART的FIFO功能

2023-05-16

经常听到UART的FIFO功能,但是从来没有真正使用过和认真思考过它的作用。正好有客户用到这个功能,在这里做个总结。
FIFO 是“First-In First-Out”的缩写,它是一个具有先入先出特点的缓冲区。串口设计FIFO的目的是为了提高串口的通讯性能。如果没有FIFO或者说缓冲区的长度只有1字节,那么使用接收中断,就意味着每次收到一个字节的数据就要进一次中断,这样频繁进中断会占用CPU资源。另外如果没有及时读走数据,那么下一个字节数据就会覆盖之前的数据,导致数据丢失,这在通讯速率高的场合很有可能出现。
使用FIFO,可以在连续接收若干个数据后才产生一次中断,然后一起进行处理。这样可以提高接收效率,避免频繁进中断,适用于大数据传输。你可能会想到如果FIFO中的数据没有达到指定长度而无法产生中断怎么办,通常MCU会有接收超时中断,即在一定的时间内没有接收到数据会进入中断,可以利用这个中断把不足FIFO长度的数据最后都读取完。
这里写图片描述
但是使用FIFO接收多字节数据进中断不好的地方是实时性会受到一定的影响,对某些实时性要求高的场合,比如说要求UART收到某个特定字符就立刻停止发送数据这样一个场合,使用FIFO每多个字节进一次中断就不合适了。
所以说使用FIFO好处是1)避免频繁进中断,提高吞吐率 2)避免数据因没有及时处理而丢失。不好的地方是实时性受影响。
此客户要求使用FIFO的原因是他们担心在接收中断处理过程中数据来的太快没有及时处理而丢失。
针对这个问题采取的解决方法是:还是一个字节进一次接收中断,这样可以保证实时性,把FIFO打开,这样可以防止数据被覆盖而丢失,在接收中断处理完接收数据之后去判断缓冲区中是否有数据,如果有的话把数据读走,这样就防止了数据丢失,同时保证了实时性。
对于Kinetis M4 MCU操作也非常简单。
以K60为例,UART0和UART1缓冲区长度为8,其他UART缓冲区长度为1.
这里写图片描述
只要配置UARTx_PFIFO寄存器即可。
这里写图片描述
软件上是:

UART_EnableRxFIFO(UART_InitStruct->instance, true);
UART_FlushRxFifo(UART_InitStruct->instance);
UART_FlushTxFifo(UART_InitStruct->instance);

需要注意的是:配置此寄存器 C2[RE] 和C2[TE] 位为0,另外在设置完RXFE位之后,应立刻向UARTx_CFIFO的TXFLUSH和RXFLUSH位写1.

这样配置完之后就打开了接收FIFO功能。在中断处理函数中,最后去判断UARTx_SFIFO 寄存器的RXEMPT位是否为1即可。
这里写图片描述

      while(!((UART_InstanceTable[HW_UART0]->SFIFO  \
       & UART_SFIFO_RXEMPT_MASK) >> UART_SFIFO_RXEMPT_SHIFT))
        {
            ch = (uint8_t)UART_InstanceTable[HW_UART0]->D;
            .
            .
            .
             }

前面提到的接收多个字节进一次中断该如何实现呢。
只需要设置一下UARTx_RWFIFO寄存器即可。
这里写图片描述

UART_SetRxFIFOWatermark(UART_InitStruct->instance, 0x4); // 每4个字节进一次中断

前面还提到超时中断,在Kinetis MCU里是叫做IDLE Line 中断。
只需要设置UARTx_C2的ILIE为1,使能IDLE LINE中断。
这里写图片描述
另外设置UARTx_C1的ILT位
这里写图片描述
这里写图片描述

在中断服务函数中

/*  IDLE interrupt */
  if(UART1_S1&UART_S1_IDLE_MASK)// if IDLE Line interrupt occured
  {
        // clear interrupt flag; To clear IDLE, read UART       status S1 with IDLE set and then read D
        UART1_S1 |= UART_S1_IDLE_MASK;
        Receive_data=(uint8_t)(UART1_BASE_PTR->D);  
        printf("\r\nGo to Idle line\r\n");
  }

前面一直说的接收过程,对于发送过程也是类似的。不用FIFO,如果使用中断方式发送的话,那么就是一个字节发送完进一次中断,然后发送另外一字节数据。使用FIFO的话,每次中断处理可以多个字节的数据。
这里写图片描述
注意在中断服务里发送的字节数并没有限制,进发送中断的核心条件是
这里写图片描述

这里写图片描述

TXWATER默认值为0. 当FIFO为空时,即所有数据都发送出去时进中断。
假设我想在每次中断服务函数中发送4个字节,程序设置如下:
首先初始化时打开TX的FIFO功能

UART_EnableTxFIFO(UART_InitStruct->instance, true);
UART_FlushRxFifo(UART_InitStruct->instance);
UART_FlushTxFifo(UART_InitStruct->instance);

在中断处理函数中

  /* Tx */
    if((UART_InstanceTable[HW_UART0]->S1 & UART_S1_TDRE_MASK) && (UART_InstanceTable[HW_UART0]->C2 & UART_C2_TIE_MASK))
    {
                /* buffer is used */
        while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));
                UART_InstanceTable[HW_UART0]->D = '1';

                 /* buffer is used */
        while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));
            UART_InstanceTable[HW_UART0]->D = '2';  

                 /* buffer is used */
        while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));
            UART_InstanceTable[HW_UART0]->D = '3';  

                 /* buffer is used */
        while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));
              UART_InstanceTable[HW_UART0]->D = '4';

                 /* buffer is used */
        while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));
          UART_InstanceTable[HW_UART0]->D = '5';

                /* buffer is used */
        while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));
          UART_InstanceTable[HW_UART0]->D = '6';

                /* buffer is used */
        while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));
          UART_InstanceTable[HW_UART0]->D = '7';

                /* buffer is used */
        while(UART_InstanceTable[HW_UART0]->TCFIFO >= UART_GetTxFIFOSize(HW_UART0));
          UART_InstanceTable[HW_UART0]->D = ' ';

.
.
.
}

在网上看到一篇很好的文章,下载链接为:http://download.csdn.net/detail/wangwenxue1989/9089861

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UART的FIFO功能 的相关文章

  • UART波形分析

    1 逻辑分析仪解码配置 波特率 xff1a 9600 2 逻辑分析仪结果 3 波特率计算 1除以9600 xff0c 结果如下 xff08 e 4表示10的负4次方 xff09 表示 0 00010416秒 61 104 16 微秒 找到发
  • 一文理解UART通信

    还记得当年的打印机 xff0c 鼠标和调制解调器吗 他们都有巨大笨重的连接器和粗电缆 xff0c 并且必须拧到你的电脑上 这些设备正是使用UART协议与计算机进行通信 虽然USB几乎完全取代了旧的电缆和连接器 xff0c 但UART绝对没有
  • FPGA uart串口收发verilog源码程序,适用于RS232 RS422

    FPGA uart串口收发verilog源码程序 xff0c 适用于RS232 RS422 xff0c 支持修改波特率 xff0c 数据位 xff0c 校验位 ID 3750670799663712
  • UART串口通信协议详解

    UART xff1a 通信异步收发器 xff0c 串行 异步通信总线 xff0c 两条数据线 xff08 收发 xff09 xff0c 全双工 xff08 可以同时接收和发送 xff09 一 UART帧格式 xff08 UART协议 xff
  • RT-Thread记录(十一、I/O 设备模型之UART设备 — 源码解析)

    深入理解 RT Thread I O 设备模型 分析 UART设备源码 目录 前言 一 初识 UART 操作函数 应用程序 二 UART 的初始化 2 1 UART 设备初始化位置 2 2 UART 设备初始化函数分析 stm32 uart
  • 一起学nRF51xx 6 - uart

    前言 通用异步接收器 发送器提供快速 全双工 内置流量控制的异步串行通信 CTS RTS 在硬件方面支持高达1Mbps波特率 支持奇偶校验和第9位数据生成 用于每个UART接口线的GPIO可从芯片上的GPIO中任选 而且可独立配置 这使得芯
  • GD32E23x的USART被断点打断后重新运行,会一直进入中断的问题

    GD32E23x的USART被断点打断后重新运行 会一直进入中断的问题 GD32E230K8单片机USART0连接一个从机芯片 该芯片每100ms发来一串16Bytes的数据 MCU中断接收 没有开启FIFO 只开启了RBNE 接收缓存非空
  • UART通信原理

    UART 通信格式 串口全称叫做串行接口 通常也叫做 COM 接口 串行接口指的是数据一个一个的顺序传输 通信线路简单 使用两条线即可实现双向通信 一条用于发送 一条用于接收 串口通信距离远 但是速度相对会低 串口是一种很常用的工业接口 I
  • ESP32-C3入门教程 基础篇(三、UART模块 — 与Enocean无线模块串口通信)

    测试第三课 ESP32 C3的串口通信测试 老样子 使用Enocean无线模块和ESP32 C3进行串口通信 目录 前言 1 UART示例测试 1 1 UART 基础测试 1 2 与Enocean无线模块串口通信测试 2 ESP32 C3
  • AWS SQS FIFO - 如何一次获取超过 10 条消息?

    目前我们想要拉下一个整个 FIFO 队列 并处理内容 如果有任何问题 将消息释放回队列中 问题是 目前 AWS 只给我们 10 条消息 并且不会再给我们 10 条消息 这是在 SQS 中获取批量消息的方式 多个 10 条最大消息请求 直到我
  • 无法写入通过 NFS 连接的 FIFO 文件

    我正在尝试写入位于 NFS 安装上的 FIFO 文件 但它会阻塞 可能是什么问题呢 我的 etc export tmp test 10 0 0 0 24 rw no root squash async NFS 服务器和客户端上的 ls tm
  • SQL 先进先出忠诚点

    各位开发人员和分析师 我在 SQL 方面有一些经验 并且已经求助于类似的帖子 然而 这有点小众 预先感谢您的帮助 我有以下数据集 已编辑 道歉 Setup CREATE TABLE CustomerPoints CustomerID INT
  • 启用 DMA 的 UART Tx 模式

    我已经为 UART 在传输模式下编写了一个简单的设备驱动程序 并启用了 DMA 和中断 我使用的硬件是 omap 4460 pandaboard 其中加载了 Linux 3 4 下面我分享一下相关部分的代码 在开放阶段 dma map io
  • 使用 read(...) 时在换行符处停止

    我需要从通过 UART 连接的 GPS 读取 NMEA 语句 操作系统是Debian 语言必须是C 为此 我使用以下命令打开文件open 并读取一个字符串read 但是 这样我必须指定字符串长度 这会分解句子 相反 我想读到 NMEA 句子
  • GATT 配置文件和 UART 服务

    我是开发通过蓝牙连接到外围设备的移动应用程序的新手 我搜索到 GATT 是用于蓝牙LE 通信的相关配置文件 但我们的客户建议我们使用 UART 服务 现在我很困惑 1 这两件事是如何关联的 2 我们是否必须选择其中之一 如果是的话 每一个的
  • C语言UART通信(十六进制)

    我想向写入函数发送一个十六进制值 例如 0 90 这是因为需要通信的设备接收到的是十六进制数的命令 未使用的变量在测试时出现 并注释为丢失十六进制值 稍后将被删除 如何编写具有字符串以外的十六进制值的写入函数 对于初学者 请告诉我们如何通过
  • Matlab 从命名管道(fifo)读取

    我在 Linux 下的 matlab 中读取命名管道 fifo 时遇到问题 管道上的 textread 始终返回 空矩阵 0 1 textread 会阻塞 直到数据写入管道 如果我使用 fopen 和 fscanf 那么 fopen 将阻塞
  • 在C中读/写结构到fifo

    我正在尝试使用命名管道在进程之间传递结构 我在尝试打开管道非阻塞模式时陷入困境 这是我写入 fifo 的代码 void writeUpdate Create fifo for writing updates strcpy fifo writ
  • 用 C 语言实现 FIFO 队列

    对于嵌入式应用程序 我尝试使用 ANSI C 实现先进先出 FIFO 结构队列 最直接的方法似乎是通过实现链表 以便每个结构包含指向队列中下一个的指针 因此我将结构本身定义为 typedef enum LED on LED off etc
  • 有队列实现吗?

    任何人都可以建议使用 Go 容器来实现简单快速的 FIF 队列 Go 有 3 种不同的容器 heap list and vector 哪一种更适合实现队列 事实上 如果您想要的是一个基本且易于使用的 fifo 队列 slice 可以满足您所

随机推荐

  • MicroPython移植

    MicroPython移植 1 目标板 stm32f407zgt6 2 下载移植准备 micropython源码 arm交叉编译工具 sudo apt get install git sudo apt get install gcc arm
  • 了解ESP32睡眠模式及其功耗

    陈拓翻译 2022 05 30 2022 05 30 原文 https lastminuteengineers com esp32 sleep modes power consumption 毫无疑问 xff0c ESP32是许多WiFi
  • 浅谈布隆过滤器

    什么是布隆过滤器 布隆过滤器是一种数据结构 xff0c 比较巧妙的概率型数据结构 xff08 probabilistic data structure xff09 xff0c 特点是高效地插入和查询 xff0c 可以用来告诉你 某样东西一定
  • 浅谈CGI基本原理和底层基本实现

    历史来由 xff1a 早期的Web服务器 xff0c 只能响应浏览器发来的HTTP静态资源的请求 xff0c 并将存储在服务器中的静态资源返回给浏览器 随着Web技术的发展 xff0c 逐渐出现了动态技术 xff0c 但是Web服务器并不能
  • linux的两种共享内存方式---mmap和shmat区别

    linux中的两种共享内存 一种是我们的IPC通信System V版本的共享内存 xff0c 另外的一种就是我们今天提到的存储映射I O xff08 mmap函数 xff09 在说mmap之前我们先说一下普通的读写文件的原理 xff0c 进
  • tcp发送窗口(滑动窗口)、拥塞窗口

    TCP发送窗口拥塞窗口试题分析 题目一 xff1a 来源2015年408计算机综合 试题链接 xff1a https www nowcoder com questionTerminal 3241441c88f04ab58585a187716
  • mktime函数性能分析

    mktime函数性能分析 1月 02 2019 in Linux环境高级编程 mktime函数性能分析 mktime是一个将break down时间 struct tm 转化为日历时间 time t 的转换函数 它的转换与struct tm
  • iptables原理和防火墙主要命令使用场景

    https www zsythink net archives 1764 朱双印的个人日志 xff0c 写的非常的通俗易懂 xff0c 好文章 https blog csdn net u011277123 article details 8
  • 链路mtu

    常常见到交换机和网卡说明中提到支持Jumbo Frame xff0c 但我一直对以太网的Jumbo Frame xff08 巨帧 xff09 如何使用不太理解 xff0c 今日在网上找到2则现摘录下来 xff0c 相信看了以后大家会有收获
  • eggjs

    https editor csdn net md not checkout 61 1 amp spm 61 1001 2014 3001 4503 https blog csdn net weixin 42304193 article de
  • mini6410上HelloQt4运行出现libQtGui.so.4: cannot open shared的原因

    主要原因是在3 3 3节中 xff0c 编写的环境变量搭建文件setqt4env中设置路径不对 export LD LIBRARY PATH 61 xff08 看看有没有文件中的目录 xff09 应该改成你所在的qt4 7目录中的lib目录
  • VINS技术路线与代码详解

    VINS技术路线 写在前面 xff1a 本文整和自己的思路 xff0c 希望对学习VINS或者VIO的同学有所帮助 xff0c 如果你觉得文章写的对你的理解有一点帮助 xff0c 可以推荐给周围的小伙伴们 xff0c 当然 xff0c 如果
  • 用MicroPython开发ESP32- 用Thonny写程序

    陈拓 2022 06 11 2022 06 12 1 简介 在 用MicroPython开发ESP32 固件烧写与测试 https zhuanlan zhihu com p 527291091 https blog csdn net che
  • 单片机 stm32 接收数据和处理

    背景 1 单片机串口接收数据处理 xff0c 这个代码已经过很多项目验证 xff0c 没有问题 用这个代码帮了好几个同事解决数据接收久了就异常 2 这个代码做到接收和处理分开 避免不必要的处理逻辑问题 3 也可用于网口tcp xff0c u
  • odroid Xu4介绍

    Odroid xu4介绍 下面对这块开发板做一下简单的介绍 xff0c 共需要用到的人参考 从参数上来看 xff0c ODROID XU4的整体性能基本和目前的中端智能手机差不多 xff0c 它搭载了主频
  • OdroidXu4开发环境搭建

    OdroidXu4开发环境搭建 一 烧录镜像 1 SD卡烧录 首先准备一张至少16G的sd卡 镜像可以在官网 xff1a http odroid com dokuwiki doku php id 61 en odroid xu4 softw
  • 大小端:字节序与比特序

    https blog csdn net fzy0201 article details 26876711 https blog csdn net qq 40334837 article details 89042607 前言 前两天被问到一
  • VLC Buffering机制介绍

    一 简介 了解一定播放器知识的同学应该都知道 xff0c 播放器内部是有缓存的 xff08 非直播场景 xff09 缓存的作用主要是解决生产者和消费者速度的不匹配 xff0c 给用户更好的使用体验 例如 xff0c 在网络不稳定的情况下 x
  • Linux静态库和动态库学习总结

    一 废话 之前由于工作需要 xff0c 要封装一个Linux加密解密转换的动态库 xff0c 这个之前只做过Windows下面的 xff0c Linux下面还真没有做过 xff0c 之后做了整一个晚上才算做好 xff0c 不过其中也学到了不
  • UART的FIFO功能

    经常听到UART的FIFO功能 xff0c 但是从来没有真正使用过和认真思考过它的作用 正好有客户用到这个功能 xff0c 在这里做个总结 FIFO 是 First In First Out 的缩写 xff0c 它是一个具有先入先出特点的缓