STM32F103RCT6 -- 定时器TIM2 输出 PWM 波形

本文详细介绍了如何在STM32F103RCT6微控制器上使用TIM2定时器生成40kHz的PWM信号,包括设置时钟源、预分频系数、计数周期和占空比。同时,讨论了PWM信号在电机速度控制、LED亮度调节、声音发生以及电压调节中的应用,并提供了相应的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 实现方式:

在STM32F103RCT6上产生一个40kHz的PWM信号,可以选择使用TIM2定时器。首先,需要配置TIM2的时钟源和预分频系数,以获得正确的计数时钟。由于要输出40kHz的PWM信号,因此可以将计数器的周期设置为1800(即72MHz/40kHz),以便每个PWM周期的持续时间是1/40kHz=25us。

然后,需要计算占空比。在本例中,占空比为50%,因此可以将CCR值设置为周期的一半,即900。在计数器溢出之前到达900时,输出会被拉高。当计数器再次比900小的时候,输出会被拉低。

最后,需要配置TIM2的PWM模式和输出通道,以便产生正确的PWM信号。在这里,我们通过设置PWM模式为TIM_OCMode_PWM1和输出通道为TIM_OCMode_PWM2来实现。

2. 代码实现:

// 定义周期
#define PWM_PERIOD 1800

// 定义占空比
#define DUTY_CYCLE (PWM_PERIOD / 2)

// 配置TIM2为PWM输出模式
void TIM2_PWM_Init(void)
{
    // 定义结构体变量
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_OCInitTypeDef TIM_OCInitStruct;

    // 使能TIM2时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 初始化TIM2
    TIM_TimeBaseInitStruct.TIM_Prescaler = 0;   // 不预分频
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数模式
    TIM_TimeBaseInitStruct.TIM_Period = PWM_PERIOD - 1;  // 自动重装载值
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  // 时钟分频
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);

    // 配置TIM2为PWM模式,输出通道2
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;  // PWM模式1
    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;  // 使能输出
    TIM_OCInitStruct.TIM_Pulse = DUTY_CYCLE;  // 占空比
    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;  // 输出极性为高
    TIM_OC2Init(TIM2, &TIM_OCInitStruct);

    // 使能TIM2
    TIM_Cmd(TIM2, ENABLE);
}

需要注意的是,在使用TIM2产生PWM信号时,可能会受到其他因素(例如电源噪声、交错IO干扰等)的影响,导致实际输出信号的占空比和频率有所偏差。此时需要通过实际测试和调试来进行校准和优化,以获得更加精确和稳定的PWM输出信号。

3. 计数周期计算

在STM32F103RCT6时钟位72MHz下,如果要输出一个每秒钟有40,000个脉冲的PWM信号,那么每个脉冲的时间为 (1 / 40,000) s = 25us。

因此,如果使用定时器模块来产生这个PWM信号,需要将定时器的计数周期设置成每个脉冲的时间 25us 的计数值。计算公式如下:

计数周期 = (定时器时钟频率 ÷ PWM频率) - 1

其中,PWM频率为40kHz,定时器时钟频率为72MHz。代入公式可得:

计数周期 = (72,000,000 ÷ 40,000) - 1 = 1799

因为定时器是从0开始计数,所以实际上计数器的计数范围应该是0~1799,一共1800个计数值。因此,将计数周期设置为1800即可生成一个每秒钟有40,000个脉冲的PWM信号。

4. PWM 波用途

4.1 控制电机速度:

PWM信号可以输入到电机驱动器中,由驱动器将其转换成电压或电流,以控制电机的转速和功率输出。
PWM信号可以通过改变电极输出电压的占空比来控制电极。在控制电极输出时,我们通常将PWM信号的占空比定义为:

占空比 = (高电平时间 ÷ PWM周期) × 100%

其中,PWM周期是PWM信号一个完整的周期时间长度,高电平时间表示PWM信号输出高电平的持续时间。

电极在输出电压时,其输出电压与PWM信号高电平时间长短成正比(时间越长,输出电压越大),因此我们可以通过改变PWM信号的占空比来控制电极的输出电压。

4.1.1 例如:

如果PWM周期为10ms,需要让电极输出5V电压,则可以将PWM信号的高电平时间设置为5ms,低电平时间也为5ms,在10ms的周期内完成一次PWM波形输出。因此,该PWM信号的占空比为50%。

具体实现时,我们可以使用MCU的定时器功能来生成指定周期和占空比的PWM信号,驱动电极输出。以使用STM32的定时器功能产生PWM信号为例,代码实现如下:

// 定义占空比为50%
#define DUTY_CYCLE 500

// 配置TIM2为PWM输出模式
void TIM2_PWM_Init(void)
{
    // 定义结构体变量
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_OCInitTypeDef TIM_OCInitStruct;

    // 使能TIM2时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 初始化TIM2
    TIM_TimeBaseInitStruct.TIM_Prescaler = 0;   // 不预分频
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数模式
    TIM_TimeBaseInitStruct.TIM_Period = 1800 - 1;  // 自动重装载值
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  // 时钟分频
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);

    // 配置TIM2为PWM模式,输出通道2
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;  // PWM模式1
    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;  // 使能输出
    TIM_OCInitStruct.TIM_Pulse = DUTY_CYCLE;  // 占空比
    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;  // 输出极性为高
    TIM_OC2Init(TIM2, &TIM_OCInitStruct);

    // 使能TIM2
    TIM_Cmd(TIM2, ENABLE);
}

