6、PWM输出

1.1、输出比较

输出比较(Output Compare,简称OC)是微控制器中的一个重要功能,用于生成PWM信号、产生精确的时间延迟或者触发特定事件。以下是关于输出比较的一些基本概念:

  1. Output Compare 寄存器(CCR):输出比较功能通过比较定时器的计数器的值(CNT)与一个特定的比较值(CCR寄存器的值)来控制输出电平的变化。当计数值与CCR寄存器的值相等或满足特定的条件时,可以触发输出操作。

  2. PWM 生成:输出比较通常用于生成脉冲宽度调制(PWM)信号,用于控制电机速度、LED亮度等。通过设定CCR寄存器的值,可以确定PWM信号的占空比,即高电平的持续时间与一个周期的比例。

  3. 死区控制:某些高级定时器的输出比较通道支持死区控制功能,用于防止同时开启两个输出通道导致短路或电流过大的情况。死区是两个输出通道之间的时间间隔,可以设置为一个固定值。

  4. 互补输出:某些高级定时器的输出比较通道支持互补输出功能,即同时控制两个输出引脚的状态,一个输出高电平时,另一个输出低电平,反之亦然。

  5. 事件触发:输出比较通道可以用于触发特定事件,例如捕获输入信号的边沿、生成精确的时间延迟等。

  6. 定时器类型:不同型号的微控制器和定时器支持不同数量的输出比较通道,以及不同的功能。一些常见的定时器包括TIM1、TIM2、TIM3等,它们通常有多个输出比较通道。

使用输出比较功能需要初始化定时器和相应的输出比较通道,并设置CCR寄存器的值来控制输出的行为。这在控制电机、LED调光、精确的时间控制等应用中非常有用。

1.2、PWM简介

PWM(Pulse Width Modulation)脉冲宽度调制在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制(不断通电断电),来等效地获得所需要的模拟参量,常应用于电机控速等领域。

PWM参数:

  • 频率 = 1 / TS
  • 占空比 = TON / TS
  • 分辨率 = 占空比变化步距

1695209171269

1695209212325

1.3、输出比较模式

image-20230920194614012

1.4、PWM基本结构

img

在时基单元部分,输出PWM不需要中断。

  1. 黄色线 (ARR的值): 自动重载寄存器(ARR)的值决定了PWM信号的周期。在这段代码中,ARR的值被设置为99,这意味着PWM信号的周期是100个计数周期。如果TIM2的时钟频率为72 MHz(由PSC设置),则PWM信号的频率将为72 MHz / 100 = 720 kHz。
  2. 蓝色线 (CNT的值): 计数器寄存器(CNT)的值代表当前的计数周期。在PWM运行期间,CNT的值会在0到ARR之间循环。这个计数值不断递增,然后重新从0开始。
  3. 红色线 (CCR1): 通道1比较寄存器(CCR1)的值决定了PWM信号的占空比。在这段代码中,CCR1的初始值被设置为0,这意味着PWM信号的占空比为0%。通过调用PWM_SetCompare1函数,您可以更改CCR1的值来调整PWM信号的占空比,使其变得不同。
  4. 绿色线 (输出PWM): PWM输出信号是TIM2根据CCR1和CNT的值生成的。占空比由CCR1的值控制,周期由ARR的值控制。通过不断改变CCR1的值,可以改变PWM信号的占空比。在周期开始时,输出被设置为高电平(在这种情况下,红色线所示),然后在CNT计数到CCR1时切换为低电平。

PWM模式1:

​ CNT < CCR:输出高电平

​ CNT ≥ CCR:输出低电平

CCR设置的高一些,输出的占空比就变大;CCR设置的低一些,输出的占空比就变小。

1.5、参数计算:

img

