蓝牙基础:FIFO(First-In-First-Out)缓存区

在这里插入图片描述

在蓝牙通信中,FIFO(First-In-First-Out,先进先出)缓存区是解决数据传输中“速度不匹配”和“时序异步”问题的核心机制,广泛应用于蓝牙芯片内部、协议栈各层级及主从设备交互中。其核心作用是临时存储数据,平衡数据产生/处理速度与传输速度的差异,避免数据丢失或溢出。

一、蓝牙中FIFO缓存区的核心应用场景

1.蓝牙芯片内部的数据缓冲(硬件级FIFO)
蓝牙芯片(如射频RF、基带Baseband、主机控制器HCI等模块)内部集成硬件FIFO,用于暂存“待发送”或“刚接收”的数据,解决芯片内部不同模块的处理速度差异:
发送端:当MCU(或上层控制器)向蓝牙芯片发送数据时,若MCU输出速度快于蓝牙射频的无线发送速度(例如MCU一次性输出大量数据,而蓝牙受限于跳频、调制速率等无法即时发送),FIFO会临时存储数据,射频模块再按无线传输节奏从FIFO中“取数”发送,避免数据因来不及处理而丢失。
接收端:蓝牙射频模块接收到无线数据后,需先暂存到FIFO中(因射频接收是实时的,而基带/MCU可能在处理其他任务),待基带或MCU空闲时再从FIFO中读取数据,防止因“接收速度快于处理速度”导致的数据溢出。
2.HCI层的数据交互缓冲(协议级FIFO)
蓝牙协议栈中,主机(Host,如手机/MCU)与控制器(Controller,如蓝牙芯片)通过HCI(主机控制器接口)通信,HCI支持UART、USB、SPI等物理接口。由于HCI接口速率(如UART波特率)与主机/控制器的内部处理速率可能不匹配,FIFO在此处用于缓冲HCI数据包:
主机向控制器发送HCI命令/数据时,若主机发送速度快于控制器处理速度,控制器的HCI接收FIFO会暂存数据,控制器按自身节奏读取处理。
控制器向主机返回HCI事件/数据时(如接收的蓝牙数据包),若控制器产生数据的速度快于HCI接口传输速度,控制器的HCI发送FIFO会暂存数据,再通过HCI接口逐步发送给主机。
3.蓝牙连接中的数据包缓冲(应用级FIFO)
在蓝牙实际通信(如BLE连接、经典蓝牙ACL链路)中,FIFO用于缓冲上下行数据包,适配不同应用场景的吞吐量需求:
低功耗场景(BLE):BLE设备(如传感器)通常周期性发送小数据包,FIFO可暂存多个数据包,等待连接事件(Connection Event)到来时一次性发送,减少无线唤醒次数,降低功耗。
高吞吐量场景(如音频传输):经典蓝牙A2DP协议传输音频流时,由于音频数据连续产生,而蓝牙无线传输可能受干扰导致瞬时中断,FIFO可暂存一定量的音频数据(如几十ms的缓存),避免因短暂中断导致的音频卡顿。
4.多设备/多链路并发缓冲
当蓝牙主设备同时连接多个从设备(如BLE主设备连接多个传感器)时,主设备需分时与各从设备通信(时分复用)。此时FIFO可按链路分别缓存不同从设备的接收/发送数据,避免多链路数据混淆,确保各链路数据按顺序处理。

二、FIFO缓存区的关键设计考量

1.大小适配:FIFO容量需根据应用场景设计。例如,低功耗传感器(小数据包、低频率)可采用小容量FIFO(如32字节);音频传输需大容量FIFO(如4KB以上)避免卡顿。容量过大会浪费芯片资源,过小则易溢出(导致数据丢失)。
2.中断机制:当FIFO数据量达到阈值(如半满/空)时,触发中断通知MCU/主机及时处理(读取或填充数据),避免溢出或空读。
3.溢出保护:若FIFO已满,新数据需触发溢出标志(如硬件寄存器标记),并根据需求选择“丢弃新数据”或“覆盖旧数据”(部分场景),同时通知上层处理异常。

