STM32F103RCT6 -- 定时器TIM2 输出 PWM 波形
由于要输出40kHz的PWM信号,因此可以将计数器的周期设置为1800(即72MHz/40kHz),以便每个PWM周期的持续时间是1/40kHz=25us。需要注意的是,在使用TIM2产生PWM信号时,可能会受到其他因素(例如电源噪声、交错IO干扰等)的影响,导致实际输出信号的占空比和频率有所偏差。然后,需要计算占空比。在STM32F103RCT6时钟位72MHz下,如果要输出一个每秒钟有40,0
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),即可通过驱动输出电路进行电压调节。
需要注意的是,实际输出电压和占空比可能存在一定误差,可以通过实验和调试进行校准和优化。此外,在进行电压调节时,需要考虑负载电流和电源稳定性等因素,以避免对电路和器件造成不良影响。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)