jjzjj

I2C协议概述

长水曰天 2024-01-03 原文

目录

Introduction

I2C总线是一个世界标准的总线协议,目前在50多家公司生产的1000多个不同的集成电路中实现。此外,通用的I2C总线可用于各种控制架构,如系统管理总线(SMBus)、电源管理总线(PMBus)、智能平台管理接口(IPMI)、显示数据通道(DDC)和高级电信计算架构(ATCA)。

Features

  • 在消费电子产品、电信和工业电子产品中,几乎每个系统都包括:
    1.一些智能控制,通常采用单片机微控制器。
    2.通用电路,如LCD和LED驱动器,远程I/O端口,RAM, EEPROM,实时时钟或A/D和D/A转换器。
    3.面向应用的电路,如无线电和视频系统的数字调谐和信号处理电路,温度传感器和智能卡。
    为了充分利用这些相似性,使系统设计师和设备制造商都受益,同时最大限度地提高硬件效率和电路的简单性,飞利浦半导体(现在的恩智浦半导体)开发了一种简单的双向双线总线,用于高效的IC间控制。这种总线被称为Inter IC或I2C总线。所有兼容I2C总线的设备都包含一个片上接口,允许它们通过I2C总线直接相互通信。

  • 以下是I2C总线的一些特性:
    1.只需两条总线线路;一个串行数据线(SDA)和一个串行时钟线(SCL)。
    2.连接到总线的每个设备都是可通过唯一地址寻址的软件,并且始终存在简单的主/从关系;master可以作为主发射机或主接收器。
    3.它是一个真正的多master总线,包括碰撞检测和仲裁,以防止在两个或多个主机同时发起数据传输时发生数据损坏。
    4.串行、8位、双向数据传输在Standard-mode下可达100kbit /s, Fast-mode下可达400kbit /s, Fast-mode Plus下可达1mbit /s,高速模式下可达3.4 Mbit/s。
    5.串行、8位、单向数据传输在Ultra Fast-mode下高达5mbit /s。
    6.片上滤波拒绝总线数据线上的峰值,以保持数据完整性。
    7.可连接到同一总线的集成电路数量仅受最大总线电容的限制。

  • 下图展示了一个I2C总线应用的示例。

  • 微控制器的设计人员经常面临节省输出引脚的压力。I2C协议允许连接各种各样的外设,而不需要单独的寻址或芯片启用信号。此外,由于现有的外围设备种类繁多,所以包含I2C接口的微控制器在市场上更成功。

Standard-mode, Fast-mode and Fast-mode Plus I2C-bus protocols

1. SDA and SCL signals

  • SDA和SCL都是双向线路,通过电流源或上拉电阻连接到正电源。
  • 当总线空闲时,两条线路都是高电平。
  • 连接到总线上的设备的输出级必须有一个漏极开路或集电极开路来执行线与的功能。
  • I2C总线的数据传输速率在Standard-mode下可达100kbit /s, Fast-mode下可达400kbit /s, Fast-mode Plus下可达1mbit /s,高速模式下可达3.4 Mbit/s。总线电容限制了连接到总线的接口数量。
  • 对于单个master的应用,如果总线上没有会拉长时钟的设备,则主应用程序的SCL输出可以是推拉式驱动设计。
  • 下图为不同电源电压的设备共用同一总线的情况。

2. SDA and SCL logic levels

由于各种不同的技术设备(CMOS, NMOS,双极)可以连接到I2C总线,逻辑’ 0 ’ (LOW)和’ 1 ’ (HIGH)的级别不是固定的,并取决于VDD的相关级别。

3. Data validity

  • 要求SDA线路上的数据在SCL拉高时保持稳定。
  • 只有当SCL线路上的时钟信号为低时,SDA数据线的高或低状态才会改变。
  • 每个传输的数据位产生一个时钟脉冲。

