【LIN】2.LIN总线通信机制深度解析:主从架构、五种帧类型与动态调度策略

参考文章:
Lin总线通信在STM32作为主机代码以及从机程序
基于STM32的LIN总线的实现
STM32F0-LIN总线通讯程序代码 主从调试OK
LIN协议通信DEMO及源码剖析

前文已讲解关于LIN帧代码如何实现:【LIN】1.LIN通信实战:帧收发全流程代码实现

帧类型

在了解了网上的LIN代码就会发现,所谓的LIN主机程序和从机程序大概是分为四个场景如下:

1. 主机:发送ID -> 从机:响应数据 -> 主机:接收数据
2. 从机:接收ID -> 发送数据
(这描述的是同一个过程,只是从主从两个视角看)

  • LIN帧类型无条件帧(Unconditional Frame)

  • 过程详解

    1. 主机(Master):发送帧头(Header)。这个Header里最关键的就是受保护的标识符(PID)。这个PID决定了哪个从机需要响应,以及这个帧的含义是什么(例如,0x30代表请求车速信号)。
    2. 从机(Slave):总线上所有从机都接收到了这个Header。每个从机都有自己的调度表(Schedule Table)信号处理程序,它们会检查这个PID。
      • 如果这个PID与自身某个发布(Publish) 任务的PID匹配(例如,车速传感器从机被配置为对PID 0x30进行响应),则该从机负责回复。
    3. 从机(Slave):在规定的响应时间内,发送响应(Response),即数据场(1-8字节) + 校验和场
    4. 主机/其他从机(Master/Other Slaves):接收这个响应。主机或其他需要该数据的从机(配置为订阅(Subscribe) 此PID的节点)会从数据场中解析出具体的信号(如车速值=50km/h)。
  • 这是LIN总线最主要的数据广播机制。

3. 主机:发送ID+数据 -> 从机:接收数据并处理
4. 从机:接收ID+数据 -> 处理数据
(这描述的也是同一个过程)

  • LIN帧类型:这也是一种无条件帧,但数据流向是主机到从机
  • 过程详解
    1. 主机(Master):发送帧头(Header) + 数据场(Data Field) + 校验和场(Checksum)注意:这里主机发送了完整的帧!
    2. 从机(Slave):所有从机接收整个帧。它们通过PID来判断这个帧是发给谁的、是干什么的。
      • 例如,主机发送一个PID为0x31的帧,数据场包含一个字节0x55,意思是“打开空调”。
      • 配置为订阅(Subscribe) PID 0x31的空调控制器从机,会识别这个PID,然后读取数据场,解析出信号,并执行相应的操作(打开空调)。
    3. 响应问题从机通常不会在总线上进行响应(ACK)。LIN协议没有规定应用层必须应答。如果主机需要确认命令是否被执行,它必须在后续的调度中,再发起一个查询帧(第一种方式),去读取从机的某个状态信号(例如,读取空调开关状态PID),来间接确认。

由此我们知道了,原来网上所说的主从机代码指的是无条件帧,那么其它帧又是怎么用到的,下面从实际场景出发,了解LIN的5种帧

一、 LIN核心思想:主从结构与单线通信

LIN(Local Interconnect Network)是一种低成本、低速率的车载网络协议,用于实现汽车中的分布式电子系统控制。

  • 核心特点
    • 单线通信:仅使用一根信号线,极大降低了线束成本和复杂度。
    • 主从结构:通信永远由主节点(Master) 发起,从节点(Slave) 响应。从节点不能主动发送数据。
    • 基于调度表:主节点内部有一个像“歌单”一样的调度表,循环决定下一刻要发送哪个帧,保证了通信的有序性。

二、 五种关键“帧”与沟通机制

LIN的“帧”是通信的基本单元。一个完整的帧由帧头(Header)响应(Response) 组成。帧头由主节点发送,响应由从节点发送。

我们可以从三个维度来理解LIN的通信方式:帧类型调度策略标识符用途

下面我们通过一个扩展的汽车车窗控制场景来详细讲解这五种方式是如何协同工作的。

场景角色

  • 主机(Master):车身控制模块(BCM)。它是车门LIN总线的主控节点。
  • 从机1(Slave 1):主驾驶车门开关模块(内部有LIN芯片)。它负责报告开关状态。
  • 从机2(Slave 2):副驾驶车门控制模块(内部有LIN芯片和电机驱动器,带防夹功能)
  • 诊断仪:维修设备(通过CAN网关连接)