img

  1. PWM频率 (Freg):PWM信号的频率,通常以赫兹(Hz)为单位,可以使用以下公式计算:

    1
    Freg = CK_PSC / (PSC + 1) / (ARR + 1)
    • CK_PSC 是TIMx的时钟频率。系统的主频72MHz(72,000,000Hz)
    • PSC 是TIMx的预分频器(Prescaler)的值
    • ARR 是TIMx的自动重载寄存器(Auto Reload Register)的值
  2. PWM占空比 (Duty):PWM信号的占空比表示高电平占据一个周期的比例,通常以百分比表示,可以使用以下公式计算:

    1
    Duty = CCR / (ARR + 1)
    • CCR 是TIMx的比较寄存器(Capture/Compare Register)的值。
    • ARR 是TIMx的自动重载寄存器的值。
  3. PWM分辨率 (Reso):PWM信号的分辨率表示可以实现的不同占空比的级别数量,通常是单位占空比所代表的大小,可以使用以下公式计算:

    1
    Reso = 1 / (ARR + 1)
    • ARR 是TIMx的自动重载寄存器的值

2、引脚重映射

引脚重定义(重映射):当一个引脚有多个功能时,如果可以进行重定义功能,则可以通过重映射的功能把原来的引脚映射到新的引脚上。这样就可以避免两个外设引脚的冲突。

在STM32微控制器系列中,引脚重映射通常由AFIO(Alternate Function I/O)模块来控制。以下是使用引脚重映射的一般步骤:

  1. 启用AFIO时钟:在使用引脚重映射之前,需要启用AFIO外设的时钟。这通常涉及到使用RCC_APB2PeriphClockCmd函数来启用RCC(Reset and Clock Control)外设的时钟。

  2. 配置引脚重映射:使用AFIO外设的寄存器来配置引脚的重映射。不同的STM32系列和型号可能有不同的寄存器和位字段用于配置重映射。您需要查阅特定型号的参考手册来了解详细信息。

  3. 初始化GPIO引脚:在重新映射引脚之后,需要确保与外设相关的GPIO引脚被正确初始化,以适应新的引脚功能。通常,您需要将GPIO引脚配置为适当的模式和设置(例如,复用推挽输出)。

  4. 使用重映射后的引脚:现在,您可以将重映射后的引脚用于所需的外设功能。这些引脚将按照重映射配置来执行相应的任务。

以下是一个示例代码片段,演示了如何启用引脚重映射:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 启用AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

// 配置引脚重映射(示例,具体配置根据您的需求)
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);

// 初始化GPIO引脚
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 配置为新映射的引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// 现在可以将GPIOA的引脚0用于新的外设功能

如果想要定时器来控制输出引脚,需要使用复用推挽输出的模式

2.1、在什么情况下会用到

引脚重映射在以下几种情况下非常有用:

  1. 多功能引脚:某些微控制器引脚具有多个功能。例如,一个引脚可以用作GPIO、USART、SPI、PWM等等。在这种情况下,可以使用引脚重映射来选择一个功能并将其映射到特定引脚上,以满足您的应用需求。
  2. 引脚冲突:有时,不同外设可能需要使用相同的引脚,这会导致冲突。通过使用引脚重映射,您可以将其中一个外设的引脚映射到另一个引脚,以解决冲突。
  3. 电路板布局:在某些情况下,电路板的布局可能需要更改引脚的连接方式。引脚重映射允许您重新分配引脚的功能,而无需更改硬件布局。
  4. 性能优化:有些引脚重映射的配置可以提高性能。例如,某些STM32系列允许将USART的引脚重映射到更高性能的引脚上,以获得更快的通信速度。
  5. 适应外设需求:某些外设可能需要特定的引脚配置才能正常工作。通过引脚重映射,您可以满足外设的特定要求。
  6. 降低功耗:在一些情况下,引脚重映射可以帮助降低功耗,例如选择更低功耗的引脚模式。

总之,引脚重映射提供了一种在特定应用需求下重新配置引脚功能的灵活方法,以满足不同的硬件和应用要求。这使得微控制器更加适应各种不同的应用场景。