4. START and STOP conditions

  • 所有事务都从START (S)开始,并由STOP §终止。当SCL为高时,SDA线上的从高到低的转换定义了一个START条件,当SCL为高时,SDA线上的从低到高转换定义了一个停止条件。
  • START和STOP条件总是由master生成。在START条件之后,总线被置为繁忙状态。在达到STOP条件后的一段时间内,认为该总线再次空闲。
  • 如果生成了重复的START (Sr)而不是STOP条件,总线将保持繁忙状态。在这方面,START (S)和重复START (Sr)条件在功能上是相同的。
  • 如果连接到总线的设备包含必要的接口硬件,则很容易检测START和STOP条件。然而,没有这种接口的微控制器必须在每个时钟周期内对SDA线采样至少两次以感知转换。

5. Byte format

  • 放在SDA上的每个字节必须是8位长。每次传输可以传输的字节数是不受限制的。每个字节后面必须有一个确认位(ACK)。数据传输首先从最高有效位(MSB)开始。
  • 如果slave在执行其他功能(例如服务内部中断)之前不能接收或传输另一个完整字节的数据,它可以将时钟线SCL保持在LOW状态,然后当slave准备好接收另一个字节的数据时,释放时钟线SCL,继续传输数据。

6. Acknowledge (ACK) and Not Acknowledge (NACK)

  • 确认发生在每个字节之后。确认位允许接收端向发送端发出信号,表示已成功接收到该字节,并且可以发送另一个字节。master产生所有的时钟脉冲,包括确认的第九个时钟脉冲。
  • 确认信号的定义如下:在第九个确认时钟脉冲期间,发送方释放SDA线,因此接收方可以将SDA线拉低,并在时钟脉冲的高周期内保持稳定的低电平,将其定义为应答信号(ACK)。
  • 不确认信号的定义如下:当SDA在第九个时钟脉冲期间保持高电平时,其被定义为Not Acknowledge信号(NACK)。然后,master可以生成一个STOP条件来终止传输,或者生成一个重复的START条件来启动新的传输。
    产生NACK有五个条件:
  • 总线上没有带有传输地址的接收器,因此没有设备响应应答。
  • 接收器无法接收或发送,因为它正在执行一些实时功能,并没有准备好开始与主机通信。
  • 在传输过程中,接收方获取它不理解的数据或命令。
  • 在传输过程中,接收方无法接收到更多的数据字节。
  • 主接收机必须向从发射机发出信号结束传输。

7. Clock synchronization

  • 两个master可以在一个空闲的总线上同时开始传输,必须有一种方法来决定哪一个master控制总线并完成它的传输。这是通过时钟同步和仲裁完成的。在单主系统中,不需要时钟同步和仲裁。
  • 时钟同步是通过I2C接口与SCL线的线与来完成的。这意味着SCL线路上的从高到低的转换会导致相关的主时钟开始计算它们的低周期,一旦主时钟变为低,它会保持SCL线路处于那个状态,直到达到时钟的高状态。然而,如果另一个时钟仍然在其低周期内,这个时钟的从低到高的转换可能不会改变SCL线路的状态。因此,SCL线路被有最长低周期的master保持在低电平。在这段时间内,低周期较短的master进入高电平等待状态。
  • 当所有相关的主时钟已经计算出他们的低周期,时钟线被释放并拉高。然后,主时钟和SCL线的状态之间就没有区别了,所有的主时钟开始计算它们的高周期。第一个完成其高周期的master会把SCL线再次拉低。
  • 这样就产生了一个同步的SCL时钟,其低周期由低电平时钟周期最长的master决定,其高周期由高电平时钟周期最短的master决定。