三、样例

以下FIFO 缓冲区实现了以下功能:初始化时创建了一个 540 字节(4320 bit)的缓冲区
write_bit方法用于向缓冲区写入单个 bit(0 或 1),get_recent_bits方法用于获取最近一个月的 bit 序列。
golang 实现细节说明:
缓冲区使用 bytearray 存储,每个字节存储 8 个 bit。head 变量跟踪下一个要写入的 bit 位置,遵循循环覆盖的 FIFO 原则,
当写入的数据量小于缓冲区总容量(4320 bit)时,直接返回所有已写入的数据。
当数据量达到或超过缓冲区总容量时,自动覆盖最旧的数据,始终保持最新的 4320 个 bit。
通过 byte_pos = head // 8 和 bit_pos = head % 8 计算当前操作的字节位置和 bit 位置。
package main

import (
“fmt”
)

const BUFFER_SIZE = 540 // 缓冲区大小(字节)
const TOTAL_BITS = BUFFER_SIZE * 8 // 总bit容量

// FIFOBuffer 实现FIFO机制的bit缓冲区
type FIFOBuffer struct {
buffer []byte // 存储bit的缓冲区
head int // 下一个要写入的bit位置
count int // 已写入的bit数量
}

// NewFIFOBuffer 创建一个新的FIFO缓冲区
func NewFIFOBuffer() *FIFOBuffer {
return &FIFOBuffer{
buffer: make([]byte, BUFFER_SIZE),
head: 0,
count: 0,
}
}

// WriteBit 写入一个bit到缓冲区
func (f *FIFOBuffer) WriteBit(bit int) error {
if bit != 0 && bit != 1 {
return fmt.Errorf(“bit必须是0或1”)
}

// 计算当前字节位置和bit位置
bytePos := f.head / 8
bitPos := f.head % 8// 写入bit(使用最高位到最低位的顺序存储)
if bit == 1 {// 置位操作f.buffer[bytePos] |= 1 << (7 - bitPos)
} else {// 清零操作f.buffer[bytePos] &^= 1 << (7 - bitPos)
}// 更新head位置(循环)
f.head = (f.head + 1) % TOTAL_BITS// 更新已写入计数(不超过总容量)
if f.count < TOTAL_BITS {f.count++
}return nil

}

// GetRecentBits 获取最近一个月的bit序列(FIFO机制)
func (f *FIFOBuffer) GetRecentBits() []int {
bits := make([]int, 0, f.count)

if f.count < TOTAL_BITS {// 数据还没存满,从0到count-1都是有效数据for i := 0; i < f.count; i++ {bytePos := i / 8bitPos := i % 8// 提取对应位置的bitbit := (f.buffer[bytePos] >> (7 - bitPos)) & 1bits = append(bits, int(bit))}
} else {// 数据已存满,从head位置开始循环读取所有数据for i := 0; i < TOTAL_BITS; i++ {pos := (f.head + i) % TOTAL_BITSbytePos := pos / 8bitPos := pos % 8bit := (f.buffer[bytePos] >> (7 - bitPos)) & 1bits = append(bits, int(bit))}
}return bits

}

func main() {
// 创建缓冲区实例
buffer := NewFIFOBuffer()

// 写入测试数据
for i := 0; i < 5000; i++ { // 写入5000个bit(超过缓冲区总容量4320)buffer.WriteBit(i % 2) // 交替写入0和1
}// 获取最近的bit序列
recentBits := buffer.GetRecentBits()
fmt.Printf("获取到的bit数量: %d\n", len(recentBits))
fmt.Printf("前10个bit: %v\n", recentBits[:10])
fmt.Printf("最后10个bit: %v\n", recentBits[len(recentBits)-10:])

}

四、结言

FIFO缓存区是蓝牙通信中“削峰填谷”的核心组件,通过平衡数据产生、传输、处理的速度差异,确保蓝牙在低功耗、高吞吐量、多设备并发等场景下的稳定运行。其设计需结合具体应用的数据包大小、速率、实时性需求,避免资源浪费或数据丢失。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/128758.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

