德州仪器McBSP串行端口发送器配置详解:从时钟帧同步到寄存器编程实战
发布时间:2026/7/22 10:02:37
分类:文化教育
浏览:1234

1. 项目概述在嵌入式开发尤其是涉及音频处理、工业通信或数字信号处理的场景里串行通信接口是连接芯片与外部世界的“咽喉要道”。它不像并行总线那样需要一堆线而是通过一根或几根数据线配合时钟和同步信号把数据一位一位地、有序地送出去或收进来。听起来简单但要让数据“听话”在正确的时间出现在正确的位置背后的时序配置就是关键。这就像指挥一个交响乐团时钟是节拍器帧同步是指挥棒起落的信号而寄存器编程就是乐谱上每一个音符的时值和强弱标记。今天要拆解的是德州仪器TIDSP和部分微控制器中常见的**多通道缓冲串行端口McBSP**的发送器配置。很多新手甚至一些有经验的工程师面对手册里几十个寄存器位域时都会感到头疼CLKGDV、FSXM、XDATDLY……这些缩写到底在控制什么怎么组合才能让我的音频数据流稳定输出或者让传感器读数准确上传这篇文章我就结合自己这些年调试McBSP的经验把发送器配置这块“硬骨头”嚼碎了讲给你听。我会从最根本的时钟和帧同步原理讲起然后带你一步步“填写”那些关键的寄存器最后分享几个我踩过坑才总结出来的实战技巧。无论你是正在评估通信方案还是已经卡在某个配置问题上希望这篇近万字的详解能成为你手边可靠的参考。2. McBSP发送器配置的核心逻辑与设计思路在动手写代码之前我们必须先理解McBSP发送器工作的“剧本”。它的核心任务就三件事何时发送时钟、从哪里开始发送帧同步、以及发送什么数据。配置的所有寄存器都是围绕这三件事展开的。2.1 时钟系统一切节奏的源头时钟是串行通信的“心跳”。McBSP的时钟可以来自外部引脚也可以由内部的**采样率发生器Sample Rate Generator, SRG**产生。对于发送器Transmitter而言我们主要关心CLKX这个时钟信号。时钟来源的选择CLKXM位这是第一个关键决策。CLKXM位在PCR_REG[9]。当CLKXM 0时时钟来自外部McBSP.CLKX引脚是输入引脚你需要从外部DAC、编解码器或其他主设备引入一个时钟。当CLKXM 1时时钟由内部的SRG产生McBSP.CLKX引脚变为输出引脚此时McBSP可以作为主设备为其他从设备提供时钟。在音频应用中如果McBSP连接的是一个需要主时钟的音频编解码器通常会将McBSP配置为主模式CLKXM1。采样率发生器SRG的妙用SRG是一个灵活的时钟分频器。它以一个输入时钟可以是内部CPU时钟McBSP_FCLK也可以是外部CLKS、CLKX或CLKR引脚为基础通过分频产生最终的数据位时钟CLKG。CLKG的频率由CLKGDV在SRGR1_REG[7:0]决定公式是Fclkg Finput / (CLKGDV 1)。例如输入时钟是12.288 MHz你需要一个2.048 MHz的位时钟对应48kHz采样率、32位字长的I2S格式那么CLKGDV应该设置为(12.288 / 2.048) - 1 5。SRG产生的CLKG时钟占空比是固定的50%非常稳定。时钟极性CLKXP位数据在哪个时钟沿被锁存或输出由极性控制。CLKXP位在PCR_REG[1]。这里有个非常重要的概念McBSP内部逻辑总是使用上升沿来输出数据。CLKXP位控制的是外部引脚看到的波形。当CLKXP0时引脚上的时钟上升沿对应内部时钟的上升沿数据在上升沿变化。当CLKXP1时引脚上的时钟信号会被反相即你看到的下落沿其实是内部时钟的上升沿在驱动数据变化。这一点在与不同极性要求的设备对接时至关重要配错了会导致数据采样错位。2.2 帧同步数据包的起跑线如果说时钟决定了每个“步点”比特的节奏那么帧同步Frame Sync就标志着一“圈”一帧数据的开始。它告诉接收方“注意新的一个数据包要来了”帧同步来源FSXM和FSGM位FSXM位PCR_REG[11]和FSGM位SRGR2_REG[12]共同决定了帧同步信号FSX的来源。外部帧同步FSXM0FSX引脚作为输入由外部设备提供同步脉冲。这在McBSP作为从设备时很常见。内部帧同步FSXM1, FSGM1帧同步由SRG产生的FSG信号直接提供。这是主模式的典型配置McBSP自己产生周期性的帧同步。门控内部帧同步FSXM1, FSGM0帧同步也由SRG产生但只有当发送缓冲区XBUFF非空时才会输出。这可以用于节省功耗或特殊流控但日常应用较少。帧同步的周期与宽度当使用内部帧同步时你需要定义这个脉冲的“形状”。FPERSRGR2_REG[11:0]定义了帧周期即两个帧同步脉冲起始点之间的CLKG周期数范围为1到4096。FWIDSRGR1_REG[15:8]定义了脉冲宽度即帧同步信号保持有效的CLKG周期数范围为1到256。通常FWID设置为1即一个比特时钟周期的脉冲就足够了。帧周期的计算决定了你的“数据包”有多长。例如在I2S格式中一帧包含左右两个声道的数据每个声道32位那么一帧就是64个比特时钟。此时FPER应设置为63因为公式是FPER 1。帧同步极性FSXP位和时钟极性类似FSXP位PCR_REG[3]决定了帧同步脉冲的有效电平是高还是低。同样内部逻辑始终使用高电平有效。FSXP0表示引脚上高电平有效FSXP1则表示引脚上的信号被反相低电平有效。必须确保发送方和接收方的帧同步极性设置一致否则接收方可能永远检测不到帧的开始。2.3 数据格式与延迟精细调整数据位置时钟和帧同步搭好了舞台数据演员该如何登场这里涉及到数据帧的结构和精确的登场时机。单相与双相帧XPHASE位XPHASE位XCR2_REG[15]决定了一帧数据是简单的单一段落还是由两个不同段落组成。绝大多数标准协议如I2S, PCM都使用单相帧XPHASE0即一帧内所有字都具有相同的格式。双相帧XPHASE1则允许一帧内包含两种不同长度和参数的数据段适用于一些非标准的、复杂的多路复用协议。字长XWDLEN与帧长XFRLEN这是定义数据包大小的核心。字长XWDLEN1XCR1_REG[7:5]定义单相或双相第一相中每个串行字的位数可选8、12、16、20、24、32位等。XWDLEN2XCR2_REG[7:5]定义双相第二相的字长。帧长XFRLEN1XCR1_REG[14:8]定义单相或双相第一相中一相包含多少个串行字。它是一个7位字段所以每相最多128个字。需要填入的值是“字数减1”。例如一相包含16个字则设置XFRLEN1 15。对于单相帧总帧长就是XFRLEN1 1个字。对于双相帧总帧长固定为2个字每相各一个XFRLEN1和XFRLEN2必须都设置为0。数据延迟XDATDLY这是最容易出错也最关键的参数之一。XDATDLYXCR2_REG[1:0]定义了在检测到帧同步有效后延迟多少个比特时钟才开始发送第一个数据位。可选0、1、2个比特延迟。XDATDLY11位延迟这是最常用、最安全的设置。帧同步脉冲有效后等待一个比特时钟在下一个时钟沿开始输出数据。这为接收端提供了稳定的建立时间。XDATDLY00位延迟数据在帧同步有效的一个时钟沿就必须开始输出。这对时序要求极其苛刻通常需要发送端提前准备好数据容易出错仅在特定协议下使用。XDATDLY22位延迟延迟两个比特时钟。有时用于跳过某些协议中紧跟在帧同步后的一个“帧头”或“起始位”。实操心得在调试任何新的串行接口时如果发现数据整体错位了一位或两位第一个要检查的就是XDATDLY的设置。我遇到过不止一次因为参考了不完整的代码片段而将XDATDLY设为0导致数据始终对不上浪费了大半天时间。无脑设为1在绝大多数情况下都是正确的起点。3. 寄存器编程实战从复位到发送的完整流程理解了原理我们来看如何用代码实现。配置McBSP发送器有一个严格的“三部曲”复位 - 配置 - 使能。这个顺序不能乱否则可能导致配置无法生效或接口行为异常。3.1 第一步将发送器置于复位状态在修改任何配置寄存器之前必须确保发送器以及整个串行端口如果你也在配置接收器处于复位状态。这是硬件的要求可以防止在配置过程中产生不可控的通信活动。// 假设 McBSP 的基地址为 0x48000000相关寄存器偏移量参考手册 volatile uint32_t *spcr2 (volatile uint32_t *)(0x48000000 0x110); // SPCR2_REG // 1. 全局复位如果整个串口都需要重置 // *spcr2 ~(1 0); // 清零 XRST 位发送器复位 // 同时也需要复位接收器(SPCR1_REG[0])和采样率发生器(SPCR2_REG[6]) // 更常见的做法是直接操作XRST位仅复位发送器 *spcr2 ~(1 0); // 确保 XRST 0发送器在复位中复位后DX、FSX、CLKX等引脚的行为可能处于高阻或默认状态具体取决于其他相关配置如XIOEN。3.2 第二步按逻辑顺序编程关键寄存器这是最核心的部分。我将按照“全局行为 - 数据行为 - 帧同步 - 时钟”的逻辑分组展示一个典型的I2S主模式发送配置示例。请注意以下代码仅为示意实际地址和位域需根据具体芯片手册调整。a. 全局行为与引脚功能配置首先确定引脚是用于McBSP还是通用GPIO。volatile uint32_t *pcr (volatile uint32_t *)(0x48000000 0x148); // PCR_REG // 禁用数字/模拟回环禁用同步收发模式通常情况 // 配置引脚为McBSP功能而非GPIO // XIOEN 1: 发送器引脚用作McBSP功能 (PCR_REG[13]) // RIOEN 0: 接收器引脚也用作McBSP功能假设也需要接收(PCR_REG[12]) // 这里我们只关注发送假设接收器独立配置或不用 *pcr | (1 13); // 设置 XIOEN 1b. 数据行为配置配置数据帧的格式。以标准的I2S格式为例单相左对齐字长32位帧长2个字-左右声道各一。volatile uint32_t *xcr1 (volatile uint32_t *)(0x48000000 0x124); // XCR1_REG volatile uint32_t *xcr2 (volatile uint32_t *)(0x48000000 0x120); // XCR2_REG // 1. 选择单相帧 (XPHASE 0) *xcr2 ~(1 15); // 清零 XPHASE 位 // 2. 设置发送字长为32位 // XWDLEN1 位域 [7:5] 32位通常对应值 0b111 或 0b110具体查手册。假设 0b111 代表32位。 *xcr1 ~(0x7 5); // 先清零 *xcr1 | (0x7 5); // 再设置为 0b111 // 3. 设置发送帧长度I2S一帧有左右2个声道字所以每相字数为2。 // XFRLEN1 位域 [14:8]需要填入 (字数 - 1)。所以 2-11。 *xcr1 ~(0x7F 8); // 先清零 *xcr1 | (1 8); // 设置 XFRLEN1 1 // 4. 设置数据延迟为1位最常用 // XDATDLY 位域 [1:0] *xcr2 ~(0x3 0); // 先清零 *xcr2 | (1 0); // 设置 XDATDLY 01b (1位延迟) // 5. 可选设置DXENA模式如果多个McBSP的DX引脚并联需要使能以避免冲突 // 通常在点对点连接中不需要保持默认禁用即可。c. 帧同步行为配置配置帧同步信号的来源和参数。// 继续使用 pcr 指针 volatile uint32_t *srgr2 (volatile uint32_t *)(0x48000000 0x128); // SRGR2_REG // 1. 设置帧同步模式内部产生由SRG直接驱动 (FSXM1, FSGM1) *pcr | (1 11); // 设置 FSXM 1 *srgr2 | (1 12); // 设置 FSGM 1 // 2. 设置帧同步极性根据对接设备要求。I2S标准中帧同步WS低电平代表左声道高电平代表右声道。 // 我们需要FSX引脚在左声道期间输出低电平。内部FSG是高有效所以需要反转。 // FSXP 1: 引脚输出信号反相即内部高有效变为引脚低有效。 *pcr | (1 3); // 设置 FSXP 1 // 3. 设置SRG帧同步周期(FPER)和脉冲宽度(FWID) // 对于I2S帧同步信号WS的周期是64个位时钟CLKG脉宽是32个位时钟半周期。 // FPER 周期 - 1 64 - 1 63 // FWID 脉宽 - 1 32 - 1 31 volatile uint32_t *srgr1 (volatile uint32_t *)(0x48000000 0x12C); // SRGR1_REG *srgr1 ~(0xFF 8); // 清零 FWID 位域 [15:8] *srgr1 | (31 8); // 设置 FWID 31 *srgr2 ~(0xFFF 0); // 清零 FPER 位域 [11:0] *srgr2 | (63 0); // 设置 FPER 63d. 时钟行为配置配置时钟的来源、分频和极性。// 1. 设置发送时钟模式内部SRG作为时钟源CLKX引脚输出时钟 (CLKXM1) *pcr | (1 9); // 设置 CLKXM 1 // 2. 设置发送时钟极性I2S标准规定数据在时钟下降沿后变化在上升沿被采样。 // 我们的McBSP内部在上升沿输出数据。因此为了让接收设备在上升沿采样到稳定数据 // 我们需要CLKX引脚输出的时钟其上升沿对应内部时钟的上升沿即数据变化沿 // 而其下降沿则对应内部时钟的下降沿即数据稳定期。这要求引脚时钟与内部时钟反相。 // CLKXP 1: 引脚输出时钟反相。 *pcr | (1 1); // 设置 CLKXP 1 // 3. 设置SRG时钟分频值 (CLKGDV) // 假设输入到SRG的时钟是McBSP_FCLK 12.288 MHz。 // 我们需要产生位时钟 BCLK 2.048 MHz (用于48kHz, 32bit*2ch的I2S)。 // CLKGDV (Finput / Fclkg) - 1 (12.288 / 2.048) - 1 5 *srgr1 ~(0xFF 0); // 清零 CLKGDV 位域 [7:0] *srgr1 | (5 0); // 设置 CLKGDV 5 // 4. 设置SRG时钟同步模式通常使用自由运行模式 (GSYNC0) *srgr2 ~(1 15); // 清零 GSYNC 位 // 5. 设置SRG时钟模式选择输入时钟源。假设我们使用内部CPU时钟源。 // 这由 SCLKME (PCR_REG[7]) 和 CLKSM (SRGR2_REG[13]) 共同决定。 // 查手册可知SCLKME0, CLKSM1 表示选择内部时钟源如McBSP_FCLK。 *pcr ~(1 7); // 设置 SCLKME 0 *srgr2 | (1 13); // 设置 CLKSM 1 // 6. 设置SRG输入时钟极性由于使用内部时钟源CLKSP位无关。保持默认0即可。3.3 第三步使能发送器与采样率发生器所有寄存器配置完毕后最后一步是“释放”复位让发送器和时钟源开始工作。顺序很重要先启动时钟再启动发送器。// 1. 使能采样率发生器 (SRG) volatile uint32_t *spcr2 (volatile uint32_t *)(0x48000000 0x110); *spcr2 | (1 6); // 设置 GRST 1 SRG脱离复位开始运行 // 等待至少2个SRG时钟周期稳定软件延时或检查状态 delay_us(10); // 简单延时具体时间取决于时钟频率 // 2. 使能发送器 *spcr2 | (1 0); // 设置 XRST 1发器脱离复位 // 此时如果FSGM1且帧同步为内部产生FSG信号会立即开始产生。 // 发送器就绪等待数据写入DXR寄存器。至此一个完整的、基于内部SRG时钟和帧同步的I2S主模式发送器就配置完成了。你可以通过向数据发送寄存器DXR_REG写入数据来启动传输。4. 高级话题与疑难杂症排查即使按照上述步骤配置在实际项目中仍可能遇到各种问题。下面分享几个常见的“坑”和排查思路。4.1 时钟与帧同步无输出这是最令人沮丧的问题之一配置了半天用示波器却看不到CLKX和FSX引脚上有任何信号。可能原因与排查步骤引脚复用未正确配置这是最常见的原因。McBSP引脚CLKX, FSX, DX通常与其他功能如GPIO、其他外设复用。在配置McBSP寄存器前必须通过芯片的引脚控制模块PinMux将这些引脚的功能选择设置为“McBSP”。这一步常常在TI的底层库如DSP/BIOS, DriverLib或板级支持包BSP中完成容易被忽略。务必检查芯片的引脚复用配置寄存器。发送器或SRG未使能确认XRST和GRST位是否已设置为1。检查代码中使能顺序是否正确。时钟源错误或未激活检查SCLKME和CLKSM位确保SRG的输入时钟源是存在的且已使能。例如如果选择了CLKX引脚作为外部输入时钟但该引脚没有信号SRG就不会工作。输出被禁用检查XIOEN位是否为1McBSP功能。如果XIOEN0引脚被配置为GPIO即使McBSP内部有信号也不会输出到引脚上。寄存器写入未生效在某些架构中对外设寄存器的写入可能需要特定的访问方式如必须32位写或需要等待同步。确保你的写操作是有效的。可以尝试先读取再回写确认。避坑技巧建立一个简单的“寄存器值打印”调试函数。在配置的每个关键步骤后将相关寄存器PCR, SRGR1, SRGR2, XCR1, XCR2, SPCR2的值通过串口打印出来与你的预期配置进行逐位比对。这能快速定位是哪一步的配置写错了或没生效。4.2 数据错位或乱码有时时钟和帧同步都正常但接收到的数据完全不对或者整体偏移了几位。可能原因与排查步骤数据延迟XDATDLY不匹配这是头号嫌疑犯。用示波器同时测量FSX、CLKX和DX信号。观察第一个数据位是在FSX有效后的第几个CLKX边沿出现的。对照XDATDLY的设置0,1,2进行验证。强烈建议在未知协议下先从XDATDLY1开始尝试。时钟极性CLKXP或帧同步极性FSXP错误这会导致接收方在错误的边沿采样数据或检测帧头。用示波器查看CLKX和FSX的波形确认其有效边沿与接收设备的要求一致。记住McBSP内部总是在CLKX上升沿输出数据CLKXP控制的是引脚上的波形是否反相。字长XWDLEN或帧长XFRLEN错误如果字长设置小于实际数据位数会导致高位被截断如果设置大于实际位数则会在多余的位置上发送未定义数据通常是0或旧数据。同样帧长错误会导致数据包边界混乱。仔细核对协议规定的数据格式。大小端Endianness问题McBSP总是先发送最高有效位MSB First。如果你的数据在内存中是Little-Endian格式而接收设备也期望MSB First那么你需要确保在将数据写入DXR_REG之前已经将字节序调整正确。例如一个16位数据0x1234在内存中小端可能是[0x34, 0x12]但McBSP会先发送最高字节的0x12的最高位。这需要根据系统架构进行处理。4.3 使用DMA传输数据时的注意事项当需要连续传输大量数据如音频流时通常会启用DMA来服务McBSP解放CPU。关键配置点中断与DMA触发源需要正确配置发送中断模式XINTM或直接配置DMA触发源。对于简单的“每准备好一个字就传输”的模式通常使用XRDY发送寄存器就绪作为触发条件。这对应XINTM 00或配置DMA由XEVT发送事件触发。缓冲区管理McBSP的发送缓冲区XBUFF深度因芯片而异。你需要了解是单缓冲、双缓冲还是多缓冲。配置DMA时传输元素大小应与McBSP的字长匹配并且DMA的传输完成中断应能及时填充下一个数据块避免缓冲区下溢Underflow这会导致发送停顿或重复发送旧数据。多通道模式如果使用了McBSP的多通道选择功能通过XMCM,XCERA等寄存器需要确保DMA传输的数据流与激活的发送通道对齐。配置错误会导致数据发送到错误的时隙channel中。4.4 回环测试Loopback的妙用当不确定是发送配置问题还是接收端问题时McBSP的数字回环模式Digital Loopback Mode是一个极其宝贵的调试工具。如何操作将DLB位在XCCR_REG中具体位置查手册设置为1使能数字回环。在此模式下发送器的输出DX, FSX, CLKX会在内部直接连接到接收器的输入DR, FSR, CLKR。配置好发送器后再配置接收器以匹配发送器的参数。向DXR_REG写入数据然后从DRR_REG读取数据。如果读回的数据与写入的一致说明从发送寄存器、经串行化、到接收寄存器的整个McBSP内部数据路径是正常的。这可以帮你排除掉大部分McBSP自身配置和硬件连接的问题将故障范围缩小到外部物理链路或对端设备上。重要提示使用回环模式时必须确保采样率发生器SRG和帧同步发生器已使能GRST1,FRST1因为回环路径需要这些内部时钟和同步信号。同时注意此时外部引脚可能没有输出或输出异常这是正常现象。5. 配置清单与快速参考为了便于查阅和避免遗漏我将关键的配置步骤和寄存器位整理成以下表格。在开始一个新的McBSP项目时可以对照此清单逐一检查。5.1 发送器配置核心寄存器位检查表配置类别寄存器位位置常用值/说明功能简述全局控制XRSTSPCR2_REG[0]0配置时, 1工作时发送器复位/使能XIOENPCR_REG[13]1发送引脚用于McBSP功能DLBXCCR_REG(具体位查手册)0正常, 1回环测试数字回环模式数据格式XPHASEXCR2_REG[15]0单相帧帧相位数XWDLEN1XCR1_REG[7:5]根据协议如0b111(32位)相位1字长XFRLEN1XCR1_REG[14:8]字数-1如12个字相位1帧长字数XDATDLYXCR2_REG[1:0]01b1位延迟数据起始延迟帧同步FSXMPCR_REG[11]1内部或0外部帧同步源选择FSGMSRGR2_REG[12]1SRG直接产生帧同步生成模式FSXPPCR_REG[3]根据协议I2S常为1帧同步引脚极性FPERSRGR2_REG[11:0]周期-1如6364周期帧同步周期FWIDSRGR1_REG[15:8]脉宽-1如3132周期帧同步脉冲宽度时钟CLKXMPCR_REG[9]1内部主或0外部从发送时钟源选择CLKXPPCR_REG[1]根据协议I2S常为1发送时钟引脚极性CLKGDVSRGR1_REG[7:0](输入频率/输出频率)-1SRG时钟分频值GSYNCSRGR2_REG[15]0自由运行SRG时钟同步模式CLKSMSRGR2_REG[13]1选择内部时钟源SRG时钟源选择SCLKMEPCR_REG[7]0与CLKSM配合SRG时钟源选择扩展SRG使能GRSTSPCR2_REG[6]0配置时, 1工作时采样率发生器复位/使能5.2 典型配置流程伪代码void McBSP_Transmitter_Init(void) { // 1. 引脚复用配置 (通过芯片特定的PinMux模块) PINMUX_ConfigMcBSPPins(); // 2. 确保发送器和SRG处于复位状态 SPCR2_REG ~(XRST | GRST); // 清零XRST和GRST // 3. 配置全局行为 PCR_REG | XIOEN; // 引脚功能选择 // 4. 配置数据格式 (以单相32位字长2字帧1位延迟为例) XCR1_REG (XWDLEN_32BIT 5) | (1 8); // 字长32位帧长2字 XCR2_REG (0 15) | (1 0); // 单相帧1位数据延迟 // 5. 配置帧同步 (内部产生I2S格式) PCR_REG | FSXM; // 内部帧同步 SRGR2_REG | FSGM; // SRG产生FS PCR_REG | FSXP; // 帧同步极性反转低有效 SRGR1_REG | (31 8); // FWID 31 (脉宽32) SRGR2_REG | (63 0); // FPER 63 (周期64) // 6. 配置时钟 (内部主时钟分频产生2.048MHz极性反转) PCR_REG | CLKXM; // 内部时钟源CLKX为输出 PCR_REG | CLKXP; // 时钟极性反转 SRGR1_REG | (5 0); // CLKGDV 5 (12.288MHz - 2.048MHz) SRGR2_REG ~GSYNC; // 自由运行模式 SRGR2_REG | CLKSM; // SRG时钟源选择 PCR_REG ~SCLKME; // 配合CLKSM选择内部时钟 // 7. 使能SRG等待稳定 SPCR2_REG | GRST; delay_for_srg_stable(); // 等待几个时钟周期 // 8. 使能发送器 SPCR2_REG | XRST; }调试串行通信三分靠配置七分靠调试。示波器或逻辑分析仪是你的最佳伙伴。一定要同时抓取CLKX、FSX和DX三条信号线对照数据手册的时序图一个边沿一个边沿地分析。从时钟和帧同步是否有输出到第一个数据位出现的位置是否正确再到整个数据帧的波形是否符合预期层层递进问题往往就藏在这些细节里。希望这份详细的梳理能让你下次面对McBSP时少走些弯路多几分从容。