8. Arbitration

  • 仲裁与同步一样,只在系统中使用多个master时才需要协议的一部分。slave不涉及仲裁程序。只有当总线是空闲的时,master才可以进行发送。两个master可以在START条件的最小保持时间(tHD;STA)内生成一个START条件,从而在总线上产生一个有效的START条件。然后需要仲裁来决定哪一个master完成它的传输。
  • 仲裁是一比特一比特进行的。当SCL为高时,每个master检查SDA的电平是否与它发送的相匹配。这个过程可能需要对比很多位。只要传输是相同的,两个master实际上可以毫无错误地完成整个事务的传输。当master第一次尝试发送HIGH,但是检测到SDA级别是LOW时,其就知道它已经失去了仲裁并会关闭它的SDA输出驱动。另一个master继续完成传送。
  • 仲裁过程中不会丢失任何信息。丢失仲裁的master可以生成时钟脉冲,直到丢失仲裁的字节结束,并且在总线空闲时必须重新启动事务。
  • 如果master也合并了slave功能,并且在寻址阶段失去仲裁,则获胜的master可能正在试图寻址它。因此,丢失的master必须立即切换到它的slave模式。
  • 下图显示了两个master的仲裁过程。根据连接到总线的主机数量,可能会涉及到更多的问题。一旦生成DATA1的master的内部数据级别与SDA线路上的实际数据级别之间存在差异,则关闭DATA1输出。这不会影响获胜的master发起的数据传输。

  • 由于I2C总线的控制权完全取决于相互竞争的master发送的地址和数据,因此总线上没有中央主机,也没有任何优先级顺序。

9. Clock stretching

  • 时钟拉伸通过保持SCL行为低来暂停事务。直到再次以高电平方式释放该行,事务才能继续。
  • 时钟拉伸是可选的,事实上,大多数slave不包含SCL驱动程序,所以它们无法拉伸时钟。
  • 在字节级的传输中,设备可能能够以较快的速率接收字节数据,但是需要更多的时间来存储接收到的字节或准备另一个要传输的字节。在接收并确认一个字节之后,slave可以保持SCL为低电平,迫使master进入等待状态,直到slave准备好通过某种握手过程进行下一个字节的传输。
  • 在比特级的传输中,像微控制器这样具有或不具有有限I2C总线硬件的设备,可以通过延长每个时钟的低电平周期来减慢总线时钟。
  • 在高速模式下,这个握手特性只能在字节级的传输中使用。

10. The slave address and R/W bit

  • 数据传输遵循下图所示的格式。在START条件(S)之后,发送一个从地址。
  • 此地址7位的长度后跟了一个第八位是一个数据方向位(R/W):0表示一个传输(写),1表示一个数据请求(读)。数据传输总是由master生成的STOP条件(P)终止。
  • 但是,如果master仍然希望在总线上通信,它可以生成一个重复的START条件(Sr)并寻址另一个从节点,而不需要首先生成一个STOP条件。在这样的传输中,读/写格式的各种组合是可能的。

传输举例:

  1. 主-发送设备发送给从-接收设备。传输方向没有改变。从接收设备ACK每一个字节。
  2. 主设备在第一个字节之后立即读取从设备;在第一次应答后,主-发送设备变成了主-接收设备,从-接收设备变成了从-发射设备;第一个ACK仍然是由从设备产生的;主设备生成后续的ACK 停止条件由主设备生成,它在停止条件之前发送一个NACK。
  3. 组合传输格式,在传输中改变方向时,开始条件和从地址都要重复,而且R/W位要倒转;如果一个主-接收设备发送一个重复的开始条件,它就会在重复的开始条件之前发送一个NACK。