3、设计PWM输出的基本步骤:

  1. 开启RCC时钟,把需要的TIM外设和GPIO外设的时钟打开

  2. 配置时基单元TIM_TimeBaseInitTypeDef,包括前面的时钟源选择

  3. 配置输出比较单元TIM_OCInitTypeDef:CCR的值,输出比较模式、极性选择、输出使能这些参数

  4. 配置GPIO,把PWM对应的GPIO口,初始化为复用推挽输出的配置。

img

img

如果要使用TIM2的OC1也就是CH1通道输出PWM,只能使用PA0输出PWM

TIM2的OC2只能使用PA1输出PWM

TIM2的OC3使用PA2

TIM2的OC4使用PA3

3.1、定时器输出比较通道函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* @brief 初始化TIMx的输出比较通道1(OC1)。
* @param TIMx: 要初始化的定时器(例如TIM1、TIM2等)。
* @param TIM_OCInitStruct: 指向TIM_OCInitTypeDef结构的指针,其中包含OC1通道的配置信息。
* @retval 无
*/
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

/**
* @brief 初始化TIMx的输出比较通道2(OC2)。
* @param TIMx: 要初始化的定时器(例如TIM1、TIM2等)。
* @param TIM_OCInitStruct: 指向TIM_OCInitTypeDef结构的指针,其中包含OC2通道的配置信息。
* @retval 无
*/
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

/**
* @brief 初始化TIMx的输出比较通道3(OC3)。
* @param TIMx: 要初始化的定时器(例如TIM1、TIM2等)。
* @param TIM_OCInitStruct: 指向TIM_OCInitTypeDef结构的指针,其中包含OC3通道的配置信息。
* @retval 无
*/
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

/**
* @brief 初始化TIMx的输出比较通道4(OC4)。
* @param TIMx: 要初始化的定时器(例如TIM1、TIM2等)。
* @param TIM_OCInitStruct: 指向TIM_OCInitTypeDef结构的指针,其中包含OC4通道的配置信息。
* @retval 无
*/
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

这些函数用于初始化定时器的输出比较通道。下面是函数的主要作用和参数的含义:

  • TIMx: 要初始化的定时器,可以是 TIM1、TIM2 等 TIM_TypeDef 结构体的指针。

  • TIM_OCInitStruct: 包含了配置输出比较通道所需参数的结构体指针,需要使用 TIM_OCInitTypeDef 类型的变量初始化。

其中 TIM_OCInitTypeDef 结构体包含了配置输出比较通道的参数,主要包括以下字段:

  • TIM_OCMode: 用于设置比较通道的工作模式,可以选择 PWM 模式、脉冲模式等。

  • TIM_OutputState: 用于启用或禁用比较通道的输出。

  • TIM_OCPolarity: 用于设置比较输出的极性,可以选择正极性或负极性。

  • TIM_Pulse: 用于设置比较值,决定了比较通道的触发时间或 PWM 的占空比。

通过适当配置这些参数,可以实现不同输出比较通道的操作方式,例如生成 PWM 信号、测量脉冲宽度等。

1
2
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);
//仅高级定时器使用,在使用高级定时器输出PWM时,需要调用这个函数,使能主输出,否则PWM将不能正常输出

3.2、设置定时器的输出比较通道的比较值

这些函数用于设置定时器的输出比较通道的比较值。以下是对这些函数的注释解释,包括函数的作用和参数的含义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* @brief 设置TIMx的输出比较通道1(OC1)的比较值。
* @param TIMx: 要设置的定时器(例如TIM1、TIM2等)。
* @param Compare1: 要设置的比较值,决定了OC1通道的触发时间或PWM的占空比。
* @retval 无
*/
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);

/**
* @brief 设置TIMx的输出比较通道2(OC2)的比较值。
* @param TIMx: 要设置的定时器(例如TIM1、TIM2等)。
* @param Compare2: 要设置的比较值,决定了OC2通道的触发时间或PWM的占空比。
* @retval 无
*/
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);