上述代码中,将定时器TIM2的计数周期设置为1800,可以生成一个40kHz的PWM信号。将PWM信号的输出通道设置为TIM2的通道2,并将占空比设置为50%(DUTY_CYCLE = 500),即可驱动电极输出5V的电压。

需要注意的是,实际输出电压和占空比可能存在一定误差,可以通过实验和调试进行校准和优化。此外,在控制电极输出时,需要注意保护电路和控制电压的稳定性,以免对电子设备和用户造成损伤。

4.2 LED亮度调节:

通过改变LED灯的亮度,可以改变LED的发光强度,实现亮度调节效果。使用PWM信号控制LED的开启时间和关闭时间,即可改变LED的亮度。
LED在输出电流时,其亮度与电流强度成正比,而电流的大小与PWM信号高电平时间长短成正比(时间越长,输出电流越大),因此我们可以通过改变PWM信号的占空比来控制LED的亮度和开启时间。

4.2.1 例如:

如果PWM周期为10ms,需要让LED以50%的亮度输出,则可以将PWM信号的高电平时间设置为5ms,低电平时间也为5ms,在10ms的周期内完成一次PWM波形输出。因此,该PWM信号的占空比为50%。

具体实现时,我们可以使用STM32的定时器功能来生成指定周期和占空比的PWM信号,驱动LED灯的亮度输出。以使用TIM2定时器产生40kHz的PWM信号为例,代码实现如下:

// 定义占空比为50%
#define DUTY_CYCLE 500

// 配置TIM2为PWM输出模式
void TIM2_PWM_Init(void)
{
    // 定义结构体变量
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_OCInitTypeDef TIM_OCInitStruct;

    // 使能TIM2时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 初始化TIM2
    TIM_TimeBaseInitStruct.TIM_Prescaler = 0;   // 不预分频
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数模式
    TIM_TimeBaseInitStruct.TIM_Period = 1800 - 1;  // 自动重装载值
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  // 时钟分频
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);

    // 配置TIM2为PWM模式,输出通道2
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;  // PWM模式1
    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;  // 使能输出
    TIM_OCInitStruct.TIM_Pulse = DUTY_CYCLE;  // 占空比
    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;  // 输出极性为高
    TIM_OC2Init(TIM2, &TIM_OCInitStruct);

    // 使能TIM2
    TIM_Cmd(TIM2, ENABLE);
}

上述代码中,将定时器TIM2的计数周期设置为1800,可以生成一个40kHz的PWM信号。将PWM信号的输出通道设置为TIM2的通道2,并将占空比设置为50%(DUTY_CYCLE = 500),即可驱动LED输出50%的亮度。

需要注意的是,实际输出亮度和占空比可能存在一定误差,可以通过实验和调试进行校准和优化。

4.3 发出特定频率的声音:

PWM信号可以通过扬声器或震动器等装置,发出特定频率的声音或振动信号。这在蜂鸣器、手机震动等场景中都有应用。

PWM信号可以通过改变输出波形的频率和占空比来发出特定频率的声音。在发出声音时,我们通常将PWM信号的频率定义为:

频率 = PWM时钟频率 ÷ (PWM周期 + 1)

其中,PWM时钟频率是MCU定时器的工作时钟频率,PWM周期是PWM信号一个完整的周期时间长度。

不同频率对应的PWM周期不同,这也决定了PWM信号每个周期内的高电平和低电平时间。例如,如果需要发出1000Hz的声音,则根据上述公式可以计算出PWM周期为:

PWM周期 = PWM时钟频率 ÷ 频率 - 1 = 72MHz ÷ 1000Hz - 1 = 71999

4.3.1 例如:

因此,可以使用STM32的定时器功能来生成指定频率和占空比的PWM信号,发出特定频率的声音。以使用TIM2定时器产生1000Hz的PWM信号为例,代码实现如下:

// 驱动蜂鸣器发出1000Hz的声音
void Beep_Init(void)
{
    // 定义结构体变量
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_OCInitTypeDef TIM_OCInitStruct;

    // 使能TIM2时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 初始化TIM2,产生1000Hz的PWM信号
    TIM_TimeBaseInitStruct.TIM_Period = 71999;  // PWM周期,对应1000Hz
    TIM_TimeBaseInitStruct.TIM_Prescaler = 0;  // 不预分频
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  // 时钟分频
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数模式
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);

    // 配置TIM2为PWM模式,输出通道2
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;  // PWM模式1
    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;  // 使能输出
    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;  // 输出极性为高
    TIM_OCInitStruct.TIM_Pulse = 36000;  // 占空比,对应50%
    TIM_OC2Init(TIM2, &TIM_OCInitStruct);

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

