1. 项目概述
在汽车电子和工业控制领域,控制器局域网(CAN)总线是连接各个电子控制单元(ECU)的“神经系统”。作为一名长期与嵌入式硬件打交道的工程师,我深知一个稳定、高效的CAN控制器对于整个系统的成败有多关键。它不仅仅是实现CAN协议栈的硬件,更是决定通信实时性、可靠性和系统功耗的核心。德州仪器(TI)的DCAN控制器模块,以其丰富的消息对象、灵活的中断机制和精细的功耗管理,成为了许多高要求项目的首选。然而,官方技术手册虽然详尽,但动辄数百页的篇幅和高度技术化的语言,常常让开发者,尤其是刚入行的朋友,感到无从下手。今天,我就结合自己踩过的坑和积累的经验,把DCAN控制器里最核心、也最容易让人困惑的几块内容——消息传输、中断机制和低功耗模式——掰开揉碎了讲清楚。无论你是正在调试第一个CAN节点的新手,还是想优化现有系统性能的老手,希望这篇深度解析能成为你手边实用的参考。
2. DCAN消息传输机制深度解析
消息传输是CAN控制器的基本功,但DCAN在这基础上做了高度抽象和封装,形成了以“消息对象”为中心的管理模式。理解这套机制,是玩转DCAN的第一步。
2.1 消息对象:DCAN通信的基石
你可以把DCAN内部的Message RAM想象成一个邮局的分拣中心,而每一个“消息对象”就是一个标准化的、带有特定地址标签的邮箱。每个消息对象都独立配置,包含了完整的帧信息:29位或11位的标识符(ID)、数据长度码(DLC)以及最多8个字节的数据载荷。这种设计的好处是,一旦配置完成,CPU就可以从繁琐的位时序处理和报文组装/解析中解放出来,专注于应用层逻辑。
核心配置要点:
- 标识符与掩码:这是实现CAN总线过滤和仲裁的核心。每个消息对象都有自己的标识符和标识符掩码。掩码位为1表示该位需要严格匹配,为0则表示“不关心”。例如,配置ID为0x18FFA001,掩码为0x1FFFFFFF,则只接收完全匹配的帧。若掩码为0x1FFF0000,则只关心高13位(标准帧ID范围),低16位任意,这常用于接收一组具有共同特征的报文。
- 控制字段:这是消息对象的“大脑”,包含几个关键位:
MsgVal:消息对象有效位。必须置1,该消息对象才参与总线通信。TxIE/RxIE:发送/接收中断使能。决定该对象在发送完成或接收新数据时是否触发中断。IntPnd:中断挂起位。当满足中断条件(如发送完成且TxIE=1)时,硬件自动置1,等待CPU处理。NewDat:新数据位。对于接收对象,当成功接收到一帧数据时置1;对于发送对象,当CPU更新了数据字节并请求发送时置1。TxRqst:发送请求位。由CPU置1来请求发送该消息对象的数据。
注意:手册中提到,当使用标识符掩码时,接收到的报文帧中那些被掩码设为“不关心”的仲裁位,在存入消息对象时可能会被改变。这意味着,如果你读取接收对象中的标识符字段,它可能不是总线上原始发送的ID,而是经过掩码过滤后的结果。在设计需要核对原始ID的应用时,这一点需要特别注意。
2.2 两种通信模式:中断与轮询
DCAN提供了两种CPU与控制器交互的模式,适应不同的应用场景和对实时性的要求。
2.2.1 中断模式这是最常用、也是效率最高的方式。通过配置IE0或IE1位使能中断线,并设置各个消息对象的TxIE/RxIE,可以让特定通信事件(如成功发送、成功接收)主动通知CPU。
工作流程:
- 事件发生(如报文接收成功)。
- 对应消息对象的
IntPnd位被硬件置位。 - DCAN的中断寄存器(INT)会更新,其
Int0ID或Int1ID字段指向当前优先级最高的、IntPnd=1的消息对象编号。 - 若中断线已使能(
IE0/IE1=1),则向CPU发出中断请求。 - CPU进入中断服务程序(ISR),读取中断寄存器获得消息对象编号,然后通过接口寄存器(IF1/IF2)访问该对象,读取数据或清除状态。
- 在通过IFx寄存器读取消息时,可以同时设置
ClrIntPnd位,一次性清除该对象的IntPnd。硬件随后会自动更新中断寄存器,指向下一个挂起的中断。
中断优先级:消息对象1的优先级最高,编号最大的对象优先级最低。这个优先级仅用于决定多个中断同时挂起时,中断寄存器先报告哪一个,并不影响总线上的报文仲裁优先级(总线仲裁由CAN ID决定)。
2.2.2 轮询模式在某些对实时性要求不高,或者为了简化中断管理的场景,可以采用轮询。CPU定期主动检查所有消息对象的状态。
如何高效轮询: DCAN提供了几个批量的状态寄存器,极大地简化了轮询操作:
NewDat_X寄存器:每个bit对应一个消息对象的NewDat位。你可以一次性读取这个寄存器,快速知道哪些接收对象有了新数据,或者哪些发送对象的数据已被更新。TxRqst_X寄存器:每个bit对应一个消息对象的TxRqst位。可以用于检查哪些发送请求已被硬件处理完成(发送成功后硬件会清除TxRqst和NewDat)。
轮询优化技巧: 手册里给了一个非常实用的建议:将所有的发送对象配置在编号较小的区域(如1-32),所有的接收对象配置在编号较大的区域(如33-64)。这样,在轮询时,你可以有针对性地读取特定的状态寄存器组,而不是遍历全部,能有效减少CPU开销。
2.3 自动重传与总线关闭恢复
这是CAN总线可靠性的两大保障机制,DCAN都提供了硬件支持。
2.3.1 自动重传这是CAN协议的标准要求。当一帧报文因为仲裁失败或传输过程中出错而发送失败时,控制器会自动重新尝试发送。这个功能默认是开启的(DAR位为0)。它的存在保证了报文最终总能发送出去(除非总线持续故障)。
何时需要关闭自动重传?在某些严格的实时或诊断场景下,你可能需要知道每一次发送尝试的确切结果。这时,可以通过设置控制寄存器中的DAR位为1来禁用自动重传。禁用后,每次发送请求只会尝试一次。如果失败,会通过错误状态(LEC)和中断(如果使能)通知CPU,由应用层软件决定下一步动作(例如,记录错误、尝试发送另一条报文等)。
2.3.2 总线关闭与恢复这是CAN节点的“终极保护机制”。当节点由于自身硬件故障或受到持续严重的总线干扰,导致发送错误计数器(TEC)超过255时,节点会进入“Bus-Off”状态。此时,控制器会自动与总线电气隔离,停止一切发送和接收活动,防止故障节点“拖垮”整个网络。
恢复流程:
- 进入Bus-Off后,DCAN会自动将
Init位置1。 - 手动恢复:CPU在检测到Bus-Off后(通过状态中断或轮询
BOff位),需要先清除Init位,启动恢复序列。 - 自动恢复(Auto-Bus-On):这是一个非常实用的功能。通过设置
ABO位为1,DCAN可以在进入Bus-Off后,自动启动恢复序列,无需CPU干预。你还可以通过Auto-Bus-On Time Register设置一个延迟时间,让节点“冷静”一会儿再尝试重返总线。 - 无论手动还是自动,恢复序列的本质是:节点等待监测到总线上的129个连续的“总线空闲”状态(即129 * 11个连续的隐性位)。这相当于给节点一个足够长的观察期,确认总线已经恢复正常。
- 恢复成功后,发送和接收错误计数器都会被清零,节点重新变为“错误主动”状态。
实操心得:在汽车电子中,对于非关键节点(如车身控制模块),开启
ABO功能可以增加系统的自愈能力。但对于动力总成等安全关键节点,通常采用手动恢复,以便上层软件能更精确地记录故障、执行安全策略或通知驾驶员。
3. DCAN中断系统全解与配置实战
中断是协调CPU与DCAN高效工作的关键。DCAN的中断系统设计得相当模块化,理解其拓扑结构是正确配置和调试中断的前提。
3.1 中断源与拓扑结构
DCAN的中断源分为三大类,它们通过两条独立的中断线(DCAN0INT和DCAN1INT)上报给CPU。
3.1.1 消息对象中断这是最灵活的一类中断,由各个消息对象的事件触发(发送完成、接收成功)。每个消息对象都可以通过IntPndMux寄存器,独立配置其IntPnd信号是路由到DCAN0INT还是DCAN1INT。这允许你将不同优先级或不同类型的通信报文分配到不同的中断线上,方便在软件中区分处理。
3.1.2 状态变更中断这类中断由Error and Status Register (ES)中的WakeUpPnd(唤醒挂起)、RxOk(成功接收一帧)、TxOk(成功发送一帧)和LEC(最近错误代码)位的变化触发。它们只能路由到DCAN0INT线。SIE位控制整个状态中断组的使能。
一个重要的细节:手册指出,当SIE=1时,每成功传输或接收一个CAN帧,都会产生一次状态中断,无论是否有总线错误。这意味着如果你使能了SIE,中断频率会非常高,必须确保你的ISR足够高效。通常,在只需要错误和唤醒通知,而不需要每帧确认的场景下,会关闭SIE。
3.1.3 错误中断这类中断由ES寄存器中的PER(奇偶校验/ECC错误)、BOff(总线关闭)和EWarn(错误警告)事件触发。它们同样只能路由到DCAN0INT线,由EIE位控制使能。
中断优先级:在DCAN0INT这条线上,错误和状态中断的优先级高于所有消息对象中断。当中断寄存器(INT)的Int0ID字段值为0x8000时,就表示当前是错误或状态中断在触发。CPU需要去读取ES寄存器来区分具体是哪个事件。
3.2 中断服务程序(ISR)编写指南
一个健壮、高效的DCAN中断处理程序,通常遵循以下流程:
- 判断中断线:首先确定是
DCAN0INT还是DCAN1INT触发的中断。 - 读取中断标识符:读取对应中断线的
INT寄存器,获取Int0ID或Int1ID字段的值。 - 分支处理:
- 如果值为
0x8000:进入错误/状态中断处理分支。- 读取
ES寄存器,检查PER、BOff、EWarn、WakeUpPnd、LEC等位。 - 根据错误类型执行相应操作(如记录日志、复位错误计数器、进入安全模式等)。
- 注意:读取
ES寄存器这个动作本身,就会清除WakeUpPnd、RxOk、TxOk和LEC位。
- 读取
- 如果值在1到最大消息对象编号之间:进入消息对象中断处理分支。
- 该值就是触发中断的消息对象编号。
- 使用
IF1或IF2命令寄存器,通过设置Message Number和ClrIntPnd位,来读取或写入该消息对象的数据,并同时清除其IntPnd位。 - 处理数据(如解包、放入应用队列)。
- 如果值为
- 中断返回:处理完成后,中断寄存器会自动更新或清零,中断线随之失效。
关键技巧:使用IFx命令寄存器IF1和IF2是CPU访问Message RAM的“通道”。在ISR中,通过它们访问消息对象是最高效的方式。一个典型的读取接收数据的操作是:
- 将消息对象编号写入
IFxCMD的Message Number字段。 - 设置
ClrIntPnd位为1(这样在读取的同时就清除了中断挂起位)。 - 设置
Access Direction为读。 - 然后从
IFxDATA等寄存器中读取数据和控制信息。
这种方式保证了操作的原子性和数据一致性,避免了直接访问RAM可能带来的并发问题。
4. 低功耗模式详解与实战配置
在电池供电或需要长时间待机的物联网设备中,功耗是核心指标。DCAN提供了全局和本地两套低功耗机制,给了开发者很大的灵活性。
4.1 全局低功耗模式
全局低功耗模式由系统级的外设中央资源(PCR)模块统一控制。当系统决定进入深度睡眠时,PCR模块会向DCAN等外设发出下电请求。
进入流程:
- 系统通过设置PCR模块中对应的
PSPWRDWNSETx位,请求DCAN进入全局下电模式。 - DCAN收到请求后,会完成所有已挂起的发送请求。
- 然后等待,直到检测到总线进入空闲状态(连续11个隐性位)。
- 最后,DCAN自动将自身的
Init位置1,并进入低功耗状态。此时,模块的大部分电路时钟可能被关闭。
唤醒流程:
- 在全局下电模式下,DCAN的总线活动检测电路(如果使能)仍在工作。
- 当总线上出现一个显性位(即任何节点开始发送)时,DCAN会设置
WakeUpPnd位。 - 如果状态中断
SIE已使能,此时会产生一个中断。 - 在这个中断的服务程序中,应用程序需要做两件事:
- 清除PCR模块中的对应
PSPWRDWNCLRx位,通知系统唤醒DCAN模块。 - 清除DCAN控制寄存器中的
Init位。
- 清除PCR模块中的对应
- DCAN在
Init位清除后,会等待11个连续的隐性位(总线空闲),然后恢复正常工作。
重要警告:手册明确指出,在唤醒过程中,触发唤醒的那第一帧CAN报文是无法被接收的。这意味着如果你用一帧特定的“唤醒报文”来唤醒网络,这帧报文本身会丢失。设计网络唤醒协议时,必须考虑这一点,通常唤醒后的第一帧应是冗余的或非关键的命令帧。
4.2 本地低功耗模式
本地低功耗模式完全由DCAN自身的寄存器控制,独立于系统的其他部分。这允许你在系统其他模块正常工作时,单独让DCAN进入睡眠。
进入流程:
- 应用程序设置控制寄存器中的
PDR位为1,请求进入本地低功耗模式。 - 与全局模式类似,DCAN完成所有发送请求并等待总线空闲。
- 随后,DCAN自动将
Init位置1,并设置状态寄存器中的PDA位,表明已进入本地低功耗模式。此时,DCAN的内部时钟被关闭。
唤醒方式有两种:
- 手动唤醒:应用程序清除
PDR位,然后清除Init位。 - 自动唤醒(通过总线活动):
- 在进入低功耗前,先设置
WUBA位为1,使能总线活动唤醒功能。 - 当总线出现显性位时,DCAN硬件自动执行唤醒序列:清除
PDA和PDR位,设置WakeUpPnd位(可能触发中断),最后清除Init位。 - 同样,它会等待11个连续隐性位后恢复活跃。
- 在进入低功耗前,先设置
模式选择与注意事项:
Init位的危险操作:手册特别警告,在本地低功耗模式下(PDA=1),应用程序绝不能单独去清除Init位而保持PDR=1。如果这样做,那些配置为发送模式的消息对象可能会被意外发送出去,造成总线干扰。- 模式对比:全局模式受系统统一调度,适合整个系统深度睡眠的场景。本地模式更灵活,适合DCAN间歇性工作、需要快速响应总线活动的场景。例如,一个车载传感器节点,大部分时间休眠,但需要随时监听总线上是否有特定的诊断命令帧。
5. 测试模式与诊断功能
DCAN内置了多种测试模式,这对于产品开发、生产测试和现场诊断至关重要。
5.1 静默模式
通过设置测试寄存器的Silent位进入。在此模式下,DCAN的TX引脚被置于高阻态(隐性),它只接收数据,而不会向总线发送任何显性位(包括ACK位、错误帧等)。这相当于一个“总线监听器”。
应用场景:
- 网络监听与分析:在不影响原有网络的前提下,接入一个节点来监听所有总线流量,用于协议分析或故障诊断。
- 节点自检:可以验证节点的接收通路和滤波逻辑是否正常,而不用担心它干扰总线。
5.2 环回模式
通过设置LBack位进入。在此模式下,TX引脚输出正常,但RX引脚被断开,内部将TX信号反馈给RX输入。自己发送的报文会被自己接收。
应用场景:
- 硬件自测试:在不连接外部CAN总线的情况下,测试DCAN控制器内核、TX驱动引脚以及软件栈的完整性。可以自发自收,验证数据是否正确。
- 软件调试:在硬件开发初期,即使没有其他节点或总线,也可以进行通信逻辑的调试。
5.3 外部环回模式
通过设置ExL位进入。它是环回模式的扩展,将TX引脚外部短路到RX引脚(通常需要通过跳线或PCB设计实现)。此模式包含了TX引脚驱动器和外部线路的测试。
应用场景:
- PCB与接口测试:在生产测试中,用于验证从DCAN芯片引脚到CAN收发器之间的物理线路是否连接正确。
5.4 软件控制TX引脚
测试寄存器的Tx[1:0]位可以强制控制CAN_TX引脚输出恒定显性、恒定隐性或输出内部采样点信号。结合读取CAN_RX引脚的状态,可以用于:
- 物理层故障排查:例如,强制输出显性,然后读取RX,可以判断总线是否对地短路;强制输出隐性,可以判断总线是否对电源短路或开路。
- 位定时测量:输出采样点信号,可以用示波器观察,辅助调试比特率配置。
警告:这些软件控制功能会干扰正常的CAN协议通信。因此,只有在测试模式下(
Test位=1),且不进行任何报文传输时,才可以使用这些功能。在正常通信前,务必将其恢复为默认功能。
6. 关键寄存器精讲与配置示例
DCAN的寄存器数量众多,但核心配置围绕几个关键寄存器展开。理解它们每一位的含义,是进行底层驱动开发的基础。
6.1 控制寄存器(CTL)核心位域详解
CTL寄存器是DCAN的总开关,许多高级功能都由此开启或关闭。
Init(位0):初始化位。写1使DCAN进入配置模式,此时才能修改BTR等配置寄存器;写0进入正常工作模式。在Bus-Off恢复序列中,此位会被硬件自动置1。IE0,IE1(位1, 17):中断线使能。分别控制DCAN0INT和DCAN1INT中断线是否向CPU发出请求。SIE,EIE(位2, 3):状态中断使能和错误中断使能。DAR(位5):禁用自动重传。如前所述,用于特殊诊断或实时性要求极高的场景。CCE(位6):配置变更使能。只有在Init=1且CCE=1时,才能修改比特定时寄存器(BTR)等配置寄存器。Test(位7):测试模式使能。进入静默、环回等测试模式的前提。ABO(位9):自动总线开启。使能Bus-Off后的自动恢复功能。PDR(位24):本地低功耗模式请求。WUBA(位25):总线活动唤醒使能(用于本地低功耗模式)。
6.2 错误与状态寄存器(ES)与错误处理
ES寄存器是诊断CAN通信健康状况的“仪表盘”。
LEC(位[4:2]):最近错误代码。指示最后一次在总线上检测到的错误类型(位错误、填充错误、CRC错误等)。每次成功收发一帧后,该字段会被清零。TxOk,RxOk(位5, 6):成功发送/接收。每成功完成一次操作,对应位会置1。读取ES寄存器会清零这些位。如果使能了SIE,每次置位都会产生中断。EWarn(位7):错误警告。当发送或接收错误计数器任一者超过96时置1,表明错误频率较高。BOff(位8):总线关闭。当发送错误计数器超过255时置1,节点已与总线隔离。PER(位9):奇偶校验/ECC错误。在使能了SECDED功能时,指示Message RAM发生了单比特或双比特错误。
错误处理策略:一个健壮的驱动应该在主循环或低优先级任务中定期轮询LEC,或在EIE使能时在中断中处理EWarn和BOff。对于BOff,除了恢复总线,还应记录到非易失存储器中,供后期诊断分析。
6.3 比特定时寄存器(BTR)配置计算
BTR寄存器的配置决定了CAN通信的比特率,是通信稳定的基石。配置不当会导致同步失败、频繁错误甚至无法通信。其计算基于公式:
比特率 = VPCLK / (BRP * (TSEG1 + TSEG2 + 1))
其中:
VPCLK:供给DCAN模块的外设时钟频率。BRP:波特率预分频器(BTR寄存器中的BRP字段加1)。TSEG1:时间段1(包含传播时间段和相位缓冲段1),等于TSEG1字段值加1。TSEG2:相位缓冲段2,等于TSEG2字段值加1。- 采样点:通常位于
(TSEG1 + 1) / (TSEG1 + TSEG2 + 1)的位置,推荐在75%-90%之间。
配置示例: 假设VPCLK = 80 MHz,目标比特率= 500 kbps,目标采样点= 87.5%。
- 选择
BRP,使得时间份额tq = (BRP+1)/VPCLK在一个合理范围(如tq = 100 ns=>BRP = 7)。 - 计算一个位时间总的时间份额数:
总tq数 = VPCLK / (比特率 * (BRP+1)) = 80M / (500k * 8) = 20。 - 分配
TSEG1和TSEG2。根据采样点公式:(TSEG1+1) / 20 = 0.875=>TSEG1 = 16.5,取整为16(实际值填15)。则TSEG2 = 总tq数 - TSEG1 - 1 = 20 - 16 -1 = 3(实际值填2)。 - 最终配置:
BRP=7,TSEG1=15,TSEG2=2,SJW(同步跳转宽度)通常设为TSEG2或更小值,例如2。
避坑指南:不同厂商的CAN控制器对
TSEG1和TSEG2的定义范围可能不同。务必查阅具体芯片的数据手册。配置后,务必在总线上用示波器或CAN分析仪实测比特率和采样点,确保与网络中其他节点匹配。微小的偏差在长距离或高速通信中可能导致间歇性错误。
7. 常见问题排查与调试技巧
在实际开发中,DCAN模块的问题主要集中在“不通”和“不稳”两个方面。下面是我总结的一些排查思路和工具技巧。
7.1 典型问题速查表
| 现象 | 可能原因 | 排查步骤 |
|---|---|---|
| 完全无法通信 | 1. 硬件连接问题(终端电阻、线序) 2. 比特率配置错误 3. DCAN未正确初始化( Init位未清零)4. 收发器供电或使能问题 | 1. 测量CANH/CANL差分电压,静态时应约2.5V。 2. 用示波器测量波形,核对比特率。 3. 检查 CTL寄存器,确认Init=0,CCE=0。4. 检查收发器VCC和STBY引脚。 |
| 能发不能收,或反之 | 1. 消息对象配置错误(标识符、掩码) 2. 消息对象 MsgVal位未使能3. 接收对象 RxIE/NewDat未处理4. 发送对象 TxRqst未置位 | 1. 使用CAN分析仪对比发送和期望接收的ID。 2. 读取 MSGVAL_X寄存器确认对象有效。3. 检查中断或轮询逻辑,确认 NewDat位被及时读取并清除。4. 确认发送请求位 TxRqst已置1,并检查TxOk状态。 |
| 通信间歇性错误,频繁进入Bus-Off | 1. 网络阻抗不匹配,反射严重 2. 比特率或采样点不匹配 3. 电磁干扰(EMI) 4. 节点供电不稳 | 1. 检查总线两端是否都有120Ω终端电阻。 2. 精确测量并校准所有节点的比特率和采样点。 3. 检查布线,远离干扰源,使用双绞线。 4. 监测节点电源纹波。 |
| 低功耗模式无法唤醒 | 1.WUBA位未使能(本地模式)2. 总线活动检测电路未工作 3. 唤醒中断未正确配置或处理 4. Init位在唤醒后未及时清除 | 1. 确认进入低功耗前WUBA=1。2. 确认CAN收发器在低功耗模式下仍能检测总线。 3. 确认 SIE和IE0已使能,且ISR能正确清除WakeUpPnd和Init。4. 在唤醒ISR中,严格按顺序操作:清 PDR/PCR位,再清Init位。 |
| 中断不触发 | 1. 中断线未使能(IE0/IE1)2. 中断源未使能( TxIE/RxIE,SIE,EIE)3. 中断服务程序未清除中断源( IntPnd)4. CPU全局中断未开启或向量表配置错误 | 1. 检查CTL寄存器中断使能位。2. 检查具体消息对象或状态/错误中断使能。 3. 确认在ISR中通过 IFxCMD正确清除了IntPnd。4. 检查MCU层面的NVIC配置和中断向量函数链接。 |
7.2 调试工具与技巧
- 示波器是首选:一个带解码功能的数字示波器,能直观看到CAN波形、比特率、采样点位置、ACK槽是否被显性拉低,是定位物理层和时序问题的利器。
- 专业CAN分析仪:如Vector CANalyzer/CANoe、PCAN-USB等。它们不仅能捕获所有报文,还能进行压力测试、统计错误帧、模拟节点,是协议层调试的终极工具。
- 软件日志:在驱动层增加详细的日志功能,记录所有发送请求、接收数据、错误代码(
LEC)和状态变化(BOff,EWarn)。这些日志在分析间歇性故障时至关重要。 - 利用测试模式:
- 在硬件设计验证阶段,使用环回模式验证驱动和基本收发功能。
- 在怀疑节点干扰总线时,使用静默模式接入网络,看总线是否恢复正常,从而隔离问题节点。
- 使用软件控制TX引脚功能,结合万用表或示波器,快速诊断物理层短路、开路故障。
- 循序渐进初始化:编写初始化函数时,遵循严格的步骤:先进入初始化模式(
Init=1, CCE=1),配置比特率(BTR),配置所有消息对象,最后退出初始化模式(Init=0)。每步之后都读取寄存器确认配置生效。