/**
* @brief 设置TIMx的输出比较通道3(OC3)的比较值。
* @param TIMx: 要设置的定时器(例如TIM1、TIM2等)。
* @param Compare3: 要设置的比较值,决定了OC3通道的触发时间或PWM的占空比。
* @retval 无
*/
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);

/**
* @brief 设置TIMx的输出比较通道4(OC4)的比较值。
* @param TIMx: 要设置的定时器(例如TIM1、TIM2等)。
* @param Compare4: 要设置的比较值,决定了OC4通道的触发时间或PWM的占空比。
* @retval 无
*/
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

这些函数用于在定时器的输出比较通道中设置比较值,从而决定了通道的触发时间或 PWM 的占空比。下面是函数的主要作用和参数的含义:

  • TIMx: 要设置的定时器,可以是 TIM1、TIM2 等 TIM_TypeDef 结构体的指针。

  • Compare1, Compare2, Compare3, Compare4: 要设置的比较值,这些值决定了对应输出比较通道的触发时间或 PWM 的占空比。这些值是一个16位的无符号整数,通常的范围是 0 到 TIM_Period 之间,其中 TIM_Period 是定时器的自动重装载值。不同的比较值将导致不同的输出效果,例如不同的 PWM 占空比。

3.3、配置和控制PWM输出

这段代码是用来在STM32微控制器上配置和控制PWM(脉冲宽度调制)输出的,具体使用了TIM2外设和GPIO引脚PA0。下面是对代码的详细注释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void PWM_Init(void)
{
// 启用TIM2和GPIOA的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

// GPIO初始化结构体
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 配置为复用推挽输出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 配置为PA0引脚
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 设置引脚速度
GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA

// 配置TIM2使用内部时钟源
TIM_InternalClockConfig(TIM2);

// TIM2的时间基准初始化结构体
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分频为TIM_CKD_DIV1
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; // 自动重载寄存器值,决定PWM频率(ARR)
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; // 预分频值,决定时钟频率(PSC)
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; // 重复计数器
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); // 初始化TIM2的时间基准

// TIM2的输出比较初始化结构体
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure); // 将结构体初始化为默认值
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 输出极性为高电平有效
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
TIM_OCInitStructure.TIM_Pulse = 0; // CCR寄存器,决定PWM的占空比
TIM_OC1Init(TIM2, &TIM_OCInitStructure); // 初始化TIM2的通道1

// 启用TIM2
TIM_Cmd(TIM2, ENABLE);
}

void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2, Compare); // 设置TIM2的通道1的占空比
}

这段代码的目的是初始化TIM2外设,配置它以生成PWM信号,并允许您使用PWM_SetCompare1函数来动态更改PWM信号的占空比。请注意,TIM2在此代码中被配置为以内部时钟为基准,PWM的频率和占空比由TIM_TimeBaseInitStructureTIM_OCInitStructure中的参数值确定。您可以调整这些参数以满足您的具体需求。

4、 PWM驱动舵机

舵机是一种根据输入PWM信号占空比来控制输出角度的装置,

根据输入PWM信号的要求,周期为20ms,高电平宽度为0.5ms~2.5ms。

1695210887577

img

PWM参数计算:

PWM频率:50hz

ARR = 20k - 1

PSC = 72 -1

注:20K对应20ms,那么CCR设置为500,就是0.5ms,参数很直观

注意PWM的VCC接到5V

5、PWM驱动直流电机

1、直流电机及驱动简介

  • 直流电机是一种将电能转换为机械能的装置,有两个电极,当电极正接时,电机正转,当电极反接时,电机反转
  • 直流电机属于大功率器件,GPIO口无法直接驱动,需要配合电机驱动电路来操作
  • TB6612是一款双路H桥型的直流电机驱动芯片,可以驱动两个直流电机并且控制其转速和方向

2、tb6612硬件电路:

