STM32F103单片机输出相位可调PWM波

    STM32定时器功能如下

通常使用的是PWM模式,可以通过PWM功能可以生成频率和占空比可调的方波信号,有时候需要生成初始相位可调的方波,PWM功能就就不能满足要求了。可以通过输出比较模式来实现。

输出比较模式是将计数器CNT的值和捕获比较寄存器CCR的对比,当CNT值等于CCR的值时,翻转输出电平。

通过捕获比较寄存器CCMR模式设置位的描述可以看出,输出比较模式只有当 CCR = CNT时,输出电平才会翻转。而PWM模式下 CNT < CCR 时输出一个电平,CNT > CCR时输出相反的电平。

通过一个示意图来看看PWM输出模式

上图中是PWM输出的示意图,可以看出CNT的值从变化范围是 0---ARR,之间,CNT的值在CCR值左边时输出一个电平,CNT值在CCR右边时,输出相反电平。这样改变CCR值就可以改变输出PWM的占空比。

下面在看看输出比较模式

输出比较模式下不关心CNT比 CCR值大还是小,只关心CNT和CCR值什么时候相等,两个值相等时,就翻转输出电平。在PWM模式下,CNT值从0增加到ARR一个周期内输出电平有两次变化,而在输出比较模式下时CNT值从0增加到ARR一个周期内输出电平只有一次变化。所以输出比较模式下,定时器输出方波的频率为PWM模式下定时器输出方波频率的一半。

下面就看看代码如何实现

// arr 自动装载值  psc 分频系数
void TIM3_CMP_Init( u16 arr, u16 psc )
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

    RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );	//使能定时器3时钟  36M 
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB , ENABLE );	//使能GPIOC时钟

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    //初始化TIM3
    TIM_TimeBaseInitStructure.TIM_Period = arr;
    TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit( TIM3, &TIM_TimeBaseInitStructure );

    //初始化TIM3 比较 模式  输出比较翻转触发模式(当计数值与比较/捕获寄存器值相同时,翻转输出引脚的电平)   
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    TIM_OC1Init( TIM3, &TIM_OCInitStructure );
    TIM_OC2Init( TIM3, &TIM_OCInitStructure );
    TIM_OC3Init( TIM3, &TIM_OCInitStructure );
    TIM_OC4Init( TIM3, &TIM_OCInitStructure );

    TIM_OC1PreloadConfig( TIM3, TIM_OCPreload_Enable );
    TIM_OC2PreloadConfig( TIM3, TIM_OCPreload_Enable );
    TIM_OC3PreloadConfig( TIM3, TIM_OCPreload_Enable );
    TIM_OC4PreloadConfig( TIM3, TIM_OCPreload_Enable );

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

这里用的是定时器3,定时器3的4个通道全部设置为输出比较模式。

定时器初始化代码,输出比较模式设置方法和PWM模式设置方法只有模式设置这一行代码不同。

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;

将输出模式由TIM_OCMode_PWM1 改为  TIM_OCMode_Toggle 就可以了。

下面看主函数代码

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "pwm.h"
// LED0  PA8  LED1 PD2
int main( void )
{
    u16 led_pwm_val = 0;
    u8 dir = 1;
    delay_init();       //延时函数初始化
    NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2 );
    LED_Init();

    LED0 = 1;
    LED1 = 1;
    delay_ms( 500 );
    LED0 = 0;
    LED1 = 0;
    //比较输出模式下:  ARR 决定输出频率  CCRx 决定每个通道的初始相位
    //PWM模式:		   ARR 决定输出频率  CCRx 决定输出 的高电平时长

    //比较翻转模式,一个周期只翻转一次,所以频率为 1/2
    TIM3_CMP_Init( 1000 - 1, 36 - 1 );			//1K
    TIM_SetCompare1( TIM3, 0 );
    TIM_SetCompare2( TIM3, 200 );
    TIM_SetCompare3( TIM3, 400 );
    TIM_SetCompare4( TIM3, 600 );
    while( 1 )
    {
        delay_ms( 200 );
        LED0 = !LED0;
    }
}

        定时器3时钟为72MHz,36分频后为2MHz,自动装载值为1000-1,输出频率为 2M / 1000 = 2KHz。输出比较模式的频率要在减一半,所以输出方波信号频率为 2K / 2 = 1KHz.

        下来分别设置4个通道输出的初始相位,通道1相位设置为0,通道2延迟1/5周期,通道3延迟2/5周期,通道4延迟3/5周期。

4个通道的输出频率都是1KHz,周期为1000us。

通过输出波形可以看出来,起始相位依次滞后,通道1为0起点的话,通道2滞后100us,通道3滞后200us,通道4滞后300us。

上面计算的通道2滞后1/5周期,周期为1000us,1/5周期应该为200us,实际测出来为100us,说明相位计算的理论值也要减半。