避不开的数据拷贝(2)

接着上周未完的话题 避不开的数据拷贝。 既然处理器是通用机器&#xff0c;就没有专属数据&#xff0c;所以数据都要从别处调来&#xff0c;这就涉及到了数据搬运&#xff0c;就有了外设的概念。由于不同外设和处理器一起共享数据存储&#xff0c;时间会花在两方面&#xff1a…

第十四届蓝桥杯青少年组省赛 编程题真题题解

明天我就要考蓝桥杯省赛了&#xff0c;本蒟蒻已瑟瑟发抖&#xff0c;所以现在写一篇文章。 题目分别为&#xff1a; 1.​​​​​​B4270 [蓝桥杯青少年组省赛 2023] 特殊运算符 2.B4271 [蓝桥杯青少年组省赛 2023] 四叶玫瑰数 3.B4272 [蓝桥杯青少年组省赛 2023] 质因数的…

ThingsBoard配置邮件发送保姆级教程(新版qq邮箱)

一&#xff1a;登入qq邮箱(点击登入) 二:点击右上角设置 三:点击账号与安全 四:点击安全设置 检查POP3/IMAP/SMTP/Exchange/CardDAV 服务有没有开启如果没有按照引导进行开启&#xff0c;如果已开启点击生成授权码 按提示发送短信 五&#xff1a;复制授权码 六:登入系统管理员…

《光刻胶技术:原理、材料与应用》——光刻曝光技术及1纳米以下光刻技术路线设计

目录&#xff1a;一、光刻曝光核心控制参数和工艺条件二、光刻曝光剂量的精确控制三、投影式光刻焦距和焦深的精确控制新技术四、投影式光刻曝光前烘质控要点及对曝光过程的影响五、后烘工艺质控制要点及对曝光质量的影响和瑕疵纠正六、投影式光刻曝光的化学过程及对光刻胶的具…

Harbor 企业级实战:单机快速上手 × 高可用架构搭建 × HTTPS安全加固

文章目录一、建立项目二、命令行登录harbor&#xff08;配置在客户端即可&#xff09;三、给本地镜像打标签并上传到harbor四、下载harbor的镜像五、创建自动打标签上传镜像脚本六、修改harbor配置七、实现harbor高可用7.1 安装第二台harbor主机7.2 新建目标&#xff0c;输入第…

原创邮件合并Python工具使用说明(附源码)

一、软件概述邮件合并Python工具是一款专为办公场景设计的自动化文档处理工具。该工具能够高效地将Excel表格中的批量数据自动填充到预定义的Word模板文档中&#xff0c;完美解决了WPS办公软件中邮件合并功能缺失的问题。应用场景批量生成个性化邀请函、通知书自动化制作员工工…

数据结构(9)——排序

文章目录 目录 文章目录 前言 一、排序的概述 1.1排序相关概念 1.2常见的排序算法 二、排序的实现 2.1插入排序 2.2希尔排序 2.3选择排序 2.4堆排序 2.5冒泡排序 2.6快速排序 2.6.1霍尔版本 2.6.2填坑版 2.6.3前后指针版 2.6.4非递归版 2.6.5小区间优化 2.7归并排序 2.7.1非递归…

drippingblues靶机教程

一、信息搜集首先将其在VirtualBOX中安装&#xff0c;并将kali与靶机都设置为桥接模式紧接着我们扫描IP&#xff0c;来发现靶机地址&#xff0c;经过搜集&#xff0c;发现IP是192.168.1.9&#xff0c;我们去访问一下紧接着我们扫一下开放了哪些端口。发现开放了21、22以及80端口…

微软发布Project Ire项目:可自主检测恶意软件的人工智能系统

微软Project Ire项目利用AI自主逆向工程并分类软件性质微软近日公布了Project Ire项目&#xff0c;这是一个能够自主进行逆向工程并分类软件性质的人工智能&#xff08;AI&#xff09;系统。该系统由大型语言模型&#xff08;LLM&#xff09;驱动&#xff0c;通过使用反编译器等…