1. 无条件帧 (Unconditional Frame) - 基石

这是LIN最常用、最基本的通信模式,用于周期性数据交换。

  • 理论主机发送帧头(含PID),指定从机回复数据;或主机发送完整帧(含数据)向从机下达命令。

  • 实践(场景:正常控制)

    • 步骤a (主机问,从机答):BCM发送帧头 PID=0x21(查询开关状态)。开关模块(从机1)响应数据 Data=0x02(二进制00000010,表示“副驾升起”按钮被按下)。
    • 步骤b (主机发命令):BCM解析后,发送一个完整帧PID=0x32(控制副驾车窗) + Data=0x02(命令:上升)。副驾模块(从机2)接收并执行,不产生总线响应
    • 步骤c (主机确认):BCM发送帧头 PID=0x33(查询车窗状态)。副驾模块响应 Data=[50, 0x00](位置50%,状态正常)。
  • 沟通方式:纯粹的“发布-订阅”模型。BCM“订阅”了开关状态,开关模块“发布”该状态。副驾模块“订阅”了控制命令,BCM“发布”该命令。


2. 事件触发帧 (Event Triggered Frame) - 优化师

用于处理多个从机可能发生、但通常不会同时发生的事件,以节省带宽。

  • 理论:主机发送一个公共PID,多个从机被配置可响应它,但只有状态发生变化的从机才会实际回复。若多个从机同时回复导致冲突,主机会退回到轮询模式。

实践(场景:防夹功能激活)
副驾车窗在上升过程中遇到障碍物,电机电流陡增,模块检测到阻力过大,判定为防夹事件。

  • 传统方式(低效):BCM需要不断轮询每个车门的状态帧(PID=0x33, 0x34, 0x35…)来检查是否有异常,即使大部分时间都没有事件发生,这浪费了总线带宽。
  • 高效方式(事件触发帧):BCM发送一个公共的询问帧,谁有事谁回答。

过程如下:

  1. BCM 发送一个特殊的Header,其 PID=0x40。这个PID在LDF中被定义为事件触发帧,它对应着一组可能发生事件的从机状态(比如,副驾车窗状态、天窗状态、尾门状态等都属于“事件源”)。
  2. 多个从机(副驾模块、天窗模块…)都配置为可以响应这个PID。
  3. 此时
    • 天窗模块状态无变化,它选择保持沉默。
    • 副驾模块因为刚刚触发了防夹功能,状态发生了重要变化,它立刻在响应时隙内回复数据。它回复的数据就是它自身的状态数据(例如 Data = [75, 0x01],位置75%,防夹触发标志位为1)。
  4. BCM 接收到响应,解析后知道是副驾车窗发生了防夹,它可能会记录事件、甚至让仪表盘显示一个警告提示。

冲突处理:如果极端情况下,副驾车窗和天窗同时发生事件并都回复,会导致总线冲突和校验和错误。BCM检测到错误后,就会退出事件触发模式,转而逐一发送每个从机专属的PID(0x33问副驾,0x34问天窗…)来精确定位所有事件源。


3. 诊断帧 (Diagnostic Frame) - 外科医生

用于执行点对点的深度访问,如读取故障码、写配置参数等。

  • 理论:使用保留的专用PID0x3C0x3D),遵循UDS等标准诊断服务格式,数据长度固定为8字节。

实践(场景:读取详细故障数据)
车辆维修时,技师需要更详细的信息,而不仅仅是“防夹触发了”这个状态位。他需要知道历史故障码、电机堵转电流值等深层数据。这需要通过诊断帧来实现,这是一种点对点、高可靠性的通信。