image-20230917131617127

  • VCC:这是电源引脚,用于供电给TB6612芯片。通常,VCC引脚连接到一个电源电压,例如5V。
  • GND:这是地引脚,连接到电源的地。
  • IN1AIN1B:这些是输入引脚,用于控制Motor A的方向。通过将它们连接到不同的电平(高或低),您可以控制电机的正转和反转。
  • IN2AIN2B:这些也是输入引脚,用于控制Motor B的方向。
  • PWM:这是输入引脚,用于控制电机的速度。通过在此引脚上应用PWM信号,您可以调整电机的速度。
  • Motor AMotor B:这是两个直流电机的连接端口,您需要将电机的两个引脚分别连接到这两个端口。

请注意,TB6612有多个型号和封装,实际的引脚和功能可能会有所不同。在使用TB6612时,请务必参考其数据手册以确保正确连接和配置。此外,还需要提供适当的电源电压以供电机驱动器和电机运行。

7、IC输入捕获

IC(Input Capture)输入捕获是一种常见于微控制器(MCU)定时器/计数器模块的功能。它允许MCU测量外部事件的时间参数,如脉冲的宽度、周期、频率等。以下是关于IC输入捕获模式的一些重要信息:

  1. 捕获触发条件:在IC输入捕获模式下,定时器会监视一个特定的输入引脚。当该引脚上的信号出现指定电平的跳变(例如上升沿或下降沿)时,定时器将记录当前计数器(CNT)的值,并将其锁存到捕获比较寄存器(CCR)中。
  2. 用途:IC输入捕获可用于测量各种参数,如PWM波形的频率、占空比、脉冲宽度、电平持续时间等。这对于需要精确测量外部信号特性的应用非常有用,如电机控制、编码器反馈、传感器输入等。
  3. 通道数量:每个高级定时器和通用定时器通常都支持多个IC输入捕获通道,通常有4个。这意味着您可以同时测量多个外部事件的参数。
  4. PWMI模式:IC输入捕获模式可以配置为PWMI(PWM输入)模式,使其能够测量PWM信号的频率和占空比。这对于检测和控制PWM信号的特性非常有用。
  5. 主从触发模式:定时器可以配置为主从触发模式,其中一个定时器可以触发另一个定时器的捕获操作。这允许硬件全自动测量,特别是在多个定时器之间协同工作时。image-20230918101049347

总之,IC输入捕获模式是一种非常有用的功能,可以帮助MCU测量和监视外部事件的时间参数,从而实现各种应用,包括控制和传感器接口。

7.1、频率测量

这是关于频率测量方法中的测频法、测周法和中界频率的一些重要概念和公式:

  1. 测频法(Frequency Counting Method):在测频法中,您测量在一个固定的时间间隔T内上升沿的数量N。然后,通过以下公式计算频率f:

    1
    fx = N / T

    这个方法适用于测量频率的应用,其中您知道测量时间T,并且您想要知道信号的频率。

  2. 测周法(Period Counting Method):在测周法中,您测量两个连续上升沿之间的时间间隔T,并且您知道一个已知的标准频率f。然后,通过以下公式计算频率f:

    1
    fx = fc / N

    这个方法适用于测量周期的应用,其中您知道一个已知频率的标准信号,然后测量要研究的信号的周期。

  3. 中界频率(Intermediate Frequency,fm):中界频率是指测频法和测周法误差相等的频率点。它可以使用以下公式计算:

    1
    fm = √(fc / T)
    • fm:中界频率
    • fc:测频法和测周法的误差频率
    • T:测量时间间隔

    中界频率对于理解在不同测量方法下频率测量的误差行为非常有用。在中界频率以下,测周法可能更准确,而在中界频率以上,测频法可能更准确。

这些概念和公式可以帮助您更好地理解频率和周期测量方法以及它们之间的误差。选择适当的测量方法和理解误差行为对于准确测量频率和周期非常重要。