11. 10-bit addressing

  • 10位寻址扩展了可能地址的位数。具有7位和10位地址的设备可以连接到相同的I2C总线,7位和10位地址都可以在所有总线速度模式下使用。目前,10位寻址还没有得到广泛的应用。
  • 10位从地址由START条件(S)或重复START条件(Sr)后的前两个字节组成。第一个字节的前7位是组合1111 0XX,其中后两位(XX)是10位地址的两个最高有效位(MSB)。第一个字节的第8位是决定传输方向的R/W位。
  • 虽然保留地址1111 XXX有8种可能的组合,但只有1111 0XX这4种组合用于10位寻址。剩下的四种1111 1XX组合是为未来的I2C总线增强保留的。
    前面描述的7位寻址的所有读写格式组合都可以用10位寻址。
    这里有两个详细的例子:
  1. Master-transmitter transmits to slave-receiver with a 10-bit slave address
    开始条件后跟着10位从地址,每个从设备将从地址(1111 0XX)第一个字节的前7位与它自己的地址进行比较,并检测第八位(R/W方向位)是否为0;有可能有多个从设备匹配并生成应答信号(A1);把以上所有匹配从设备的地址与从地址(XXXX XXXX)第二个字节的8位进行比较,只有一个从设备地址匹配并生成应答信号(A2);匹配的从设备地址一直由主地址寻址,直到它接收到一个停止条件(P)或一个重复启动条件(Sr),并且它后面跟着一个不同的从属地址。
    具体地址如下图:
  2. Master-receiver reads slave-transmitter with a 10-bit slave address
    传输方向在第二个R/W位之后改变,在确认位A2之前,其过程和上面相同,重复启动条件(Sr)后匹配的从设备会记住它之前被寻址过;然后这个从设备检查Sr之后的第一个字节的前7位是否与开始条件之后的第一个字节相同,并检测第8位(R/W)是否为1,如果匹配,从设备认为它已经作为一个发送器被寻址并生成确认A3;从发送设备保持寻址,直到它收到一个停止条件(P)或直到它收到另一个重复启动条件(Sr),且后面跟着一个不同的从设备地址。

12. Reserved addresses

为下表所示的目的保留了两组的8地址(0000 XXX和1111 XXX)。

13. General call address

  • 广播寻址用于同时寻址连接到I2C总线的每个设备,如果设备不需要广播提供的任何数据,它可以NACK来忽略广播地址;如果设备确实需要来自广播的数据,它就会对广播地址进行ACK,并作为一个slave接收设备。

  • 如果多个设备都发出了响应,主设备实际上并不知道有多少设备回应;每个能够处理此数据的从接收设备都会对第二个和后面的字节ACK,一般广播地址的含义总是在第二个字节中指定。(如下图)

  • 有两种情况需要考虑,最低有效位B为0,或最低有效位为1。

  1. LSB = 0:
    • 0000 0110 (06h):通过硬件复位和写从设备可编程部分;
    • 当接收到这2字节序列时,从设备回应广播地址复位,并接收其地址可编程部分。
    • 必须采取预防措施,以确保设备在施加电源电压后不会拉低SDA 或SCL,因为这些低电平会阻塞总线。
    • 0000 0100 (04h):通过硬件编写从地址的可编程部分。行为如上述,但设备不重置。
    • 0000 0000 (00h):此代码不允许用作第二个字节。
  2. LSB = 1:
    • 当第B位为1时,2字节序列是一个硬件通用调用。
    • 这意味着序列是由硬件主设备传输的,例如键盘扫描器,它可以通过编程传输所需的从地址。
    • 由于硬件主设备事先不知道消息必须传输到哪个设备,因此它只能生成这个硬件通用调用和它自己的地址,并将其标识给系统。
    • 第二个字节中剩下的7位包含硬件主设备地址;这个地址被一个连接到总线的智能设备(例如,一个微控制器)识别,然后总线接受来自硬件设备的信息。

14. Software reset

  • 在通用调用(0000 0000)之后,发送0000 0110 (06h)作为第二个字节导致软件复位。此特性是可选的,并不是所有设备都响应此命令。在接收到这个2字节序列后,所有设计来响应通用呼叫地址的设备复位,并接收其地址的可编程部分。
  • 必须采取预防措施,以确保在施加电源电压后,设备不会拉下SDA或SCL线路,因为这些低电平将阻塞总线。

15. START byte

  • 微控制器与I2C总线连接有两种方式。
  • 一个带有片上硬件I2C总线接口的微控制器可以被编程为只被来自总线的请求中断。当设备没有这样的接口时,它必须通过软件不断地监控总线。
  • 显然,微控制器监视或轮询总线的次数越多,用于执行其预期功能的时间就越少。因此,在快速的硬件设备和依赖于软件轮询的相对较慢的微控制器之间存在速度差异。在这种情况下,数据传输之前可以使用一个比正常情况长得多的start过程,这个过程比正常情况要长得多。
  • 启动过程包括:一个启动条件(S)、一个起始字节(0000 0001)、确认时钟脉冲(ACK)、重复START条件(Sr)。
  • 在需要总线访问的master机传输了START条件S之后,就传输了START字节(0000 0001)。因此,另一个微控制器可以以较低的采样率对SDA行进行采样,直到START字节中的7个零中的一个。
  • 在SDA线上检测到这个低电平后,单片机可以切换到一个更高的采样率,找到用于同步的重复启动条件Sr。硬件接收器在收到重复启动条件Sr时重新设置,因此忽略开始字节。
  • 在开始字节之后产生一个与ACK相关的时钟脉冲,这样做是为了与总线上使用的字节处理格式相一致,不允许任何设备确认开始字节。

