1. 从“定时器”到“移相”:TIM1的计数模式为何是核心
在嵌入式开发,特别是基于STM32这类MCU的项目里,定时器(Timer)是工程师最常打交道的外设之一。它就像系统里的“心跳”和“节拍器”,从简单的延时、PWM波生成,到复杂的电机控制、通信协议同步,都离不开它。而STM32的TIM1和TIM8,作为高级控制定时器,其功能之强大、配置之灵活,常被誉为定时器家族的“瑞士军刀”。最近,关于“tim1和tim8 实现移相”的讨论热度很高,这恰恰触及了高级定时器最核心、也最考验理解深度的功能之一。
要实现移相,或者其他任何基于定时器的复杂波形控制,其底层基石就是计数模式。很多人刚开始接触定时器,可能只关心如何设置预分频器(PSC)和自动重载值(ARR)来得到一个想要的溢出频率,认为计数模式无非就是“向上数”或“向下数”。但当你需要精确控制多个通道的输出时序、生成互补带死区的PWM、或者实现文中提到的移相功能时,才会发现计数模式的选择和配置,直接决定了你能否“指挥”定时器按照你设想的方式工作。它定义了计数器值变化的“轨迹”,而这个轨迹,是所有高级定时器输出比较、输入捕获、刹车等功能的时空坐标系。
所以,今天我们不空谈概念,而是深入TIM1(其原理同样适用于TIM8)的计数模式,把它掰开揉碎,讲清楚每种模式下的计数器行为、对应的寄存器配置、以及最关键的应用场景。理解了这些,你再去看“移相”之类的应用,就会有一种豁然开朗的感觉——原来它只是计数模式、输出比较模式和预装载机制等基础功能组合起来的一场“协同演出”。
2. TIM1计数模式的四种“性格”与核心寄存器解析
TIM1的计数模式主要通过对TIMx_CR1寄存器的CMS[1:0]和DIR位进行配置来实现。我们常说有四种基本模式,但本质上是由计数方向(DIR)和中央对齐模式(CMS)共同决定的。理解它们,就是理解计数器值CNT随时间变化的曲线。
2.1 边缘对齐模式:单向的冲锋
这是最直观、最常用的模式,包含向上计数和向下计数。
向上计数模式(Edge-aligned Upcounting)
- 配置:
DIR=0(向上),CMS=00。 - 行为:计数器从0开始,每个时钟周期加1,一直计数到自动重载寄存器(
ARR)设定的值。在到达ARR的瞬间,会产生一个更新事件(UEV),计数器清零,然后重新开始向上计数。如此周而复始。 - 波形与关键点:如果你查看
CNT的波形,它是一个从0到ARR的锯齿波。更新事件发生在锯齿波的“顶峰”(ARR值处)。PWM输出比较的有效/无效边沿,就是在这个线性增长的CNT与比较寄存器CCRx的值匹配时触发的。 - 典型应用:生成标准的PWM波形。例如,控制LED亮度、驱动舵机。它的时序简单明了,计算占空比非常直观:
占空比 = CCRx / ARR。
向下计数模式(Edge-aligned Downcounting)
- 配置:
DIR=1(向下),CMS=00。 - 行为:计数器从ARR值开始,每个时钟周期减1,一直减到0。在到达0的瞬间,产生更新事件,计数器重新加载ARR值,开始下一轮递减。
- 波形与关键点:
CNT波形是一个从ARR到0的下降锯齿波。更新事件发生在“谷底”(0值处)。 - 典型应用:某些特定的电机控制算法或电源拓扑中,可能需要从高向低计数的时序逻辑。但单独使用向下计数模式的情况相对较少。
注意:在单纯的边缘对齐模式下,
ARR寄存器包含在计数范围内。例如ARR设为999,向上计数时,CNT会遍历0,1,2...999。这意味着一个计数周期是(ARR+1)个时钟 ticks。这一点在计算频率时至关重要:定时器溢出频率 = 定时器时钟频率 / (PSC+1) / (ARR+1)。
2.2 中央对齐模式:对称的舞蹈
中央对齐模式,也叫中心对齐模式或对称PWM模式,是理解移相等功能的关键。它通过对CMS[1:0]位进行设置,有三种子模式,但最常用的是模式1。
中央对齐模式1(Center-aligned Mode 1)
- 配置:
CMS=01或CMS=10或CMS=11。通常使用CMS=10(先向上再向下计数)。 - 行为:这是双向计数。计数器从0开始向上计数到ARR,然后立即调转方向,从ARR开始向下计数回0,完成一个完整周期。更新事件(UEV)在什么时候产生呢?在计数器从向上转为向下(到达ARR时)和从向下转为向上(到达0时)都会产生。但根据
TIMx_CR1中的URS位设置,你可以选择只在计数器溢出(0或ARR)时产生更新事件以同步DAC等外设。 - 波形与关键点:
CNT的波形是一个三角波。这是与边缘对齐模式最根本的图形化区别。PWM的比较匹配事件会发生两次:一次在向上计数过程中(CNT等于CCRx),另一次在向下计数过程中(CNT再次等于CCRx)。这直接影响了PWM输出的对称性。 - 核心优势:
- 对称PWM:生成的PWM波形关于中心对称,能显著降低电机驱动中的谐波分量,减少噪音和损耗,是电机FOC控制的标配。
- 为移相奠定基础:移相的本质是控制多个通道的PWM输出在时间轴上的相对位置。在三角波计数轨迹下,通过设置不同的
CCRx值,可以非常精确地控制输出边沿在三角波的“上升沿”和“下降沿”上的位置,从而实现通道间的相位差。这是边缘对齐的锯齿波难以优雅实现的。
模式0、1、2的细微差别:CMS=01和CMS=10分别代表“只在下溢时产生中断”和“只在上溢时产生中断”,而CMS=11代表在上溢和下溢时都产生中断。但在计数行为上,它们都是先上后下的三角波。这个中断配置的差异,在需要非常精确的中断响应时序时需要考虑。
2.3 关键寄存器:不只是CR1
理解计数模式,不能只看CR1。有几个寄存器与之深度耦合:
TIMx_ARR(自动重载寄存器):计数器的上限。在中央对齐模式下,它是三角波的“峰顶”。强烈建议使用预装载功能(ARPE=1),这样你修改ARR时,新值会在下一个更新事件后才生效,防止在计数中途修改导致不可预测的波形断裂。TIMx_CCMRx(捕获/比较模式寄存器):这里配置通道的输出比较模式。例如,你需要设置为PWM模式1或PWM模式2。这两个模式决定了当CNT < CCRx时输出有效电平还是无效电平,并且在中央对齐模式下,它们的行为会自动适配,以确保在三角波的两个斜坡上都能正确比较,生成连续的PWM。TIMx_CCRx(捕获/比较寄存器):这就是你控制脉宽(占空比)和相位的关键。在中央对齐模式下,修改CCRx的值,会同时移动PWM脉冲两个边沿的位置(相对于三角波中心对称移动),从而改变占空比。而要实现移相,就是让不同通道的CCRx值具有一个固定的差值。TIMx_EGR(事件生成寄存器):手动产生一个更新事件(UG位)。在初始化定时器或需要强制同步所有影子寄存器(ARR, CCRx等)时非常有用。
3. 中央对齐模式下的PWM生成与移相原理拆解
现在,我们进入最精彩的部分:如何利用中央对齐模式实现PWM,并在此基础上理解移相。
3.1 PWM生成:三角波上的“切割”
假设我们配置TIM1为中央对齐模式1(CMS=10),ARR=1000,CCR1=300。
- 计数轨迹:CNT从0 -> 1000(上升沿),然后从1000 -> 0(下降沿)。
- 输出比较(以PWM模式1为例):
- 在上升沿:当 CNT < CCR1 (300) 时,通道输出有效电平(例如高电平);当 CNT >= CCR1 时,输出无效电平(低电平)。
- 在下降沿:当 CNT > CCR1 (300) 时,输出无效电平;当 CNT <= CCR1 时,输出有效电平。
- 结果:你会得到一个以三角波中心对称的PWM波。有效电平(高电平)出现在每个周期开始和结束的一小段,以及中间CNT值小于300的区间。实际上,在中央对齐模式下,占空比的计算公式为:
占空比 = (2 * CCRx) / (ARR + 1)?不,这个简化公式容易误导。更准确的理解是,有效电平的时间宽度对应于CNT值小于CCRx的区间。由于是三角波,这个区间在时间轴上是两段。但整体效果是一个脉宽被“中心化”的PWM。
3.2 移相实现:错开“切割”的位置
移相,就是让两个或多个PWM通道的波形在时间上有一个偏移,而不是同时开始。 在中央对齐模式下,这变得异常简单。核心思想就是为每个通道设置不同的CCRx值。
场景:TIM1_CH1 和 TIM1_CH2 输出一对具有90度相位差(即1/4周期)的PWM。
- 基础配置:TIM1工作在中央对齐模式,ARR=1000(一个完整三角波周期对应2001个计数点?这里需要澄清:一个完整的中央对齐周期,CNT从0到ARR再到0,经历的计数点总数是
2 * ARR个tick。因为0->ARR是ARR个步长,ARR->0也是ARR个步长。但通常我们以三角波的周期为准,频率计算为Fpwm = Fck_psc / ( (ARR+1) * 2 )?这里有个常见的混淆点。实际上,在中央对齐模式下,定时器溢出频率(即三角波频率)是Fck_psc / (ARR+1)。因为CNT从0到ARR(或反之)算作一次计数操作。ARR=1000时,CNT从0数到1000需要1001个时钟(0,1,...,1000),然后从1000数到0也需要1000个时钟(1000,999,...,1),总共2001个时钟?不,更标准的理解是:在中央对齐模式,PWM频率 = 定时器时钟频率 / ( (ARR+1) * 2 )。这是最常用的公式。ARR=1000,则PWM周期对应2002个定时器时钟周期?我们以数据手册为准:通常,PWM频率 = Fck / (PSC+1) / (ARR+1)。这个公式在中央对齐和边缘对齐模式下都适用吗?需要验证。经验上,为了在中央对齐模式下得到目标频率Fpwm,通常设置ARR = (Fck_psc / Fpwm) - 1。这个ARR值在中央对齐模式下,CNT会从0计数到ARR,再计数回0,完成一个完整的PWM周期。所以,一个PWM周期包含的定时器时钟数是2 * (ARR+1)?还是(ARR+1)?实测和标准库代码显示,应该使用ARR = (Fck_psc / Fpwm) - 1。例如,72MHz时钟,欲得36KHz PWM,Fck_psc=72MHz,ARR = (72M/36K) - 1 = 2000 - 1 = 1999。此时,PWM周期时间对应2000个定时器时钟周期。而在中央对齐模式下,CNT会走0->1999->0,总共是3999个步数?这产生了矛盾。关键在于:在中央对齐模式下,计数器的一个“计数周期”是0->ARR->0,这被视为一个完整的定时器周期。PWM的周期与此同步。因此,设置ARR的公式与边缘对齐模式相同:ARR = (Fck_psc / Fpwm) - 1。三角波的频率就是Fpwm。CNT从0到ARR需要 (ARR+1) 个tick,从ARR到0也需要 (ARR+1) 个tick,所以三角波一个周期消耗 2*(ARR+1) 个定时器时钟?不对,这样频率就对不上了。正确的硬件行为是:在中央对齐模式,定时器时钟驱动CNT每次加1或减1。从0到ARR,需要ARR个时钟脉冲(0->1, 1->2, ..., (ARR-1)->ARR)。到达ARR后,下一个时钟脉冲到来时,CNT变为ARR-1,开始递减。因此,一个完整的三角波周期(0->ARR->0)需要2 * ARR个时钟脉冲。那么,PWM频率 Fpwm = Fck_psc / (2 * ARR)。所以,为了得到目标频率,应该设置ARR = Fck_psc / (2 * Fpwm)。很多资料和库函数(如HAL库的HAL_TIM_PWM_Init)内部计算正是基于此。我们采用这个更精确的理解:中央对齐模式下,ARR值直接决定了三角波的峰值,PWM周期对应的时钟数为2 * ARR,因此Fpwm = Fck_psc / (2 * ARR)。假设Fck_psc=72MHz,目标Fpwm=36KHz,则 ARR = 72M / (2 * 36K) = 1000。ARR设为1000。 - 相位差计算:90度相位差对应1/4个PWM周期。在三角波上,一个完整周期是0->ARR->0。我们可以将相位差映射为CCRx值的偏移量。一个简单的方法是:相位差对应的CCR偏移量 = (相位差角度 / 360°) * ARR。但注意,在中央对齐模式下,CCR值影响的是脉冲边沿在三角波上的位置。要让CH2滞后CH1 90度,意味着CH2的脉冲中心(或边沿)要比CH1的晚1/4个周期。
- 更实用的操作:假设我们想要CH1和CH2都是50%占空比,但CH2滞后CH1 90度。
- 对于50%占空比,脉冲的中心应对应于三角波的中心(即计数器的0点或ARR点?不,对于对称PWM,50%占空比时,有效电平覆盖半个周期,CCR值通常设为ARR/2?在中央对齐模式,设置CCR=ARR/2会得到50%占空比吗?我们来推导:有效电平时间为CNT<CCR的时间。在三角波中,CNT<CCR的时间占总周期的比例是 CCR/ARR。当CCR=ARR/2时,这个比例是50%。正确。
- 因此,设ARR=1000。CH1的CCR1设为500(50%占空比)。
- 要让CH2滞后90度(即1/4周期,对应250个计数点),我们将CH2的CCR2设置为 CCR1 + 相位偏移。但要注意,当CCR值超过ARR时,会从0开始循环。所以,CCR2 = (500 + 250) % 1000 = 750。
- 这样,CH1的PWM脉冲中心(由CCR1=500定义)在三角波上升沿的500处和下降沿的500处触发动作。CH2的脉冲中心则在750处触发。从时间上看,CH2的脉冲中心比CH1的晚了250个计数点的时间,正好是ARR(1000)的1/4,即90度相位差。
配置步骤概要:
- 初始化TIM1时钟,配置时基单元:预分频器PSC,自动重载值ARR,计数模式为中央对齐模式1(
CMS=10)。 - 配置通道1和通道2为PWM模式1,并使能预装载(
OCxPE=1)。 - 设置
CCR1 = 500,CCR2 = 750。 - 使能通道输出,使能主输出(MOE,因为TIM1是高级定时器),启动定时器。
这样,TIM1_CH1和TIM1_CH2就会输出两个50%占空比、频率相同,但相位相差90度的PWM波。你可以通过逻辑分析仪或示波器清晰地观察到这一现象。
4. 实战配置:从零配置TIM1实现移相PWM
理论说了一堆,现在我们来点实际的。以下以STM32CubeIDE/HAL库为例,展示如何配置TIM1输出两路移相PWM。我们假设使用内部时钟(如72MHz),目标生成一个36kHz的中央对齐PWM,且CH2滞后CH1 90度。
4.1 时钟与引脚配置
首先,确保TIM1的时钟总线(APB2)已使能。在CubeMX中:
- 在Pinout视图,找到TIM1。
- 将
CH1和CH2设置为PWM Generation CHx。这会自动配置对应的GPIO引脚(通常是PA8, PA9),并将模式设为复用推挽输出。 - 在
Configuration标签页,点击TIM1进入参数设置。
4.2 时基单元关键参数计算与设置
这是核心步骤,任何错误都会导致频率不对或模式错误。
- Prescaler (PSC):定时器时钟预分频系数。如果APB2定时器时钟是72MHz,我们想直接用它,则PSC设为0(即不分频)。
PSC = 0。 - Counter Mode:选择
Center Aligned Mode 1。注意:在HAL库的CubeMX界面,这个选项可能直接叫“中央对齐模式1”或“Center aligned mode 1”。务必选中它。 - Counter Period (ARR):这是自动重载值。根据我们之前的公式,中央对齐模式下
Fpwm = Fck_psc / (2 * ARR)。所以ARR = Fck_psc / (2 * Fpwm)。Fck_psc = 72,000,000 HzFpwm = 36,000 HzARR = 72,000,000 / (2 * 36,000) = 72,000,000 / 72,000 = 1000- 因此,设置
ARR = 1000 - 1?等等,这里有个大坑!在HAL库和标准外设库中,ARR寄存器写入的值是“周期数减一”。因为计数器是从0开始计数的。如果ARR=999,那么计数器会从0计数到999,总共1000个值。在我们的公式ARR = Fck_psc / (2 * Fpwm)中,计算出的1000直接就是周期值。所以,在代码或CubeMX中,我们应该设置Counter Period = 1000 - 1 = 999。但更稳妥的理解是:公式计算出的ARR值,就是需要写入寄存器的值。根据公式Fpwm = Fck / ((PSC+1) * (ARR+1))在边缘对齐模式下成立。在中央对齐模式下,HAL库的内部计算可能会自动处理乘以2的关系。为了保险,我们可以用CubeMX自带的“Parameter Settings”中的“Auto-reload preload”和计算器。或者,更简单的方法:在CubeMX中,先设定为“中央对齐模式”,然后在“Counter Period”框里输入999,在下方它会显示“PWM频率”,我们看那个频率是否接近36kHz。如果显示是36kHz,那就对了。根据经验,对于72MHz时钟,36kHz中央对齐PWM,ARR设为999或1000,实际频率可能是36kHz或35.928kHz,误差很小。我们采用ARR = 999。
- auto-reload preload:务必使能(Enable)。这能保证修改ARR或CCR时,新值在下一个更新事件才生效,避免波形毛刺。
4.3 PWM通道配置
切换到PWM Generation CH1和CH2的子标签(或直接在NVIC设置下方找)。
- Mode:选择
PWM Mode 1。这个模式决定了CNT<CCR时输出有效电平(我们假设有效电平为高)。 - Pulse:这是初始的CCR值。我们先设CH1的Pulse为500(对应50%占空比,因为ARR=999,500大约是50%)。CH2的Pulse我们先设为500,后面在代码中修改以实现移相。
- Fast Mode:禁用。这用于快速强制输出,一般不需要。
- CH Polarity:根据硬件电路决定有效电平是高还是低。假设高电平有效,就选
High。 - CH Idle State:刹车或未使能时的输出状态,根据安全需求设置。
- CH Output State:使能。
4.4 生成代码与关键API调用
生成代码后,在用户代码区域(如main.c的合适位置)添加以下内容:
// 1. 启动PWM HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2); // 2. 关键:使能主输出(对于高级定时器TIM1/TIM8必须要有) __HAL_TIM_MOE_ENABLE(&htim1); // 3. 动态修改CCR值以设置相位差 // 目标:CH2滞后CH1 90度。ARR=999,90度对应偏移量 = 999 / 4 ≈ 250 uint32_t phase_shift = 250; uint32_t ccr1_value = 500; // 50%占空比 uint32_t ccr2_value = (ccr1_value + phase_shift) % (htim1.Init.Period + 1); // 注意Period是ARR寄存器值,实际周期是Period+1 __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, ccr1_value); __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, ccr2_value); // 4. (可选)如果需要更精确的控制或动态改变相位,可以封装成函数 void SetPWMPhaseShift(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t dutyCyclePercent, int32_t phaseShiftDegrees) { uint32_t arr = __HAL_TIM_GET_AUTORELOAD(htim); uint32_t ccr_base = (dutyCyclePercent * (arr + 1)) / 100; // 计算基准CCR // 将角度转换为计数点偏移。360度对应一个完整周期 (arr+1)?注意中央对齐模式一个电角度周期对应2*ARR计数点? // 更通用的方法:相位偏移时间 = (phaseShiftDegrees / 360.0) * PWM_Period // PWM_Period (以秒计) = 1 / Fpwm // 但我们需要的是计数点偏移量。已知计数点总数 per PWM周期 = 2 * (arr+1)?还是 arr+1? // 根据之前推导,中央对齐模式下,一个PWM周期对应 2*ARR 个计数时钟。 // 所以,计数点偏移量 = (phaseShiftDegrees / 360.0) * (2 * arr); uint32_t count_per_cycle = 2 * arr; // 这是CNT从0到ARR再到0走过的总步数 int32_t offset = (int32_t)((phaseShiftDegrees / 360.0) * count_per_cycle); uint32_t ccr_target = (ccr_base + offset) % (arr + 1); __HAL_TIM_SET_COMPARE(htim, Channel, ccr_target); } // 调用示例:SetPWMPhaseShift(&htim1, TIM_CHANNEL_2, 50, 90); // CH2占空比50%,滞后CH1 90度注意:
__HAL_TIM_SET_COMPARE函数会直接写入CCRx寄存器。如果使能了预装载(推荐),这个值会先写入影子寄存器,在下次更新事件时才生效。如果需要立即生效,可以在设置后手动软件触发一个更新事件(__HAL_TIM_GENERATE_SW_EVENT(&htim1, TIM_EVENTSOURCE_UPDATE)),但通常没必要,等待下一个自然更新事件即可,这样更平滑。
5. 调试技巧与常见问题排查
配置完成后,用示波器测量PA8和PA9引脚,应该能看到两路36kHz、50%占空比、相位差90度的PWM波。如果没看到,或者波形奇怪,请按以下步骤排查:
没有输出:
- 检查时钟:确认APB2时钟是否使能,TIM1是否已正确初始化(
HAL_TIM_PWM_Init是否成功)。 - 检查GPIO:确认PA8/PA9已正确复用为TIM1_CH1/CH2,并且没有和其他外设冲突。
- 检查主输出:这是TIM1/TIM8特有的坑!高级定时器的输出需要使能“主输出”(Main Output Enable, MOE),通常通过设置
BDTR寄存器的MOE位。在HAL库中,调用__HAL_TIM_MOE_ENABLE(&htim1)或HAL_TIMEx_MasterConfigSynchronization进行相关配置。忘记这一步,通道绝对没有输出。 - 检查刹车电路:如果刹车(Break)功能被意外使能或刹车输入引脚有干扰,也会强制关闭输出。检查
BDTR寄存器相关位。
- 检查时钟:确认APB2时钟是否使能,TIM1是否已正确初始化(
频率不对:
- 重新计算ARR:仔细核对时钟树,确认输入到TIM1的实际时钟频率(
Fck_psc)。注意APB预分频器的影响。如果APB总线时钟是72MHz,且APB预分频系数不为1,定时器时钟可能会被倍频。在STM32中,当APB分频系数为N(N>1)时,挂载在该总线上的定时器时钟是APB时钟的2倍。这是最容易算错的地方。 - 验证公式:使用示波器测量实际周期T,反推频率。
F_measured = 1 / T。然后根据F_measured = Fck_psc / (2 * ARR)来验证你的ARR设置。在CubeMX生成的代码中,查看htim1.Init.Period的值,它就是写入ARR寄存器的值。
- 重新计算ARR:仔细核对时钟树,确认输入到TIM1的实际时钟频率(
移相角度不准:
- CCR计算逻辑:确认你的相位差计算逻辑是否正确。特别是取模运算,确保CCR值在0到ARR之间。
- 中央对齐模式理解:确认定时器确实工作在中央对齐模式。在调试模式下,查看
TIM1->CR1寄存器的CMS位。如果误设为边缘对齐模式,移相效果会完全不同。 - 更新事件干扰:如果你在运行中动态修改CCR值,并且修改的时刻正好在计数器接近CCR值的区域,可能会导致一个周期出现毛刺。确保在“安全”的时间点更新CCR,例如在更新事件中断中修改,或者使用DMA传输。HAL库的
__HAL_TIM_SET_COMPARE在预装载使能时是安全的。
波形畸变或抖动:
- 预装载未使能:如果
ARPE或OCxPE未使能,直接修改ARR或CCR会立即生效,可能导致计数器在比较时发生错乱,产生毛刺。 - 中断负载过重:如果在中段服务程序中进行复杂的计算或操作,可能导致中断响应不及时,影响PWM时序。对于高频PWM,尽量避免在中断中做耗时操作。
- 电源噪声:对于高精度应用,确保MCU供电稳定,并尽可能让PWM驱动电路靠近负载,减少引线电感的影响。
- 预装载未使能:如果
理解TIM1的计数模式,尤其是中央对齐模式,是解锁高级定时器强大功能的第一把钥匙。从简单的PWM到复杂的多通道移相、互补输出带死区,其核心都建立在对计数器行为轨迹的精确把握之上。当你下次再看到“移相”这个词时,希望你的第一反应是:“哦,这不过是给不同的CCRx寄存器设个偏移量的事”。而这种举重若轻的信心,正是来自于对底层原理的透彻理解。在实际项目中,不妨多用手头的开发板和示波器,亲手配置几个不同的ARR和CCR值,观察波形变化,这种直观的感受比读任何文档都来得深刻。