• STM32-高级定时器


    STM32F429为例。

    目录

    高级定时器

    功能框图

    时钟源

    内部时钟源CK_INT

    外部时钟模式1:外部输入引脚TIx(x=1/2/3/4)

    外部时钟模式2:外部触发输入ETR

    内部触发输入ITRx(x=1/2/3/4)

    控制器

    时基单元

    输入捕获

    输出比较

    死区发生器

    输出控制

    断路功能

    实验环节:PWM互补输出

    常规操作

    TIM8配置

    测试环节

    实验操作及现象


    高级定时器

    高级定时器比通用定时器增加了可编程死区互补输出、重复计数器、带刹车(断路)功能,这些功能都是针对工业电机控制方面。

    功能框图

    16位向上、向下、向上/向下自动重装载计数器。

    16位可编程预分频器,1~65536。

    多达4个独立通道,用于:

            输入捕获

            输出比较

            PWM产生(边沿对齐模式和中心对齐模式)

            单脉冲模式输出

    具有可编程死区时间的互补输出。

    用外部信号控制定时器的同步电路,并将多个定时器互连在一起。

    重复计数器,仅在给定次数的计数器循环后更新定时器寄存器。

    中断输入,使定时器的输出信号处于复位状态或已知状态。

    中断/DMA生成以下事件:

            更新:计数器溢出/下溢,计数器初始化(由软件或内部/外部触发)

            触发事件(计数器启动、停止、初始化或由内部/外部触发计数)

            输入捕获

            输出比较

            断路输入

    支持增量(正交)编码器和霍尔传感器电路的定位目的。

    触发输入外部时钟或逐周期电流管理。

    时钟源

    高级控制定时器可选四种时钟源:

    内部时钟源CK_INT

    外部时钟模式1:外部输入引脚TIx(x=1/2/3/4)

    外部时钟模式2:外部触发输入ETR

    内部触发输入ITRx(x=1/2/3/4)

    内部时钟源CK_INT

    时钟信号来自芯片内部,为主频168M(STM32F407为例)。一般情况下都是使用内部时钟。当从模式控制寄存器TIMx_SMCR:SMS位为000时使用内部时钟。

    外部时钟模式1:外部输入引脚TIx(x=1/2/3/4)

    时钟信号来自定时器的输入通道TI1/2/3/4,即TIMx_CH1/2/3/4。具体使用哪一路信号,由TIM_CCMRx:CCxS[1:0]配置。CCMR1控制TI1/2,CCMR2控制TI3/4。

    如果来自外部时钟信号的频率过高或混杂有高频干扰信号的话,就需要使用滤波器对信号重新采样,来达到降频或者去除高频干扰的目的,具体由TIMx_CCMRx:ICxF[3:0]配置。

    边沿检测的信号来自于滤波器的输出,在成为触发信号前需要进行边沿检测,决定是上升沿有效还是下降沿有效,具体由TIMx_CCER:CCxP和CCxNP位配置。

    触发源有两个:滤波后的定时器输入1(TI1FP1)、滤波后的定时器输入2(TI1FP2),具体由TIMx_SMCR:TS[2:0]配置。

    选定了触发源信号后,需要把信号连接到TRGI引脚,让触发信号成为外部时钟模式1的输入,最终等于CK_PSC,然后驱动计数器CNT计数。具体由TIMx_SMCR:SMS[2:0]配置,000时为外部时钟模式1。

    经过上面的5个步骤后,最后只需使能计数器开始计数,外部时钟模式1的配置就算完成了。具体由TIMx_CR1:CEN位配置。

    外部时钟模式2:外部触发输入ETR

    时钟信号来自定时器的特定输入通道TIMx_ETR,只有一个。

    外部触发极性来自ETR引脚输入的信号,可以选择上升沿有效还是下降沿有效,具体由TIMx_SMCR:ETP位配置。

    由于ETRP的信号频率不得超过TIMx_CLK的1/4,当触发信号的频率很高时必须使用分频器来降频,具体由TIMx_SMCR:ETPS[1:0]配置。

    如果ETRP的信号频率过高或混杂有高频干扰信号的话,就需要使用滤波器对信号重新采样,来达到降频或者去除高频干扰的目的,具体由TIMx_SMCRx:ETF[3:0]配置。fDTS是由内部时钟CK_INT分频得到,具体由TIMx_CR1:CKD[1:0]配置。

    经过滤波器滤波的信号连接到ETPF引脚后,触发信号成为外部时钟模式2的输入,最终等于CK_PSC,然后驱动计数器CNT计数。具体由TIMx_SMCR:ECE位配置,1时为外部时钟模式2。

    经过上面的5个步骤后,最后只需使能计数器开始计数,外部时钟模式2的配置就算完成了。具体由TIMx_CR1:CEN位配置。

    内部触发输入ITRx(x=1/2/3/4)

    内部触发输入是使用一个定时器作为另一个定时器的预分频器。硬件上高级控制定时器和通用定时器在内部连接在一起,可以实现定时器同步和级联。主模式的定时器可以对从模式定时器只需复位、启动、停止或提供时钟。

    高级控制定时器和部分通用定时器(TIM2~TIM5)可以设置为主模式或从模式,TIM9和TIM10可以设置为从模式。

    如图,主模式定时器TIM1为从模式定时器TIM2提供时钟,即TIM1用作TIM2的预分频器。

    控制器

    触发控制器用来针对片内外设输出触发信号,比如为其它定时器提供时钟和触发DAC/ADC转换。

    编码器接口专门针对编码器计数而设计。

    从模式控制器可以控制计数器复位、启动、递增/递减、计数。

    时基单元

    高级控制定时器时基单元组成:计数器寄存器(CNT,16位有效)、预分频器寄存器(PSC,16位有效)、自动重装载寄存器(ARR,16位有效)、重复计数器寄存器(RCR,8位有效,高级定时器专有)。

    PSC预分频器寄存器有一个输入时钟CK_PSC和一个输出时钟CK_CNT。输入时钟CK_PSC就是时钟源的输出,输出时钟CK_CNT用来驱动计数器CNT计数。通过设置预分频器PSC的值可以得到不同的CK_CNT,值为1~65536分频。

    三种计数模式:递增、递减、中心对齐。

    递增计数模式:计数器从0开始计数,每一CK_CNT脉冲,计数器就加1,直到计数器的值与ARR值相等,然后计数器又从0开始计数并生成计数器上溢事件,如此循环。如果禁用重复计数器,在计数器生成上溢事件就马上生成更新事件(UEV);如果使能重复计数器,每生成一次上溢事件,重复计数器就减1,直到减为0时才会生成更新事件(UEV)。

    递减计数模式:计数器从ARR值开始计数,每一CK_CNT脉冲,计数器就减1,直到计数器的值减为0,然后计数器又从ARR值开始计数并生成计数器下溢事件,如此循环。如果禁用重复计数器,在计数器生成下溢事件就马上生成更新事件(UEV);如果使能重复计数器,每生成一次下溢事件,重复计数器就减1,直到减为0时才会生成更新事件(UEV)。

    中心对齐模式:计数器从0开始递增,直到计数器的值与(ARR-1)值相等,生成计数器上溢事件。然后计数器又从ARR开始递减,直到计数器的值为1时生成计数器下溢事件。然后重新重0开始,如此循环。每次发送计数器上溢和下溢事件都会生成更新事件。

    ARR自动重装载寄存器用来存放与CNT比较值。如果CNT值等于ARR值,就递减重复计数器。可以通过TIMx_CR1:ARPE位控制自动重装载影子寄存器功能,如果ARPE位置1,只有在事件更新时才把TIMx_ARR值赋给影子寄存器。如果ARPE位置0,则修改TIMx_ARR值时马上赋给影子寄存器。

    在基本/通用定时器发生上溢/下溢事件时直接就生成更新事件,但对于高级控制定时器在硬件结构上多出了RCR重复计数器寄存器,在定时器发生上溢/下溢事件会递减重复计数器的值,当重复计数器的值为0时才生成更新事件。在发生N+1个上溢/下溢事件时产生更新事件(N为RCR的值)。

    输入捕获

    输入捕获可以对输入的信号上升沿、下降沿或双边沿进行捕获,常用的有测量输入信号的脉宽和测量PWM输入信号的频率和占空比。

    大概原理是当捕获到信号的跳变沿时,把CNT计数器的值锁存到捕获寄存器CCR中,把前后两次捕获到的CCR寄存器中的值相减,就可以算出脉宽和频率。如果捕获的脉宽的时间长度超过捕获定时器的周期,就会发生溢出,需要额外做处理。

    TIx为输入通道,需要被测量的信号从定时器的外部引脚TIMx_CH1/2/3/4进入

    当输入的信号存在高频干扰时,需要对输入信号进行滤波,根据采样定律(采样频率必须大于或等于两倍的输入信号),比如输入信号为1M,存在高频信号干扰时就要进行滤波,可以设置采样频率为2M,这样可以在保证采样到有效信号的基础上把高于2M的高频干扰信号过滤掉。

    输入滤波器的配置由TIMx_CR1:CKD[1:0]和TIMx_CCMR1/2:ICxF[3:0]控制。根据ICxF位的描述,采样频率Fsample可以由Fck_int(内部时钟)和Fdts(Fck_int经过分频后的频率,分频因子由CKD[1:0]决定,1/2/4分频)分频后的时钟提供。

    边沿检测器用来设置信号在捕获时什么边沿有效(上升沿、下降沿、双边沿),具体由TIMx_CCER:CCxP、CCxNP决定。

    捕获通道:IC1/2/3/4。每个捕获通道都有对应的捕获寄存器CCR1/2/3/4,当发生捕获时,计数器CNT的值就会被锁存到捕获寄存器中。

    输入通道TIx是用来输入信号的,捕获通道ICx是用来捕获输入信号的通道。一个输入通道的信号可以同时输入给两个捕获通道。比如TI1的信号经过滤波和边沿检测器后TI1FP1和TI1FP2可以进入到捕获通道IC1和IC2。输入通道和捕获通道的映射关系具体由TIMx_CCMR:CCxS[1:0]配置。

    ICx的输出信号会经过预分频器,用于决定发生多少个事件时进行一次捕获。具体由TIMx_CCMR:ICxPSC配置。如果希望捕获信号的每一个边沿,则不分频。

    经过预分频器的信号ICxPS是最终被捕获的信号,当发生捕获时(第一次),计数器CNT的值会被锁存到捕获寄存器TIMx_CCR中,还会产生CCxI中断,相应的中断位CCxIF(在SR寄存器中)会被置位,通过软件或读取CCR的值可以将CCxIF清0。如果发生第二次捕获(即重复捕获,CCR寄存器中已捕获到计数器值且CCxIF标志已置1),则捕获溢出标志位CCxOF(在SR寄存器中)会被置位,CCx_OF只能通过软件清零

    输出比较

    输出比较就是通过定时器的外部引脚对外输出控制信号

    输出比较八种模式:冻结、将通道x(x=1/2/3/4)设置为匹配时输出有效电平、将通道x(x=1/2/3/4)设置为匹配时输出无效电平、翻转、强制变为无效电平、强制变为有效电平、PWM1和PWM2。具体有寄存器CCMRx:OCxM[2:0]配置,PWM模式是输出比较的特例,使用的也最多。

    当计数器CNT的值跟比较寄存器CCR的值相等时,输出参考信号OCxREF的信号极性就会发生改变(OCxREF=1,是有效电平;OCxREF=0,是无效电平),并且会产生比较中断CCxl,SR寄存器中的标志位CCxIF会置位。然后OCxREF再经过一系列的控制后就成为真正的输出信号OCx/OCxN。

    输出比较的输出信号最终是通过定时器的外部IO来输出的,分别是CH1/2/3/4,其中前面三个通道还有互补的输出通道CH1N/2N/3N。

    死区发生器

    在生成的参考信号OCxREF的基础上,可以插入死区时间,用于生成两路互补的输出信号OCx和OCxN。死区时间的大小具体由BDTR:DTG[7:0]配置。死区时间的大小必须根据与输出信号相连接的器件及其特性来调整。

    举个例子:带死区的PWM信号的应用,以一个半桥驱动电路为例。

    在这个半桥驱动电路,Q1导通、Q2截止。如果想让Q1截止、Q2导通,肯定是先让Q1截止一段时间,再等待一段时间才让Q2导通,这个等待时间就是死区时间。

    因为Q1关闭需要时间(由MOS管的工艺决定),如果Q1关闭后马上打开Q2,那么此时一段时间内相当于Q1和Q2都导通了,电路会短路。

    输出控制

    在输出比较的输出控制中,参考信号OCxREF在经过死区发生器后会产生两路带死区的互补信号OCx_DT和OCxN_DT(通道1~3才有互补信号,通道4没有),这两路带死区的互补信号然后进入输出控制电路。如果没有加入死区控制(不经过死区发生器),那么进入输出控制电路的信号就直接是OCxREF。

    进入输出控制电路的信号会被分为两路(一路为原始信号,一路为被反向的信号),具体由CCER:CCxP、CCxNP位控制。经过极性选择的信号是否由OCx引脚输出到外部引脚CHx/CHxN则由CCER:CxE/CxNE位配置。

    如果加入了断路(刹车)功能,则断路和死区寄存器TIMx_BDTR:MOE、OSSI和OSSR位会共同影响输出的信号。

    断路功能

    断路功能就是电机控制的刹车功能。使能断路功能时,根据相关控制位状态修改输出信号电平。在任何情况下,OCx和OCxN输出都不能同时为有效电平,这关系到电机控制常用的H桥电路结构原因。

    断路源可以是时钟故障事件,其内部复位时钟控制器的时钟安全系统(CSS)生成,也可以是外部断路输入IO,两者是或运算关系。

    系统复位启动都默认关闭断路功能,将断路和死区寄存器TIMx_BDTR:BKE=1,使能断路功能。可通过TIMx_BDTR:BKP位设置断路输入引脚的有效电平,为1时输入BRK为高电平有效,否则低电平有效。

    发生断路时,将产生以下效果:

    TIMx_BDTR:MOE主输出模式使能位被清零,输出处于无效、空闲或复位状态。

    根据相关控制位状态去控制输出通道引脚电平;当使能通道互补输出时,会根据情况自动控制输出通道电平。

    将TIMx_SR:BIF位置1,并可产生中断和DMA传输请求。

    如果TIMx_BDTR:AOE自动输出使能位置1,则MOE位会在发生下一个UEV事件时自动再次置1。

    实验环节:PWM互补输出

    常规操作

    配置按键KEY1和KEY2。

    TIM8配置

    TIM8_CH1:OCPWM:PC6 

    TIM8_CH1N:OCNPWM:PA5

    TIM8_BKIN:BKIN:PA6

    1. TIM_HandleTypeDef htim8;
    2. void MX_TIM8_Init(void)
    3. {
    4. TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    5. TIM_MasterConfigTypeDef sMasterConfig = {0};
    6. TIM_OC_InitTypeDef sConfigOC = {0};
    7. TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
    8. htim8.Instance = TIM8;
    9. htim8.Init.Prescaler = 167;
    10. htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
    11. htim8.Init.Period = 999;
    12. htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    13. htim8.Init.RepetitionCounter = 0; // 重复计数器
    14. htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    15. if (HAL_TIM_Base_Init(&htim8) != HAL_OK)
    16. {
    17. Error_Handler();
    18. }
    19. sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    20. if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK)
    21. {
    22. Error_Handler();
    23. }
    24. if (HAL_TIM_PWM_Init(&htim8) != HAL_OK)
    25. {
    26. Error_Handler();
    27. }
    28. sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    29. sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    30. if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig) != HAL_OK)
    31. {
    32. Error_Handler();
    33. }
    34. sConfigOC.OCMode = TIM_OCMODE_PWM1; // PWM1为跳变后电平,PWM2为跳变前电平
    35. sConfigOC.Pulse = 500;
    36. sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; // 达到跳变值Pulse,电平跳变为高电平
    37. sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; // 达到跳变值Pulse,电平跳变为高电平
    38. sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    39. sConfigOC.OCIdleState = TIM_OCIDLESTATE_SET; // 空闲状态下经过死区时间后定时器通道输出高电平
    40. sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; // 空闲状态下经过死区时间后定时器通道输出低电平
    41. if (HAL_TIM_PWM_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
    42. {
    43. Error_Handler();
    44. }
    45. sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE; // 运行模式下的关闭状态选择
    46. sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE; // 空闲模式下的关闭状态选择
    47. sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1; // 锁定级别配置,(不能写入某些寄存器的某些位,防止意外修改)
    48. sBreakDeadTimeConfig.DeadTime = 11; // 死区持续时间
    49. sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE;
    50. sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW; // 断路输入通道BRK极性,低电平触发刹车
    51. sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;
    52. if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig) != HAL_OK)
    53. {
    54. Error_Handler();
    55. }
    56. HAL_TIM_MspPostInit(&htim8);
    57. /* 定时器通道1输出PWM */
    58. HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1);
    59. /* 定时器通道1互补输出PWM */
    60. HAL_TIMEx_PWMN_Start(&htim8, TIM_CHANNEL_1);
    61. }
    62. void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
    63. {
    64. GPIO_InitTypeDef GPIO_InitStruct = {0};
    65. if(tim_baseHandle->Instance==TIM8)
    66. {
    67. __HAL_RCC_TIM8_CLK_ENABLE();
    68. __HAL_RCC_GPIOA_CLK_ENABLE();
    69. /**TIM8 GPIO Configuration
    70. PA6 ------> TIM8_BKIN
    71. */
    72. GPIO_InitStruct.Pin = GPIO_PIN_6;
    73. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    74. GPIO_InitStruct.Pull = GPIO_NOPULL;
    75. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    76. GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
    77. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    78. }
    79. }
    80. void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
    81. {
    82. GPIO_InitTypeDef GPIO_InitStruct = {0};
    83. if(timHandle->Instance==TIM8)
    84. {
    85. __HAL_RCC_GPIOA_CLK_ENABLE();
    86. __HAL_RCC_GPIOC_CLK_ENABLE();
    87. /**TIM8 GPIO Configuration
    88. PA5 ------> TIM8_CH1N
    89. PC6 ------> TIM8_CH1
    90. */
    91. GPIO_InitStruct.Pin = GPIO_PIN_5;
    92. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    93. GPIO_InitStruct.Pull = GPIO_NOPULL;
    94. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    95. GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
    96. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    97. GPIO_InitStruct.Pin = GPIO_PIN_6;
    98. GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    99. GPIO_InitStruct.Pull = GPIO_NOPULL;
    100. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    101. GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
    102. HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    103. }
    104. }
    105. void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
    106. {
    107. if(tim_baseHandle->Instance==TIM8)
    108. {
    109. __HAL_RCC_TIM8_CLK_DISABLE();
    110. /**TIM8 GPIO Configuration
    111. PA5 ------> TIM8_CH1N
    112. PA6 ------> TIM8_BKIN
    113. PC6 ------> TIM8_CH1
    114. */
    115. HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6);
    116. HAL_GPIO_DeInit(GPIOC, GPIO_PIN_6);
    117. }
    118. }

    测试环节

    1. __IO uint16_t ChannelPulse = 500;
    2. void test(void)
    3. {
    4. 初始化
    5. while (1)
    6. {
    7. /* 扫描KEY1 */
    8. if (Key_Scan(KEY1_GPIO_PORT, KEY1_PIN) == KEY_ON)
    9. {
    10. /* 增大占空比 */
    11. if (ChannelPulse < 950)
    12. {
    13. ChannelPulse += 50;
    14. }
    15. else
    16. {
    17. ChannelPulse = 1000;
    18. }
    19. __HAL_TIM_SetCompare(&htim8, TIM_CHANNEL_1, ChannelPulse);
    20. }
    21. /* 扫描KEY2 */
    22. if (Key_Scan(KEY2_GPIO_PORT, KEY2_PIN) == KEY_ON)
    23. {
    24. /* 减小占空比 */
    25. if (ChannelPulse >= 50)
    26. {
    27. ChannelPulse -= 50;
    28. }
    29. else
    30. {
    31. ChannelPulse = 0;
    32. }
    33. __HAL_TIM_SetCompare(&htim8, TIM_CHANNEL_1, ChannelPulse);
    34. }
    35. }
    36. }

    实验操作及现象

    将PC6(OC)和PA5(OCN)引脚接在示波器的两个输入通道上(注意共地),将PA6(BKIN)接在带上拉的输入按键上(保持3.3V高电平)。

    可观察示波器波形。

    按下KEY1和KEY2按键可增加或减少PWM波形的占空比大小,可实现0%到100%的波形输出。

    控制断路输入引脚PA6为低电平,两个通道保持直接输出相反电平。

  • 相关阅读:
    DHCP学习
    生成式AI,赋能数字劳动力的关键工具
    探究Presto SQL引擎(3)-代码生成
    10个微服务设计模式
    keycloak~jwt的rs256签名的验证方式
    动态规划问题(二)
    阿里巴巴面试题- - -JVM篇(十五)
    Perl中的单行注释和多行注释语法
    uni-app 介绍及使用
    Foxmail新版本迁移邮箱的数据文件教程
  • 原文地址:https://blog.csdn.net/weixin_47077788/article/details/134205705