16. Bus clear

  • 在一些概率较低的情况下,时钟(SCL)会一直卡在低电平,如果你的I2C设备有硬件复位输入,优先考虑使用硬件复位信号复位总线。如果I2C设备没有硬件复位输入,则对I2C设备循环上电,激活内部强制POR (power - on reset)电路。
  • 如果数据线(SDA)一直卡在低电平,master应该发送九个时钟脉冲,控制总线拉低的设备应该在这9个时钟内释放它。如果没有效果,则使用硬件复位或循环电源来清除总线。

17. Device ID

  • 设备ID字段(参见图20)是一个可选的3字节只读(24位)字,给出以下信息:
    1.12位包含制造商名称,每个制造商唯一(例如,NXP)。
    2.9位部件标识,由制造商分配(例如,PCA9698)。
    3.3位模具修改,由制造商指定(例如,RevX)。
  • 设备ID是只读的,在设备中是硬连接的,可以通过以下方式访问:
    1.开始条件(S)。
    2.主机发送保留设备ID I2C总线地址,其后是R/W位设置为“0”(写):“1111 1000”。
    3.主机发送从设备可以识别的I2C总线slave地址。LSB是“Don ’ t care”值。只有一个设备可以识别这个字节(具有I2C总线从地址的设备)。
    4.主机发送一个重新启动条件(Sr)。
    5.主机发送保留设备ID I2C总线地址,后面跟着R/W位设置为“1”(读):“1111 1001”。
    6.接着为设备ID读取,从12个制造商位(第一个字节+第二个字节的高四比特)开始,接着是9个部分标识位(第二个字节的4个低四比特 +第三个字节的高五比特),然后是3个模具修改部分(第三个字节的低三比特)。
    7.主机通过抓取最后一个字节来结束读取序列,从而重置从设备状态机,并允许master发送STOP条件。
    备注:通过发送NACK可以随时停止读取设备ID。