上述代码中,将定时器TIM2的计数周期设置为71999,可以生成一个1000Hz的PWM信号。将PWM信号的输出通道设置为TIM2的通道2,并将占空比设置为50%(对应PWM信号的高电平和低电平时间相等),即可驱动蜂鸣器发出特定频率的声音。

需要注意的是,具体实现时需要根据要发出的声音频率来计算出对应的PWM周期和占空比,并进行合理配置和调整。此外,在发出声音时,需要注意保护设备和用户的听觉健康,避免过大的声音对听力造成损伤。

4.4 电压调节:

PWM信号可以输入到电路中,通过控制输出的占空比,来实现对电压的调节。例如在稳压电源中,就可以使用PWM信号来控制输出的电压值。
PWM可以通过控制输出波形的占空比来实现电压调节。在PWM输出时,输出电压与PWM信号高电平时间长短成正比(时间越长,输出电压越大),因此我们可以通过改变PWM信号的占空比来调节输出电压。

4.4.1 例如:

具体实现时,我们可以使用MCU的定时器功能来生成指定周期和占空比的PWM信号,驱动输出电路进行电压调节。以使用STM32的定时器功能产生PWM信号为例,代码实现如下:

// 定义占空比为50%
#define DUTY_CYCLE 500

// 配置TIM2为PWM输出模式
void TIM2_PWM_Init(void)
{
    // 定义结构体变量
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_OCInitTypeDef TIM_OCInitStruct;

    // 使能TIM2时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 初始化TIM2
    TIM_TimeBaseInitStruct.TIM_Prescaler = 0;   // 不预分频
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;  // 向上计数模式
    TIM_TimeBaseInitStruct.TIM_Period = 1800 - 1;  // 自动重装载值
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  // 时钟分频
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);

    // 配置TIM2为PWM模式,输出通道2
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;  // PWM模式1
    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;  // 使能输出
    TIM_OCInitStruct.TIM_Pulse = DUTY_CYCLE;  // 占空比
    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;  // 输出极性为高
    TIM_OC2Init(TIM2, &TIM_OCInitStruct);

    // 使能TIM2
    TIM_Cmd(TIM2, ENABLE);
}

上述代码中,将定时器TIM2的计数周期设置为1800,可以生成一个40kHz的PWM信号。将PWM信号的输出通道设置为TIM2的通道2,并将占空比设置为50%(DUTY_CYCLE = 500),即可通过驱动输出电路进行电压调节。

需要注意的是,实际输出电压和占空比可能存在一定误差,可以通过实验和调试进行校准和优化。此外,在进行电压调节时,需要考虑负载电流和电源稳定性等因素,以避免对电路和器件造成不良影响。

### 使用STM32CubeMX配置STM32F103RCT6定时器 #### 配置环境准备 为了成功配置STM32F103RCT6定时器,在开始之前需确保已安装好STM32CubeMX软件,并下载对应于目标芯片的数据包。 #### 定时器基本设置 打开STM32CubeMX,创建新项目并选择对应的MCU型号即STM32F103RCT6。进入Clock Configuration页面调整系统时钟频率至所需值[^2]。 #### TIM6定时器用于DAC输出 对于使用TIM6配合DAC通道2输出正弦波的情况,首先应在Pinout & Configuration界面找到TIM6定时器,将其模式设为Timer Output Compare。接着设定Prescaler预分频系数以及Period自动重装载周期数值来决定计数频率与溢出间隔。此案例中,这些参数的选择应能使得定时器每达到一次满量程就触发DMA传输下一个样本给DAC模块[^1]。 ```c __HAL_TIM_SET_COUNTER(&htim6, 0); // CNT清零 HAL_TIM_Base_Start(&htim6); // 启动定时器6 ``` 上述代码片段展示了如何初始化和启动TIM6定时器以便它能够按照预定的时间间隔工作。 #### 中断服务程序定义 当涉及到更复杂的操作比如响应特定事件或执行周期性的任务时,则可能需要用到中断机制。可以在工程文件`tim.c`里添加自定义的中断回调函数来进行处理: ```c void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == htim2.Instance) { static int16_t tim_delay; if (++tim_delay >= 500) { // 延迟计算逻辑 tim_delay = 0; HAL_GPIO_TogglePin(LED_1_GPIO_Port, LED_1_Pin); } } if (htim->Instance == htim6.Instance) { static int16_t tim2_delay; if (++tim2_delay >= 200) { tim2_delay = 0; HAL_GPIO_TogglePin(LED_2_GPIO_Port, LED_2_Pin); } } } ``` 这段代码实现了两个不同实例下的延时切换LED状态的功能,同时也说明了如何区分多个定时器共享同一个ISR入口点的方法[^3]。 #### PWM功能实现 如果目的是生成PWM信号,那么可以参照如下做法:在Main Loop部分编写循环改变比较寄存器中的占空比从而形成连续变化的脉宽调制波形[^4]。 ```c while (PluseWidch < 999) { PluseWidch++; __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, PluseWidch); HAL_Delay(1); } while (PluseWidth) { PluseWidth--; __HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, PluseWidth); HAL_Delay(1); } ``` 以上就是关于如何利用STM32CubeMX工具对STM32F103RCT6微控制器上的定时器进行配置的一些指导信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值