过程如下:

  1. 诊断仪(通过CAN)向BCM发送一个诊断请求:“读取副驾车窗控制模块的故障码(服务ID: 0x22)”。
  2. BCM 作为LIN总线的主机,充当了网关的角色。它将来自CAN的请求翻译成LIN总线上的诊断帧。
  3. BCM 在LIN总线上发送一个Header,其 PID=0x3C。这是一个专用的诊断请求标识符,所有从机都知道这个PID用于诊断。
  4. BCM 紧接着发送数据场(8字节),这8字节符合UDS(统一诊断服务)标准格式:
    • Byte 0: 0x02 — 表示后续有效数据长度。
    • Byte 1: 0x22 — 服务ID,0x22代表“按标识符读数据”。
    • Byte 2 & 3: 0xF1 0x90 — 一个自定义的诊断标识符,代表“读取第一个防夹事件的历史数据”。
    • 剩余字节填充为0x00。
  5. 副驾模块 识别到 PID=0x3C 是诊断请求,并且数据场中的标识符 0xF190 是给自己的。它准备诊断响应数据。
  6. BCM 随后再发送一个Header,其 PID=0x3D。这是一个专用的诊断响应标识符
  7. 副驾模块 响应这个 0x3D 帧,回复8字节的诊断数据:
    • Byte 0: 0x04 — 后续有效数据长度。
    • Byte 1: 0x62 — 对 0x22 请求的响应(0x22 + 0x40)。
    • Byte 2 & 3: 0xF1 0x90 — 回显请求的标识符。
    • Byte 4: 0x05 — 故障码,例如0x05代表“防夹功能激活”。
    • Byte 5: 75 — 发生时的车窗位置(75%)。
  8. BCM 接收到响应后,再通过CAN总线转发给诊断仪。技师就在诊断仪屏幕上看到了详细的故障信息。

4. 偶发帧 (Sporadic Frame) - 调度策略

核心思想: 这是一种优化带宽的高级调度策略。主机(Master)不会死板地周期性地发送每一个帧,而是只在确信该帧所携带的数据有可能会更新时,才在调度表中插入这个帧。

为什么需要它?
想象一下,车窗从完全关闭到完全打开需要5秒钟。如果BCM以100ms的周期去查询车窗位置(PID=0x33),那么在5秒内会发送50次查询,但回复的位置值可能只是从0, 2, 4, 6… 慢慢变到100。很多次查询返回的数据变化极小,这是一种带宽浪费。

“偶发”如何工作?

  1. 条件触发:主机BCM知道,只有当你按下开关(PID=0x21有变化) 或者收到事件触发帧(PID=0x40报告了事件) 时,车窗位置才会开始快速变化。
  2. 动态插入:当BCM检测到上述“触发条件”时,它就会在接下来的几个调度周期里,临时、高频地插入查询车窗位置的帧(PID=0x33)。
  3. 停止查询:当BCM发现位置数据在连续几次查询中不再变化(比如车窗已经到达目标位置),它就会停止发送这个查询帧,从而节省出带宽给其他任务。

场景举例(优化后的调度):

  • 常态(车窗静止):BCM的调度表主要循环发送:0x21(问开关)、0x22(问门锁)… 它不发送 0x33(问车窗位置),因为位置没变化,问了也是白问。
  • 按下开关:BCM通过 0x21 得知用户命令。
  • 动态调整:BCM立即修改调度表,在未来5秒内,高频循环:0x21 -> 0x32(发命令)-> 0x33(问位置) -> 0x21 -> 0x32 -> 0x33
  • 恢复常态:BCM通过 0x33 的响应发现位置已达到100%且不再变化,于是从调度表中移除 0x33,恢复到此前的低频查询模式。

所以,“偶发帧”不是一种新帧,它仍然是无条件帧,只是它的发送时机是“偶发的”、“有条件的”,而非周期性的。这是一种主机软件的智能调度算法。


5. 保留帧 (Reserved Frame) - 标识符分类

核心思想: 这是指LIN协议规范中为未来用途预留的标识符(PID)。这些PID有特定的值,不能用于普通的无条件帧。

为什么需要它?
为了保障协议的扩展性和兼容性。LIN联盟预先规定好哪些PID是留给未来新功能或特殊功能的,这样所有厂商的芯片和软件都会遵守这个规则,避免冲突。

常见保留帧:

  • 主请求帧 (Master Request Frame): PID = 0x3C
  • 从响应帧 (Slave Response Frame): PID = 0x3D
    • 这两个PID就是我们之前讲的诊断帧的专用通道。它们被“保留”用于诊断目的。
  • 其他保留范围:协议还规定了其他一些范围的PID值(例如0x30-0x31之间的某些值)也被保留,用户不能自定义使用。

场景举例:
当BCM需要与副驾模块进行诊断通信时,它必须使用保留的PID:0x3C0x3D。它不能自己定义一个比如PID=0x40来做诊断,因为:

  1. 0x40可能已经被你用作事件触发帧了。
  2. 副驾模块的厂商是按照标准协议开发的,它的软件只认 0x3C0x3D 是诊断帧。如果你用 0x40,它根本不会把它当成诊断请求来处理。

