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串口通信

    目录 一 通信特点二 通信应用三 接线示意图三 UART通信协议四 STM32F4 串口使用1 资源分布2 特性3 UART框图4 使用方法5 相关库函数6 函数实例 五 实战 上位机控制开发板小灯 一 通信特点 异步 串行 全双工 一般描
  • 转:DSP28335使用FIFO的串口中断总结

    版权声明 xff1a 本文为CSDN博主 E ROAD BY U 的原创文章 xff0c 遵循CC 4 0 BY SA版权协议 xff0c 转载请附上原文出处链接及本声明 原文链接 xff1a https blog csdn net E R
  • UART串口通信协议概述

    1 UART协议介绍 UART是一种通用串行数据总线 xff0c 用于异步通信 UART能实现双向通信 xff0c 在嵌入式设计中 xff0c 常用于主机与辅助设备通信 UART包括RS232 RS449 RS423等接口标准规范和总线标准
  • 串口发送通信---UART发送---STM32F4实现

    串口发送程序配置过程 xff08 HAL库 xff09 初始化串口相关参数 xff0c 使能串口 HAL StatusTypeDef span class token function HAL UART Init span span cla
  • 嵌入式Linux应用开发笔记:串口

    文章目录 目的 基础说明 开发准备 设备树 应用程序 应用程序与演示 代码 演示 总结 设备树文件 目的 串口 UART 是嵌入式设备中比较常用的功能 这篇文章将记录下应用程序中串口操作相关内容 这篇文章中内容均在下面的开发板上进行测试 新
  • mega328p-ADC,PWM,UART驱动

    ADC驱动 函 数 名 Ai Init 函数功能 Ai端口初始化 输入参数 void 输出参数 void 返 回 值 void 参考文档 void 创 件 人 程强刚 创建日期 2016 02 09 修改历史 void Ai Init vo
  • MicroPython串口数据转换技巧

    技巧一 还原从串口接收的HEX字符串 首先上官方文档 确认接收数据类型为bytes 串口读来的bytes类型HEX数据转换成HEX类型字符串转换函数 ByteToHex的转换 返回数据16进制字符串 def ByteToHex bins r
  • STM32双串口

    STM32双串口的使用 最近老是需要stm32通过串口去跟WiFi模块 蓝牙模块 openmv进行数据交互 然后需要用到stm32的串口调试 就把这个程序整理成一个工程 方便调试 实验目的 外设模块 WiFi模块 蓝牙模块 openmv 发
  • Verilog功能模块——Uart收发

    摘要 本文分享了一种通用的Uart收发模块 可实现Uart协议所支持的任意波特率 任意位宽数据 5 8 任意校验位 无校验 奇校验 偶校验 1校验 0校验 任意停止位 1 1 5 2 的数据传输 此模块需要搭配FIFO使用 以消除发送端和接
  • 一文看懂异步 FIFO 架构(二) 读写时钟独立的异步 FIFO

    目录 写在前面 亚稳态 解决时间 MTBF 和可靠性 同步 采样计数器 同步 解决可靠性问题 悲观报告 正确处理错误 架构 1 创建空 满条件 第一个解决方案 执行 时序考虑 往期系列博客 写在前面 在本系列的前一部分中 我们看到了如何使用
  • UART串口协议

    通用异步收发传输器 Universal Asynchronous Receiver Transmitter 通常称作UATR 是一种异步收发传输器 将数据由串行通信与并行通信间做传输转换 作为并行输入称为串行输出的芯片 UART是一种通用串
  • AWS SQS FIFO - 如何一次获取超过 10 条消息?

    目前我们想要拉下一个整个 FIFO 队列 并处理内容 如果有任何问题 将消息释放回队列中 问题是 目前 AWS 只给我们 10 条消息 并且不会再给我们 10 条消息 这是在 SQS 中获取批量消息的方式 多个 10 条最大消息请求 直到我
  • OSError: [Errno 11] 资源暂时不可用。这是什么原因造成的?

    背景 我有两个 python 进程需要相互通信 通信由名为 Pipe 的类处理 我为此创建了一个单独的类 因为大多数需要通信的信息都以字典的形式出现 因此 Pipe 实现了一个非常简单的协议来执行此操作 这是管道构造函数 def init
  • 启用并测试 UART 的本地环回

    我正在尝试进行 UART 内部环回测试并提出以下更改 include
  • 英特尔伽利略裸机 UART

    我想编写一些 hello world 程序裸机申请于英特尔伽利略木板 当然 使用 UEFI 打印文本 到 UART 1 效果很好 但我想 手动 访问 UART 而不需要 UEFI 的任何帮助 在 QEMU 中我的代码运行良好 h file
  • 完全通过 FIFO 连接到 MySQL 客户端

    在 Bash 脚本中 我想在多个顺序访问中保持 MySQL 会话打开 访问 MySQL 的常见方法是为每个 SQL 命令或命令集打开一个单独的会话 例如 mysql u user e show tables 此方法的限制是那些需要双重事务的
  • C语言UART通信(十六进制)

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

    我遇到一种情况 我需要检查 fifo 的另一侧是否已打开它 但是我不能使用 open 因为否则程序将开始执行操作 为什么我必须这样做 我有一个程序 监视器 来启动服务器程序 都是我创建的 监视器使用此 fifo 进行通信 因为监视器可以在服
  • Node.js fs.open() 在尝试打开超过 4 个命名管道 (FIFO) 后挂起

    我有一个 node js 进程 需要从不同其他进程提供的多个命名管道中读取数据作为 IPC 方法 我意识到在打开并创建来自四个以上 fifo 的读取流后 fs 似乎不再能够打开 fifo 并只是挂在那里 考虑到可以毫无问题地同时打开数千个文
  • 有队列实现吗?

    任何人都可以建议使用 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 它是一个具有先入先出特点的缓