这样利用定时器输出比较模式,通过设置改变定时器CCR寄存器的值,就可以控制输出方波的起始相位了。

  • 23
    点赞
  • 192
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
### 回答1: 要在STM32F103C8T6单片机输出PWM,可以按照以下步骤进行操作: 1. 配置GPIO为复用功能,并设置对应的复用功能映射 2. 配置定时器,设置PWM模式,并计算出预分频器和计数器的值,使得定时器的时钟频率为所需的PWM频率 3. 配置定时器的通道,使其输出PWM形,设置占空比和极性等参数 以下是一个简单的代码示例,演示如何在STM32F103C8T6单片机输出PWM: ```c #include "stm32f10x.h" // 定义所需的PWM频率和占空比 #define PWM_FREQUENCY 1000 // 1kHz #define PWM_DUTY_CYCLE 50 // 50% int main(void) { // 初始化系统时钟 SystemInit(); // 打开GPIOB和TIM3的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 配置GPIOB.0为复用功能 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // 配置TIM3为PWM模式 TIM_TimeBaseInitTypeDef TIM_InitStructure; TIM_InitStructure.TIM_Period = (SystemCoreClock / PWM_FREQUENCY) - 1; TIM_InitStructure.TIM_Prescaler = 0; TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_InitStructure); // 配置TIM3通道1为PWM输出 TIM_OCInitTypeDef TIM_OC_InitStructure; TIM_OC_InitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OC_InitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OC_InitStructure.TIM_Pulse = ((SystemCoreClock / PWM_FREQUENCY) * PWM_DUTY_CYCLE / 100) - 1; TIM_OC_InitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM3, &TIM_OC_InitStructure); // 启动TIM3计数器 TIM_Cmd(TIM3, ENABLE); // 程序循环 while (1) { // do something } } ``` 以上代码示例中,我们使用GPIOB.0作为PWM输出口,以1kHz的频率输出50%的占空比PWM形。你可以根据具体的需要,修改代码中的频率和占空比参数。 ### 回答2: STM32F103C8T6单片机是一款功能强大的ARM Cortex-M3内核的微控制器,可以实现PWM输出。 首先,我们需要在单片机上配置相应的引脚作为PWM输出引脚。通常,该单片机的引脚具有多种功能,包括GPIO(通用输入输出),AF(复用功能),TIM(定时器功能)等。在这个例子中,我们将选择一个TIM定时器引脚作为PWM输出引脚。 其次,我们需要初始化定时器来生成PWM。首先,我们需要选取一个可用的定时器,然后设置预分频器和周期来确定PWM的频率。预分频器决定了定时器时钟的频率,周期则决定了PWM的频率。另外,我们还需要设置占空比,以控制PWM的高电平时间。占空比可以通过设置定时器的比较寄存器来实现。 最后,我们需要启动定时器,并根据需要设置输出引脚的极性。如果需要反向输出PWM(即高电平变为低电平),我们可以设置输出比较模式为反向输出。否则,我们可以选择正常输出模式。 简而言之,要在STM32F103C8T6单片机上实现PWM输出,我们需要选择一个合适的引脚作为PWM输出引脚,初始化定时器来生成PWM,并设置输出引脚的极性。通过适当地配置预分频器、周期和占空比,我们可以控制PWM的频率和高电平时间。 ### 回答3: STM32F103C8T6是一款基于ARM Cortex-M3内核的高性能微控制单元。要实现该单片机输出PWM,步骤如下: 1. 配置GPIO引脚:选择一个合适的引脚作为PWM输出引脚,并将其对应的GPIO引脚设置为复用模式。 2. 配置定时器:选择一个合适的定时器,配置其工作模式和时钟源,并设置PWM模式。 3. 配置定时器输出比较通道:选择一个合适的比较通道,并设置比较值和输出模式。 4. 设置PWM占空比:通过改变比较值来调整PWM占空比。 5. 启动定时器:使能定时器和比较通道的输出。 具体的代码实现如下: #include "stm32f10x.h" void PWM_Configuration() { // Step 1: 配置GPIO引脚 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // 选择引脚为GPIO_Pin_0 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 引脚速度为50MHz GPIO_Init(GPIOA, &GPIO_InitStructure); // GPIOA为所选引脚所在的GPIO // Step 2: 配置定时器 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能TIM2时钟 TIM_TimeBaseStructure.TIM_Period = 999; // 设置定时器周期为1000-1 TIM_TimeBaseStructure.TIM_Prescaler = 71; // 设置预分频器为7200-1 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; // 时钟分频为1 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // Step 3: 配置定时器输出比较通道 TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // 设置为PWM模式1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 允许输出 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 输出极性为高 TIM_OC1Init(TIM2, &TIM_OCInitStructure); // 比较通道1 // Step 4: 设置PWM占空比 TIM_SetCompare1(TIM2, 500); // 设置通道1的比较值为500 // Step 5: 启动定时器 TIM_Cmd(TIM2, ENABLE); } int main() { PWM_Configuration(); while(1) { // 无需其他操作,单片机会一直输出PWM形 } } 以上就是使用STM32F103C8T6单片机输出PWM的步骤和代码实现。通过配置GPIO引脚、定时器和比较通道,再调整比较值来设置PWM占空比,最后启动定时器即可实现输出PWM形。
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值