所以,“保留帧”指的是那些使用了保留PID的帧,这些帧用于特定目的(主要是诊断),普通应用层通信不能占用这些PID。

三、 总结与协作图景

在真实的汽车网络中,这五种方式绝非孤立工作,而是紧密协作,形成一个高效的整体。它们的关系如下图所示:

LIN通信核心概念
按帧类型划分
按调度策略划分
按PID用途划分
无条件帧
最基础的通信单元
事件触发帧
用于处理多从机事件
诊断帧
使用专用PID进行配置与诊断
周期帧
按固定周期调度
偶发帧
仅在数据可能更新时调度
自定义PID
用于应用层通信
保留PID
预留给特殊功能如诊断

为了更清晰地理解,我们可以用以下表格来总结所有这些概念在车窗控制场景中的具体体现:

概念分类具体类型目的在车窗场景中的具体示例
帧类型无条件帧基础数据交换PID=0x21(查询开关状态)
PID=0x32(发送升降命令)
PID=0x33(查询车窗位置)
事件触发帧高效处理多从机事件PID=0x40(广播查询,谁有异常事件谁响应)
诊断帧配置、诊断、读故障码使用PID=0x3C(主请求)和0x3D(从响应)读取详细防夹故障码
调度策略周期调度固定时间间隔查询每100ms查询一次开关状态(PID=0x21
偶发调度优化带宽,动态查询仅在收到升降命令后,才临时高频查询车窗位置(PID=0x33
PID用途自定义PID用于普通应用功能0x21, 0x32, 0x33, 0x40 等,由系统设计师定义
保留PID保证兼容和扩展0x3C, 0x3D 等,协议规定只能用于诊断,不可另作他用

调度表(Schedule Table)

如果说LIN总线上的各种帧(无条件帧、事件触发帧等)是乐手们演奏的音符,那么调度表就是主机(Master)手中的指挥棒乐谱。它规定了在什么时间、由谁来演奏哪个音符,确保了整个LIN网络通信的井然有序,避免冲突。

一、 调度表是什么?

调度表是主机节点(在我们的场景中就是BCM)内部的一个定时任务列表。它定义了:

  1. 发送顺序:帧与帧之间的先后执行顺序。
  2. 时间基准:每个帧或每一组帧之间的时间间隔(例如,每个帧槽Frame Slot的持续时间)。

它的本质是一个无限循环的“歌单”,主机CPU会严格按照这个歌单,周而复始地依次发送各个帧的Header,从而 orchestrate(协调)整个总线的通信。

二、 调度表里有什么?

一个调度表由多个调度表条目(Schedule Table Entry) 组成。每个条目至少包含两样东西:

  1. 要发送的帧:例如,发送PID为0x21的Header(查询开关状态)。
  2. 该帧的延迟时间:发送完当前帧后,等待多长时间再发送下一个帧。这个时间称为帧时隙(Frame Slot)

一个简单的调度表示例(车窗控制基础版):

调度表条目帧的PID含义帧时隙(例如:10ms)
10x21查询主驾开关状态2个时隙(20ms后发下一个)
20x22查询门锁状态3个时隙(30ms后发下一个)
30x31控制主驾车窗(命令帧)2个时隙(20ms后发下一个)
40x32控制副驾车窗(命令帧)3个时隙(30ms后发下一个)

注:帧时隙必须大于该帧完成整个通信(Header + 最大可能Response时间)所需的时间,并为从机的处理留出余量。

三、 调度表如何工作?动态调度与场景结合

调度表并非一成不变。一个优秀的主机程序会管理多个调度表,并根据当前车辆状态在不同调度表之间切换,这就是“动态调度”的概念。结合我们的车窗场景:

1. 基础调度表(正常状态)
当车辆平稳运行,没有紧急事件时,BCM使用一个周期性的基础调度表。这个表就像背景音乐,持续循环,监控着基本状态。

  • 内容:主要包含高优先级的、需要持续监控的无条件帧
    • PID=0x21:频繁查询开关状态(用户随时可能操作)。
    • PID=0x22:查询门锁状态。
    • PID=0x33以较低频率查询车窗位置(因为位置不会瞬间变化,无需高频查询,这是偶发帧调度思想的体现)。
  • 特点:循环周期短,带宽占用稳定。

2. 事件触发调度(高效响应)
当BCM通过基础调度表收到开关命令(PID=0x21响应变化)或收到事件触发帧(PID=0x40)的报告时,它知道有“事情”发生了。

  • 动作:BCM可能会临时切换到一个更密集的调度表,或者在基础调度表中动态插入几个帧
  • 场景举例(用户按下开关)
    1. 基础调度表中,PID=0x21的响应数据从0x00变为0x02(副驾升起)。
    2. BCM识别到这个变化,判定为“事件”。
    3. 在接下来的几个循环中,BCM大幅提高 PID=0x32(控制副驾车窗)和 PID=0x33(查询副驾车窗位置)的发送频率。
    4. 这就相当于指挥棒突然指挥某几个乐手(副驾控制模块)快速、密集地演奏一段solo,以实现车窗的平滑移动和实时位置监控。
    5. 当车窗到达目标位置后,BCM再切回基础调度表。

3. 诊断调度表(精准干预)
当诊断仪接入(例如,CAN网关转发诊断请求给BCM),需要执行深度诊断时。

  • 动作:BCM会暂停当前的调度表,立即切换到一个专为诊断服务的调度表。
  • 场景举例(读取故障码)
    1. BMC收到诊断请求。
    2. BCM中断当前循环,切换到诊断调度表。这个表里只包含两个条目:
      • 发送 PID=0x3C + 8字节诊断请求数据。
      • 等待一个帧时隙后,发送 PID=0x3D 的Header,准备接收从机的诊断响应。
    3. 完成诊断通信后,BCM再切回之前的调度表,从中断处继续执行。
  • 特点:优先级最高,实时响应,执行完即退出。

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

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

相关文章

Maven的概念与Maven项目的创建

MavenMaven的概念依赖管理项目构建Maven安装Maven项目的创建Maven的第一个项目Maven的第二个项目Maven的概念 Maven 是 Apache 基金会推出的跨平台的项目管理工具,主要服务于基于Java平台的项目构建、依赖管理和项目信息管理,目前是 Java 生态中最主流的…

Mysql之binlog日志说明及利用binlog日志恢复数据操作记录

众所周知,binlog日志对于mysql数据库来说是十分重要的。在数据丢失的紧急情况下,我们往往会想到用binlog日志功能进行数据恢复(定时全备份+binlog日志恢复增量数据部分),化险为夷! 废话不多说,下面是梳理的binlog日志操作解说: 一、初步了解binlog MySQL的二进制日志…

windows安装Elasticsearch,ik分词器,kibana可视化工具

安装地址 elasticsearch安装地址: Past Releases of Elastic Stack Software | Elastic 分词器下载地址: https://github.com/infinilabs/analysis-ik?tabreadme-ov-file kibana下载地址: Past Releases of Elastic Stack Software | Elastic 注意:版本一定要统…

GaussDB 数据库架构师修炼(十八)SQL引擎-SQL执行流程

1 SQL执行流程查询解析:词法分析、语法分析、 语义分析 查询重写:视图和规则展开、基于规则的查询优化 计划生成:路径搜索和枚举、选出最优执行计划 查询执行:基于优化器生成的物理执行计划对数据进行获取和计算2 解析器和优化器S…

能源管理系统中的物联网数据采集:深度探索与操作指南

一、引言物联网(Internet of Things, IoT)作为数字化时代的核心基础设施,通过将物理世界的设备、物体与网络连接,实现数据的实时感知与交互。而数据采集作为物联网系统的 “神经末梢”,是整个体系运行的基础。本文将从…

Java实现一个简单的LRU缓存对象

LRU(Least Recently Used)算法的核心思想是:最近使用的数据将被保留,最久未使用的数据将被淘汰。这种策略适用于内存有限、但又需要高频访问的数据场景,比如缓存系统、页面置换算法等。mysql的缓冲池就是使用的LUR Inn…

整体设计 之定稿 “凝聚式中心点”原型 --整除:智能合约和DBMS的在表层挂接 能/所 依据的深层套接 之2

摘要三“式”三“心”三“物” 整数原型三段式表达 的 凝聚式中心点dot 、组织式核心元素位element和分析式内核基因座locus 三者分别以**“等号线(Arc)”**(动态关联)、**“边界线(Transition)”**&#…

vue.根据url生成二维码

文章目录概要QR码步骤1. 引入库2. 生成二维码3. 将二维码加入页面中用javascript库简化二维码生成1. 引入库2. 使用库生成二维码二维码美化和定制1. 调整大小2. 调整颜色3. 添加自定义形状和图案4. 添加logo性能优化与错误处理1. 减少不必要的计算2. 异步处理概要 生成 URL 二…

WPF+MVVM入门学习

最近在学WPF的MVVM,有两种方式实现,一种是自己实现,一种是借助MVVM框架,接下来通过一个医院自助打印报告机键盘输入界面来演示自己实现、框架CommunityToolkit和Prism的区别。 项目源码:https://gitee.com/cplmlm/Sel…

[e3nn] docs | 不可约表示(Irreps)

链接:https://docs.e3nn.org/en/latest/examples/examples.html docs:e3nn e3nn是一个用于构建欧几里得(E(3))等变神经网络的Python库,这意味着它们能自动保持三维旋转和反射的对称性。 该库使用不可约表示(Irreps)来描述数据变换方式&…

深入浅出 ArrayList:从基础用法到底层原理的全面解析(中)

四、ArrayList 常用方法实战 —— 从添加到遍历的全场景覆盖ArrayList 提供了数十个方法,但日常开发中常用的只有 10 个左右,我们按 “元素操作”“集合查询”“遍历方式” 三类来梳理,每个方法都附带示例和注意事项。4.1 元素添加&#xff1…

java后端如何实现下载功能

后端需要把要下载的若干文件 按 ZIP 格式编码成一段二进制字节流,然后以 Content-Type: application/zip Content-Disposition: attachment; filenamexxx.zip 的形式写进 HTTP 响应体。浏览器收到这段“ZIP 格式的字节流”后,就会弹出保存对话框&#xf…

AI生成技术报告:GaussDB与openGauss的HTAP功能全面对比

GaussDB 与 openGauss 的 HTAP 功能比较 前言 GaussDB集中式版本从505.2版本开始引入了HTAP混合负载功能,openGauss也从7.0.0 RC1版本开始引入了HTAP行列融合功能,加强了行存转列存的使用友好度,但两者的实现似乎存在不小的差异。 虽然文档…

小程序开发指南(四)(UI 框架整合)

✍讲解了微信小程序 UI 框架的使用方法和特点,根据项目需求选择合适的组件库。附有相应的组件库预览码,也是将所有的微信小程序原生组件库整合在一起方便后续开发的使用。如果有不好或者有错误的地方请告知!希望可以与大家相互的交流学习&…

golang 1.25.0 安装

wget https://golang.google.cn/dl/go1.25.0.linux-amd64.tar.gz tar -C /usr/local/ -xzf go1.25.0.linux-amd64.tar.gz ln -s /usr/local/go/bin/* /usr/bin/ go env -w GO111MODULEon go env -w GOPROXYhttps://goproxy.cn,direct

基于深度学习的人脸表情识别系统:YOLOv5/v6/v7/v8/v10模型实现与UI界面集成

基于YOLOv5/v7/v8的智能人脸表情识别系统:从算法原理到应用实现 表情识别的技术价值与挑战 人脸表情识别(Facial Expression Recognition, FERYOLOv5/v7/v8等深度学习算法构建高效的表情识别系统,并设计直观的UI界面集成方案。无论你是深度学习初学者还是有经验的开发者,…

初步了解多线程

系列文章目录 目录 系列文章目录 前言 一、进程 二、线程 1. 线程解决资源开销的方式 2. 线程和进程的联系和区别 三、多线程编程 1. 直观了解多线程 2. 线程的创建方式 1. 继承 Thread 重写 run() 方法 2. 实现 Runable 接口,重写 run() 方法 3. 继承 …

安卓Android低功耗蓝牙BLE连接异常报错133

安卓Android低功耗蓝牙BLE连接异常报错133 之前连接一直好好的,不知道为什么今天突然就连接不了蓝牙了,报错133,按照 找网上的说明总是说清除GATT缓存,其实并不是我的问题,最后看到这里https://softs.im/android-ble-%e8%bf%9e%e6%8e%a5%e9%94%99%e8%af%af133/ 有如下说明: 情…

【分治】快排与归并专题

分治思想 分(Divide):将待排序数组不断拆分为两个等长(或近似等长)的子数组,直到子数组长度为 1(天然有序)。 治(Conquer):递归排序每个子数组。 …