news 2026/7/22 12:02:52

I2C总线自由数据格式与NACK机制深度解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
I2C总线自由数据格式与NACK机制深度解析

1. I2C总线核心机制深度剖析

在嵌入式系统开发中,I2C总线因其简洁的两线制(SDA数据线、SCL时钟线)和灵活的主从架构,成为了连接微控制器与各类低速外设(如传感器、EEPROM、实时时钟)的首选协议。然而,很多开发者仅仅停留在调用库函数完成读写操作的层面,对总线底层的工作机制,特别是那些直接影响通信可靠性和灵活性的高级功能,往往一知半解。这就好比只会开车,却不了解发动机的燃烧原理和变速箱的换挡逻辑,一旦遇到复杂路况或车辆异常,便束手无策。今天,我们就深入I2C的“发动机舱”,重点拆解两个关键但常被忽略的机制:自由数据格式和NACK生成逻辑,并系统梳理其四大操作模式,让你不仅能“开车”,更能“修车”甚至“改装车”。

自由数据格式(Free Data Format)打破了标准I2C帧必须以地址字节开头的惯例,允许数据直接传输,这为点对点高速数据流或私有协议通信打开了新思路。而NACK(无应答)位的生成与控制,则是实现通信流控、错误处理和传输终止的核心手段,理解其触发条件与配置方法,是构建健壮I2C通信系统的基石。同时,主/从、发送/接收四种基本模式的切换与协作,构成了I2C通信的骨架。本文将结合TI I2C模块的具体寄存器配置,从硬件信号时序到软件状态机管理,为你呈现一幅完整的I2C底层运作图景。

2. 自由数据格式:超越地址寻址的直连通信

2.1 格式定义与标准帧对比