有关I2C协议概述的更多相关文章

  1. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  2. 阿里云RDS——产品系列概述 - 2

    基础版云数据库RDS的产品系列包括基础版、高可用版、集群版、三节点企业版,本文介绍基础版实例的相关信息。RDS基础版实例也称为单机版实例,只有单个数据库节点,计算与存储分离,性价比超高。说明RDS基础版实例只有一个数据库节点,没有备节点作为热备份,因此当该节点意外宕机或者执行重启实例、变更配置、版本升级等任务时,会出现较长时间的不可用。如果业务对数据库的可用性要求较高,不建议使用基础版实例,可选择其他系列(如高可用版),部分基础版实例也支持升级为高可用版。基础版与高可用版的对比拓扑图如下所示。优势 性能由于不提供备节点,主节点不会因为实时的数据库复制而产生额外的性能开销,因此基础版的性能相对于

  3. ruby - HTTP POST 上的 SSL 错误(未知协议(protocol)) - 2

    尝试通过SSL连接到ImgurAPI时出现错误。这是代码和错误:API_URI=URI.parse('https://api.imgur.com')API_PUBLIC_KEY='Client-ID--'ENDPOINTS={:image=>'/3/image',:gallery=>'/3/gallery'}#Public:Uploadanimage##args-Theimagepathfortheimagetoupload#defupload(image_path)http=Net::HTTP.new(API_URI.host)http.use_ssl=truehttp.verify

  4. 物联网MQTT协议详解 - 2

    一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su

  5. 网络实验之RIPV2协议(一) - 2

    一、RIPV2协议简介  RIP(RoutingInformationProtocol)路由协议是一种相对古老,在小型以及同介质网络中得到了广泛应用的一种路由协议。RIP采用距离向量算法,是一种距离向量协议。RIP-1是有类别路由协议(ClassfulRoutingProtocol),它只支持以广播方式发布协议报文。RIP-1的协议报文无法携带掩码信息,它只能识别A、B、C类这样的自然网段的路由,因此RIP-1不支持非连续子网(DiscontiguousSubnet)。RIP-2是一种无类别路由协议(ClasslessRoutingProtocol),支持路由标记,在路由策略中可根据路由标记对

  6. ruby - 协议(protocol)族不支持的地址族 - 2

    我尝试执行此页面中显示的ruby示例:http://tomayko.com/writings/unicorn-is-unix但我得到的只是echo.rb:9:in`bind':Addressfamilynotsupportedbyprotocolfamily-bind(2)(Errno::EAFNOSUPPORT)fromecho.rb:9:in`'有什么想法吗? 最佳答案 我遇到了同样的问题。只需将localhost更改为0.0.0.0:address=Socket.pack_sockaddr_in(4242,'0.0.0.0')

  7. ruby-on-rails - 在 Github 上 fork Ruby/Rails gem 的正确协议(protocol)/礼仪是什么,可以作为持续的并行 fork 进行维护? - 2

    最近我使用了一个由单个开发人员创建的不错的gem,它托管在Github上。在我的工作中,我不得不对它进行一些实质性的修改,添加一些改进。有些是特定于项目的,有些是特定于gem的,还有一些是独立的改进。对于特定于gem的改进(例如,错误修复),我fork了存储库,应用了修复,并提出了拉取请求。然后,然而,我注意到独立的改进有点属于原始gem的并行、持续的分支类别。更清楚地说,你以前见过它;我重写了原始gem的View以使用TwitterBootstrap框架。因此,我也将它推送到了Github,但是,当然,我没有提出拉取请求——相反,我更新了README以解释不同之处,并感谢gem的原作

  8. STM32F103C8T6—库函数应用I2C/SPI驱动OLED显示中文、字符串 - 2

    文章目录1.I2C与SPI通信协议对比2.四脚OLED与六脚OLED3.I2C驱动OLED显示oled.h&oled.c:汉字取模&oledfont.h:main.c显示示例:连线方法:4.SPI驱动OLED显示1.I2C与SPI通信协议对比I2C(Inter-IntegratedCircuit)SPI(SerialPeripheralInterface)传输方式半双工全双工传输速度低速,100Kbps----4Mbps高速,30Mbps以上几线制4线制:VCC,GND,SCL,SDA6/7线制:VCC,GND,SCLK(D0),MOSI(D1/SDA),DC,CS/SS主从模式多主机总线,通

  9. ruby-on-rails - OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=unknown 状态:未知协议(protocol) - 2

    我关注了很多关于这个问题的帖子,但没有一个对我有帮助。我正在尝试使用最简单的irb命令进行连接:require'open-uri'open('https://aristo4stu3.bgu.ac.il')奇怪的是,对于我尝试过的任何其他httpsuri,它都工作正常(即https://google.com)。出于调试目的,我什至尝试使用以下方法禁用SSL验证:OpenSSL::SSL::VERIFY_PEER=OpenSSL::SSL::VERIFY_NONE这似乎也没有帮助。我的设置是(在AWS上):$rvm-vrvm1.21.3(stable)byWayneE.Seguin,Mic

  10. ruby-on-rails - 如何使用rails输出当前协议(protocol)和url? - 2

    我有一个共享对话框。在开发中它看起来像:http://xxxxxx.com/stuff产品上:https://yyyyyyyyyyy.com/stuff输出#Protocol##URL#的最佳Rails方式是什么我可以在哪里设置它们?谢谢 最佳答案 request.protocolrequest.url参见requestobject. 关于ruby-on-rails-如何使用rails输出当前协议(protocol)和url?,我们在StackOverflow上找到一个类似的问题:

随机推荐