Nodejs》》Express》》模板引擎 express-art-template

art-template 、express-art-template 区别 art-template Express 的模板引擎 art-template express-art-template官网 # 安装npm install art-template express-art-template# 应用# view engine setup&#xff0c;这是关键的代码&#xff0c;第一个参数表示将使用模…

基于STM32H5的非循环GPDMA链表使用

0 说明 硬件平台:STM32H503RBT6 HAL库版本:STM32Cube_FW_H5_V1.3.01 GPDMA链表介绍 STM32H503的GPDMA支持直接编程和使用链表2种方式,直接编程也就是我们常用的DMA使用方式,通过指定目标地址、源地址然后进行单次或循环DMA处理。而使用链表则可以大大提高使用DMA的灵活性…

windows下使用nvm安装nodejs的版本问题

最近学习了一个开源项目&#xff0c;用的是vue2vue CLI 版本算是比较老了&#xff0c;其中有一个依赖node-sass 使用高版本的node安装各种问题&#xff0c;尤其是node-sass还依赖python的运行环境进行编译。开始使用的是nvm的最新版本 安装的node版本&#xff0c;但是高版本的n…

第05章 排序与分页

1.排序数据 1.1 排序规则 1.2 单列排序 1.3 多列排序 2.分页 2.1 背景 背景1:查询返回的记录太多了,查看起来很不方便,怎么样能够实现分页查询呢? 背景2:表里有 4 条数据,我们只想要显示第 2、3 条数据怎么办呢? 2.2 实现规则 分页原理:所谓分页显示,就是将数据…

创建MyBatis-Plus版的后端查询项目

记得编码和maven库的检测&#xff01;&#xff01;&#xff01; 1、maven库导入包<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupI…

Vulnhub----Beelzebub靶场

1.用kali作为攻击机 查找靶机的ip kaili和靶机都设为NAT模式 nmap -sn 192.168.51.0/24 2.扫描端口 nmap -p- 192.168.51.133 3.访问页面 4.扫目录 dirsearch -u http://192.168.51.133 5.访问index.php 查看源代码 6.将beelzebub用md5加密一下 d18e1e22becbd915b45e0e655…

极限相关的练习题

文章目录绪论具体内容130129128127126绪论 数学强化真的强度挺大&#xff0c;刷题稍微让人有点疲劳&#xff0c;所以写一写笔记&#xff0c;让自己找到一点正反馈&#xff0c;另外&#xff0c;也算是总结一下&#xff0c;总结总归是有点用处的吧。争取九月份结束强化&#xff…

n8n 入门指南:更适合跨境出海搞钱的AI智能体

如果你最近刷到 AI 圈的分享应该会发现——n8n 又火起来了。其实 n8n 早在 2020 年左右就被程序员玩过一波&#xff0c;当时很多人拿它做网站自动发邮件、消息转发之类的“流程自动化”。但那时候 AI 还没这么卷&#xff0c;大家也没觉得多有用。n8n为什么最近又翻红&#xff1…

疏老师-python训练营-Day40训练和测试的规范写法

浙大疏锦行 知识点回顾&#xff1a; 彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中展平操作&#xff1a;除第一个维度batchsize外全部展平dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭dropout 作业&#xff1a;仔细学习下测…

rosrun 和 roslaunch 区别

在 ROS&#xff08;机器人操作系统&#xff09;中&#xff0c;rosrun 和 roslaunch 是两个常用的命令行工具&#xff0c;用于运行节点和管理 ROS 程序&#xff0c;但它们的功能和使用场景有明显区别&#xff1a; rosrun 功能&#xff1a;用于启动单个 ROS 节点 特点&#xff1a…

力扣(删除有序数组中的重复项I/II)

在 LeetCode 的数组类题目中&#xff0c;有序数组去重是经典且高频的题型 。今天我们聚焦 删除有序数组中的重复项&#xff08;题号 26&#xff09; 和 删除有序数组中的重复项 II&#xff08;题号 80&#xff09; &#xff0c;用双指针技巧优雅解决&#xff0c;带你理清解题思…
推荐文章