标准I2C通信帧结构严谨,以起始条件(S)开始,紧随其后的是一个7位或10位的从机地址字节,以及1位数据方向位(R/W#)。只有在地址匹配成功后,后续的数据字节传输才会进行。这种设计完美支持了多从机的主从网络,但也在某些特定场景下引入了不必要的开销。

自由数据格式则是一种“轻量化”的变体。如图28-10所示,在起始条件之后,紧跟着的就是第一个数据字节,省去了地址和方向位。每个数据字节之后,依然会插入一个应答位(ACK),然后继续传输下一个8位数据。整个传输过程中,数据的方向(发送或接收)是恒定不变的,必须在通信开始前由主从双方协商确定。

这种格式的核心价值在于效率。对于点对点连接、且通信双方角色固定的场景(例如,一个专用的ADC芯片只向主控制器发送数据),每次传输都发送地址字节是冗余的。启用自由数据格式可以节省这些比特时间,在高速模式下(如Fast-mode Plus, 1MHz)能略微提升有效数据吞吐率。更重要的是,它为实现自定义的、非标准的简单串行协议提供了硬件基础,开发者可以利用I2C的物理层和部分链路层,实现更高效的私有通信。

2.2 配置方法与关键限制

在TI的I2C模块中,启用自由数据格式非常简单,只需将模式寄存器(I2CMDR)中的自由数据格式位(FDF)写为1即可。一旦启用,模块将按照前述的帧格式进行解析和生成。

注意:自由数据格式不支持数字回环模式(Digital Loopback Mode)。回环模式通常用于模块自检,将发送端与接收端在内部短接。由于自由数据格式没有地址寻址环节,在回环模式下无法建立标准的自检通信流程,因此硬件上禁止了此组合。若需测试,应使用标准寻址模式。

配置时,一个常被忽视的细节是传输方向的预先设定。因为帧中不包含R/W#位,模块无法通过帧信息动态切换方向。因此,必须在初始化时,通过配置I2CMDR寄存器中的主/从模式位(MST)和发送/接收模式位(TRX)来明确本次传输中,本模块是作为发送器还是接收器。这个方向在整个自由数据格式传输会话中必须保持一致。

2.3 典型应用场景与实操要点

自由数据格式并非通用解决方案,它的适用场景相对专一:

  1. 专用数据流传输:例如,一个配置好的数字温度传感器持续输出测量值,主设备只需周期性读取。在初始化阶段用标准格式配置好传感器后,后续的读数操作可以切换到自由数据格式以提升效率。
  2. 私有轻量级协议:在系统内部两个特定芯片之间,需要一种比SPI线多、比UART需要额外时钟线更折中的通信方式时,可以利用I2C物理层,启用自由数据格式,并定义自己的数据包结构(如包含命令码和长度的数据头)。

在实操中,切换格式需要谨慎。必须在总线空闲(BB位为0)且模块处于复位或就绪状态时,修改I2CMDR寄存器的FDF位。一个常见的流程是:先以标准格式完成设备寻址和初始配置,然后发送一个重复起始条件(Repeated START),在重复起始条件之后,主设备可以立即发送数据字节,从设备需提前配置为支持自由数据格式并处于正确的接收状态。

此外,由于没有地址广播,总线上只能有两个设备参与通信(一点对一点)。在多设备总线上使用自由数据格式,必须确保在切换期间,其他设备都不会响应,否则会造成总线冲突。通常的做法是通过GPIO控制一个片选线,在需要独占总线进行自由格式通信时,使能目标从设备,并让其他从设备进入高阻态。

3. NACK生成机制:通信流控与错误处理的核心

3.1 NACK的本质与作用

在I2C协议中,每个数据字节(包括地址字节)传输后的第9个时钟周期是应答周期。发送器(此时是数据提供方)会释放SDA线,而接收器则需要将SDA线拉低,以此作为应答信号(ACK)。如果接收器没有拉低SDA线(即SDA线保持高电平),则意味着一个“无应答”(NACK)。

NACK是一个强大的通信控制信号,其含义根据上下文有所不同:

  • 从设备不存在或故障:主设备发送地址后,若没有设备应答(NACK),通常表示总线上不存在该地址的从设备,或从设备故障。
  • 接收器无法接收更多数据:在数据字节传输阶段,接收器发送NACK,告知发送器“请停止发送数据”。这在主设备读取从设备数据时尤为重要,主设备通过发送NACK来终止读取。
  • 流控制:从设备作为接收方时,如果其内部缓冲区已满(RSFULL=1),可以通过发送NACK来通知主设备暂停发送,直到缓冲区有空闲。
  • 强制结束传输:在特定模式下,主动生成NACK可以作为一种提前结束通信序列的手段。

理解并正确配置NACK的生成条件,是避免通信挂死、实现优雅错误恢复的关键。

3.2 硬件NACK生成条件详解

TI I2C模块手册的Table 28-1清晰地总结了在各种模式下生成NACK的条件。我们可以将其归纳为几个核心场景:

场景一:从接收器模式(Slave Receiver Mode)当模块作为从设备且处于接收状态时,可以通过以下方式导致NACK发送:

  1. 禁止数据传输(STT = 0):在传输过程中,如果从设备软件上将开始条件位(STT)清零,模块将停止响应,并在下一个应答周期发送NACK。
  2. 设置NACKMOD位:这是一个主动控制位。在期望接收的最后一个数据位的上升沿之前,软件将NACKMOD位设置为1,模块会在该字节后的应答周期自动发送NACK。这是主设备读取从设备数据时,主设备作为接收方发出停止信号的典型方式(在主机模式下)。
  3. 允许溢出条件(RSFULL = 1):当接收移位寄存器已满,且数据接收寄存器(I2CDRR)未被读取时,RSFULL标志置1。此时若继续收到数据,���块将发送NACK。这是硬件流控制的体现。
  4. 复位模块(IRS = 0):将模块复位,自然会导致其停止应答。

场景二:主接收器模式(Master Receiver Mode)当模块作为主设备且处于接收状态时,情况更为复杂,且与重复模式(RM)位密切相关:

  • 重复模式开启(RM = 1)
    • 生成停止条件(STP = 1):软件设置STP位,模块会在完成当前字节传输后生成停止条件,并在之前发送NACK。
    • 设置NACKMOD位:与从模式类似,在最后一个期望数据位的上升沿前设置此位,主动发送NACK。
    • 复位模块(IRS = 0):强制复位。
  • 重复模式关闭(RM = 0)
    • 如果STP=1,模块会等待内部数据计数器(I2CCNT)递减到0,然后强制产生停止条件。在此过程中,计数器为0后接收的字节将触发NACK。
    • 设置NACKMOD位:作用同上。
    • 如果STP=0,则需要软件将其置1来生成停止条件,伴随NACK。
    • 复位模块(IRS = 0)

3.3 软件配置与“忽略NACK”模式

在软件层面,我们需要关注两个关键寄存器位:NACKMOD和IGNACK。

NACKMOD位位于I2CMDR寄存器中。如前所述,它是一个“计划性”NACK触发器。你需要在目标数据位的最后一个时钟上升沿之前将其置1。例如,主设备想从从设备读取3个字节,那么在开始读取第三个字节之前,就应将NACKMOD置1。当第三个字节传输完毕,进入应答周期时,主设备(作为接收方)便会自动发出NACK信号,通知从设备“发送结束”,随后主设备可以发出停止条件。这个时序非常关键,设置过早或过晚都会导致通信错误。

IGNACK位位于扩展模式寄存器(I2CEMDR)中。这是一个“容错”功能位。当它被置1时,模块将忽略从设备发来的NACK信号,并继续数据传输。这有什么用呢?有些老旧的或特殊的从设备可能无法在特定情况下(如内部忙)产生正确的ACK,但它们实际上能够继续处理后续数据。如果主设备一收到NACK就停止,通信就会失败。启用IGNACK模式后,主设备会“假装”收到了ACK,继续发送后续数据。但务必谨慎使用此功能,因为它掩盖了从设备的真实状态,可能导致数据覆盖或从设备状态不可知。通常仅在与明确不支持标准ACK的特定设备通信时才启用。

在编程时,一个可靠的模式是:在主设备接收数据的循环中,在读取倒数第二个字节后,立即设置NACKMOD位,然后读取最后一个字节。读取完成后,检查状态寄存器(I2CSTR)的NACKSNT位,确认NACK已成功发送,再发出停止条件(STP=1)。

4. I2C四大基础操作模式全解析

I2C模块可以扮演四种角色:主发送(Master Transmitter)、主接收(Master Receiver)、从发送(Slave Transmitter)、从接收(Slave Receiver)。理解这四种模式的进入条件、状态转换和时序控制,是编写稳定驱动的基础。

4.1 主发送器模式(Master Transmitter Mode)

这是所有主设备通信的起点。在此模式下,主设备控制SCL时钟,并主动向SDA线发送数据序列,该序列始于起始条件,包含从机地址(含R/W#位为0,表示写操作)和后续的数据字节。

核心行为与难点

  • 时钟控制:主设备生成所有SCL时钟脉冲。但当其需要“等待”时(例如,内部发送缓冲区空,XSMT=0),它会拉低SCL线,强制总线进入等待状态,直到它准备好下一个数据位。这就是I2C的时钟拉伸(Clock Stretching)特性,主设备同样支持。
  • 多主传输的陷阱:手册特别警告了配置为双主同时传输时的场景。在第一个主传输结束后,必须同时检测总线忙(BB)位和主设备状态(MST)位是否都已复位。如果仅检测BB位变为0就立即发起第二次传输,而此时MST位还未复位,那么第二个起始条件将无法发出,总线也不会被正确占用。这是因为硬件需要时间完全释放对总线的控制权。稳妥的做法是在BB变0后,增加一个短暂延时或循环检查MST位,确保其也为0。

实操代码片段示意(伪代码)

// 配置为主发送模式,设置从机地址 I2CMDR = (MST_MODE | TRX_MODE | ...); I2CSAR = slave_address; // 产生起始条件 I2CMDR |= STT_BIT; // 等待寄存器就绪(ARDY标志) while(!(I2CSTR & ARDY_BIT)); // 写入第一个数据字节(可能是寄存器地址) I2CDXR = data_byte; // 等待发送缓冲区空(TXRDY标志),以便写入下一个字节 while(!(I2CSTR & TXRDY_BIT)); I2CDXR = next_data_byte; // ... 发送更多数据 // 发送完成后,产生停止条件 I2CMDR |= STP_BIT;

4.2 主接收器模式(Master Receiver Mode)

主设备在此模式下接收来自从设备的数据。它必须从主发送器模式切换而来。即,主设备先以发送模式发出起始条件和从机地址(此时R/W#位为1,表示读),然后才切换到接收模式。

核心行为与难点

  • 模式切换:切换发生在发送完地址字节和R/W#位之后。硬件会自动完成这一转换。
  • 终止读取:主设备通过不发送最后一个字节的ACK(即发送NACK)来告知从设备“发送结束”。随后,主设备产生停止条件或重复起始条件。这是主接收模式最关键的步骤,通常通过设置NACKMOD位来实现。
  • 重复模式(RM)的妙用:当主设备预先不知道要接收多少数据时(例如,从设备返回的数据包长度信息包含在数据流本身),必须使用重复模式(RM=1)。在此模式下,主设备不会在内部数据计数器(I2CCNT)为0时自动停止,而是由软件在读取到足够数据后,主动设置STP位来终止传输。由于接收端是双缓冲的,主设备必须在读取倒数第二个数据后,就设置STP位,以确保在最后一个数据被移入接收寄存器后,能及时产生停止条件。

4.3 从发送器与从接收器模式(Slave Transmitter/Receiver Mode)

从设备模式相对被动,其时钟(SCL)完全由主设备提供。

  • 从接收器模式:这是所有从设备上电后的初始状态。从设备持续监听总线,等待自己的地址(或广播地址)。当地址匹配且R/W#位为0(写)时,它保持在此模式,准备接收主设备发来的数据。它也可以通过拉低SCL(在RSFULL=1时)来请求主设备等待。
  • 从发送器模式:当从设备地址被呼叫且R/W#位为1(读)时,它从从接收器模式切换为从发送器模式,准备向主设备发送数据。它同样可以拉低SCL(在XSMT=0时)来告知主设备“数据尚未准备好”。

从设备开发的关键在于中断处理。当地址匹配(AAS中断)、接收数据就绪(RXRDY中断)或发送缓冲区空(TXRDY中断)时,从设备的CPU需要及时响应,读取或写入数据寄存器(I2CDRR/I2CDXR),否则会导致溢出(RSFULL)或下溢(XSMT),通信超时失败。

5. 总线完整性与高级功能

5.1 仲裁机制与时钟同步

当多个主设备同时发起传输时,I2C通过仲裁机制确保只有一个主设备胜出。仲裁发生在SDA线上,遵循“线与”逻辑:输出低电平(0)的设备将覆盖输出高电平(1)的设备。因此,发送数据流二进制值最小的主设备��得仲裁。失败的主设备会立即切换为从接收器模式,并设置仲裁丢失(AL)标志。

仲裁过程依赖于时钟同步。所有主设备的SCL输出在总线上也是“线与”关系。第一个拉低SCL的设备启动低电平周期,其他设备必须跟随。SCL线将被低电平保持时间最长的设备所主导。这意味着,最慢的设备决定了总线的低电平周期,最快的设备决定了高电平周期。这种机制天然地允许低速从设备通过拉长低电平来“减慢”快速主设备,为自己争取处理时间。

5.2 低功耗与自由运行模式

  • 低功耗模式:通过系统级的外设掉电控制,可以关闭I2C模块的所有时钟,此时寄存器不可访问。这是系统深度睡眠时的状态。
  • 自由运行模式:通过设置FREE位为1,当调试器遇到断点时,I2C模块可以继续运行而不挂起总线。这对于调试与实时性相关的通信任务至关重要。如果FREE=0,则在断点处,如果SCL为低,模块立即停止并保持SCL低;如果SCL为高,则等待其变低后停止。

5.3 中断与DMA事件管理

I2C模块提供了丰富的中断源(AL, NACK, ARDY, RXRDY, TXRDY, SCD, AAS)来通知CPU关键事件。合理配置中断掩码寄存器(I2CIMR)并编写高效的中断服务程序(ISR)是保证实时响应的关键。例如,在主发送模式下,即使从机无应答,也会在起始条件后立即产生TXRDY中断,确保CPU能及时处理错误。

对于大数据量传输,使用DMA可以极大减轻CPU负担。I2C模块提供读(I2CREVNT)和写(I2CWEVNT)DMA事件,分别与RXRDY和TXRDY同步。需要注意的是,在10位地址、主发送、重复模式下,可能会在起始条件后、地址第一位发送前,产生一个“意外的”DMA事件。应用程序应忽略此事件,等待从机ACK确认后再启动DMA传输。

6. 寄存器精讲与配置实战

6.1 关键寄存器功能速查

I2C模块的寄存器是控制其行为的直接接口。以下是一些最核心的寄存器及其字段摘要:

寄存器缩写全称核心功能与关键位
I2CMDR模式寄存器总开关(IRS)、主从模式(MST)、发送接收(TRX)、自由数据格式(FDF)、重复模式(RM)、NACKMOD、起始(STT)、停止(STP)条件控制。
I2CSTR状态寄存器反映实时状态:总线忙(BB)、发送空(XSMT)、接收满(RSFULL)、地址匹配(AAS)、各种中断标志(AL, NACK, ARDY, RXRDY, TXRDY, SCD)。
I2CIMR中断掩码寄存器使能/禁止各中断源(ALEN, NACKEN, ARDYEN, RXRDYEN, TXRDYEN, SCDEN, AASEN)。
I2CDXR数据发送寄存器CPU或DMA写入待发送的数据。
I2CDRR数据接收寄存器CPU或DMA读取已接收的数据。
I2CSAR从机地址寄存器在主模式下,存放目标从机的7位或10位地址。
I2COAR自身地址寄存器在从模式下,存放本设备的7位或10位地址。
I2CCNT数据计数寄存器在非重复模式(RM=0)下,设置要传输的数据字节数。计数器为0时可能触发自动停止。
I2CEMDR扩展模式寄存器包含忽略NACK位(IGNACK)等扩展功能。

6.2 初始化与典型通信流程配置

一个稳健的I2C驱动初始化应遵循以下步骤:

  1. 模块软复位:将I2CMDR中的IRS位写0,确保模块处于已知的复位状态。
  2. 配置时钟预分频器(I2CPSC):根据系统时钟(VBUS_CLK)计算分频值,使模块时钟在6.7-13.3 MHz范围内。
  3. 配置时钟高低分频(I2CCKL, I2CCKH):根据目标I2C总线速率(如100kHz, 400kHz)计算高低电平周期。
  4. 配置自身地址(I2COAR):如果设备可能作为从机,则设置此寄存器。
  5. 配置引脚功能:通过I2CPFNC、I2CDIR等寄存器,确保SDA和SCL引脚被配置为I2C功能,而非GPIO。
  6. 使能模块:将I2CMDR中的IRS位置1,模块开始工作。
  7. 配置中断:根据需要使能I2CIMR中的相应中断位,并设置CPU的中断向量。

一次完整的主设备写操作流程(标准模式)

  1. 检查总线是否空闲(BB位为0)。
  2. 将目标从机地址写入I2CSAR。
  3. 配置I2CMDR:主模式(MST=1)、发送模式(TRX=1)、非重复模式(RM=0,如果知道长度)、设置数据计数器I2CCNT(可选)。
  4. 设置STT位,产生起始条件。
  5. 等待ARDY中断或轮询ARDY位,表示地址已发送。
  6. 将第一个数据字节(如寄存器地址)写入I2CDXR。
  7. 等待TXRDY中断或轮询TXRDY位,表示数据已从DXR移入移位寄存器,可以写入下一个数据。
  8. 重复步骤6-7,发送所有数据。
  9. 发送完成后,设置STP位,产生停止条件。
  10. 等待SCD中断或轮询SCD位,确认停止条件已产生。

7. 常见问题排查与调试技巧

7.1 通信失败问题速查表

现象可能原因排查步骤
总线死锁,SCL被拉低1. 从设备时钟拉伸过长。
2. 主设备在异常状态下复位,未释放总线。
3. 硬件短路或上拉电阻过大。
1. 用逻辑分析仪抓取时序,看哪个设备在持续拉低SCL。
2. 检查主设备程序,确保异常处理中包含总线恢复(发9个时钟)或复位序列。
3. 测量SCL/SDA电压,检查上拉电阻值(通常4.7kΩ @3.3V)。
主设备发送地址后无ACK1. 从机地址错误。
2. 从机未上电或故障。
3. 从机忙(如EEPROM在写周期)。
4. 总线电平或时序问题。
1. 核对从机数据手册的7位/10位地址格式,注意是否包含R/W位。
2. 测量从机电源和复位信号。
3. 查询从机状态寄存器(如有),或增加重试和延时。
4. 用示波器检查起始条件、地址数据波形是否干净,上升时间是否过快。
能收到ACK,但数据错误1. 时钟速率过快,从设备跟不上。
2. 电源噪声或地线干扰。
3. 软件读取I2CDRR/写入I2CDXR不及时。
1. 降低I2C总线频率(调整I2CCKL/H)。
2. 优化PCB布局,加强电源滤波,缩短走线。
3. 检查中断服务程序或轮询响应时间,确保在RSFULL/XSMT发生前完成操作。
仲裁频繁丢失(AL标志置位)1. 多主竞争,且本设备发送的数据值较大(二进制)。
2. 在总线忙(BB=1)时尝试发起传输。
1. 这是正常现象,检查AL中断处理程序是否正确,失败后是否妥善转为从模式或等待重试。
2. 在发起任何传输前,务必检查BB位。
NACKMOD设置后无效果设置NACKMOD位的时机不对。必须在最后一个期望数据位的时钟上升沿之前设置NACKMOD位。如果是在接收中断里设置,可能已经晚了。尝试在接收倒数第二个字节后立即设置。

7.2 调试工具与技巧

  1. 逻辑分析仪:是调试I2C的终极利器。设置好触发条件(如起始条件),可以清晰看到地址、数据、ACK/NACK位的完整波形,直观定位时序问题。
  2. 软件模拟:在初期,可以用GPIO模拟I2C时序,验证物理层连接和从设备基本功能。这有助于排除硬件驱动能力问题。
  3. 状态寄存器轮询:在关键操作(STT, STP, 写DXR, 读DRR)后,加入对I2CSTR中ARDY、BB、NACK等状态的检查与超时判断,使程序更健壮。
  4. 分步测试:先测试最简单的单字节读写,再测试多字节;先测试标准模式,再测试自由数据格式或高速模式。
  5. 上拉电阻:务必确保SDA和SCL线上有合适的上拉电阻(通常3.3V系统用4.7kΩ,5V系统用2.2kΩ)。电阻值过大会导致上升沿过缓,通信不可靠;过小会导致电流过大。对于长总线或多设备,可能需要减小阻值。

深入理解I2C总线的这些底层机制,��其是自由数据格式和NACK的灵活运用,能让你在面对复杂传感器、多设备总线管理或自定义通信协议时,拥有更强的掌控力和解决问题的能力。从看懂时序图到理解状态机,再到熟练配置寄存器,每一步都是构建稳定嵌入式系统的坚实阶梯。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/22 12:00:36

新能源集卡车头高压系统维修与安全操作指南

1. 新能源集卡车头维修核心要点解析新能源集卡车头与传统柴油车在维修思路上存在本质区别,维修人员必须建立"高压安全优先、数据驱动诊断"的新认知体系。我在参与多个新能源物流车队的技术支持中发现,90%的维修失误都源于对高压系统认知不足或…

作者头像 李华
网站建设 2026/7/22 11:59:13

车载智能座舱风冷散热设计:从基础原理到工程实战

1. 项目概述:从一则专利新闻到车载散热设计的深度思考 最近,一则关于“路畅科技取得座舱散热控制器相关专利”的消息在汽车电子圈里引起了我的注意。标题很技术化,核心点在于“风冷控制器增大散热面”和“风道对流提效率”。乍一看&#xff0…

作者头像 李华
网站建设 2026/7/22 11:57:48

3分钟搞定:用PostgreSQL版Northwind数据库开启你的SQL实战之旅

3分钟搞定:用PostgreSQL版Northwind数据库开启你的SQL实战之旅 【免费下载链接】northwind_psql Northwind sample database for postgres 项目地址: https://gitcode.com/gh_mirrors/no/northwind_psql 你是否正在寻找一个既经典又实用的数据库来练习SQL技能…

作者头像 李华
网站建设 2026/7/22 11:56:51

Cocos Creator 3.8 接入Taku

提前你的申请账号https://app.takuad.com/ SDK下载中心https://app.takuad.com/m/sdk/download Taku SDK接入指南 1.开屏广告 开屏广告容器 <FrameLayoutandroid:id"id/splash_ad_container"android:layout_width"match_parent"android:layout_height&…

作者头像 李华