打印
[STM32F1]

STM32动态改变PWM占空比

[复制链接]
21882|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
小浣熊|  楼主 | 2015-6-2 22:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32庞大的库函数让初学者摸不到头脑,想要直接操作寄存器也存在一定难度,比如想要动态改变PWM占空比这样一个简单的问题,查找了很多帖子和书籍依旧没有找到答案(可能是因为太简单了吧),最后终于发现这的确很简单,具体操作如下:1.首先要包含头文件#include "stm32f10x_tim.h",因为这里面包含了定时器相关寄存器的定义
2.编写TIMx->CCRx = 800,其中TIMx(x=1~7)是你用的哪一个定时器,CCRx(x=1~4)是定时器的哪一个通道,CCRx就是改变定时器的寄存器,直接改变它的值这样想要编写一个呼吸灯程序就再简单不过了,比如:
//初始化定时器TIM3
static void TIM3_GPIO_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;


  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);


  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_Init(GPIOB, &GPIO_InitStructure);
}


static void TIM3_Mode_Config(void)
{
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;

         
  TIM_TimeBaseStructure.TIM_Period = 999;     //定时周期1000
  TIM_TimeBaseStructure.TIM_Prescaler = 0;           
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;        
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;         
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;        
  TIM_OCInitStructure.TIM_Pulse = CCR1_Val;       //占空比  
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;         
  TIM_OC1Init(TIM3, &TIM_OCInitStructure);             //使能通道1
  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);

  TIM_Cmd(TIM3, ENABLE);              
}


//主函数里这样写
while(1)
                        {               
                                uint32_t i;
                                TIM3->CCR1 -= 100;
                                
                                for(i=0xffffff;i!=0;i--);
                                if(TIM3->CCR1 < 1)
                                        {
                                                for(i=0xffffff;i!=0;i--);
                                                TIM3->CCR1 = 800;
                                        }
                        }
}

这样一个简单的呼吸灯程序就完成了
沙发
airwill| | 2015-6-3 07:58 | 只看该作者
动态改变PWM占空比, 其实改变 CCRx 寄存器的值就可以了, 注意不要超出重装载值.
不过为了不会出现异常的 PWM 波形, 注意要使用更新事件更新寄存器.

使用特权

评论回复
板凳
hjh2008303| | 2015-6-3 09:38 | 只看该作者
在PWM的计时器益处中断里面更新不是更好吗

使用特权

评论回复
地板
hjl2832| | 2015-6-3 10:01 | 只看该作者
库函数里,只接就有这个命令,只是你不会用,没看到?
/**
  * @brief  Sets the TIMx Capture Compare1 Register value
  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
  * @param  Compare1: specifies the Capture Compare1 register new value.
  * @retval None
  */
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)
{
  /* Check the parameters */
  assert_param(IS_TIM_123458_PERIPH(TIMx));
  /* Set the Capture Compare1 Register value */
  TIMx->CCR1 = Compare1;
}

/**
  * @brief  Sets the TIMx Capture Compare2 Register value
  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
  * @param  Compare2: specifies the Capture Compare2 register new value.
  * @retval None
  */
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2)
{
  /* Check the parameters */
  assert_param(IS_TIM_123458_PERIPH(TIMx));
  /* Set the Capture Compare2 Register value */
  TIMx->CCR2 = Compare2;
}

/**
  * @brief  Sets the TIMx Capture Compare3 Register value
  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
  * @param  Compare3: specifies the Capture Compare3 register new value.
  * @retval None
  */
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3)
{
  /* Check the parameters */
  assert_param(IS_TIM_123458_PERIPH(TIMx));
  /* Set the Capture Compare3 Register value */
  TIMx->CCR3 = Compare3;
}

/**
  * @brief  Sets the TIMx Capture Compare4 Register value
  * @param  TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
  * @param  Compare4: specifies the Capture Compare4 register new value.
  * @retval None
  */
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4)
{
  /* Check the parameters */
  assert_param(IS_TIM_123458_PERIPH(TIMx));
  /* Set the Capture Compare4 Register value */
  TIMx->CCR4 = Compare4;
}

使用特权

评论回复
5
小浣熊|  楼主 | 2015-6-5 22:09 | 只看该作者
hjl2832 发表于 2015-6-3 10:01
库函数里,只接就有这个命令,只是你不会用,没看到?
/**
  * @brief  Sets the TIMx Capture Compare1 Re ...

非常感谢。。

使用特权

评论回复
6
戴风海| | 2016-3-11 20:18 | 只看该作者
算是学习啦啦啦

使用特权

评论回复
7
晴天太抢手| | 2016-3-15 16:36 | 只看该作者
airwill 发表于 2015-6-3 07:58
动态改变PWM占空比, 其实改变 CCRx 寄存器的值就可以了, 注意不要超出重装载值.
不过为了不会出现异常的 PW ...

那在修改CCRx值的时候加入delay函数,想实现pwm的间隔输出,为什么delay函数不起作用啊,pwm还是同步的,求解

使用特权

评论回复
8
airwill| | 2016-3-15 18:46 | 只看该作者
晴天太抢手 发表于 2016-3-15 16:36
那在修改CCRx值的时候加入delay函数,想实现pwm的间隔输出,为什么delay函数不起作用啊,pwm还是同步的, ...

我觉得应该是可以实现的, 只是你的 PWM 间隔是关闭波形吗? 那就先CCER 里关闭 PWM 后再 delay

使用特权

评论回复
9
晴天太抢手| | 2016-3-15 18:50 | 只看该作者
airwill 发表于 2016-3-15 18:46
我觉得应该是可以实现的, 只是你的 PWM 间隔是关闭波形吗? 那就先CCER 里关闭 PWM 后再 delay ...

额。。。还真有点不太清楚呢 方不方便加个扣扣请教下 谢谢!

使用特权

评论回复
10
沙尘幽客| | 2016-12-21 18:50 | 只看该作者
++++++++++++++++++++++++++++

使用特权

评论回复
11
zunaxia| | 2017-8-6 10:14 | 只看该作者
#include "pwm_out.h"



/*******************************************************************************
* 函 数 名         : pwm_init
* 函数功能                   : IO端口及TIM3初始化函数          
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Pwm_tim3_init(u16 CCR1_Val_12,u16 CCR1_Val_34)
{
        GPIO_InitTypeDef GPIO_InitStructure;   //声明一个结构体变量,用来初始化GPIO
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//声明一个结构体变量,用来初始化定时器
        TIM_OCInitTypeDef TIM_OCInitStructure;//根据TIM_OCInitStruct中指定的参数初始化外设TIMx

        /* 开启时钟 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

        /*  配置GPIO的模式和IO口 */
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
        GPIO_Init(GPIOC,&GPIO_InitStructure);


        //TIM4定时器初始化
        TIM_TimeBaseInitStructure.TIM_Period = 900;           //不分频,PWM 频率=72000/900=8Khz//设置自动重装载寄存器周期的值
        TIM_TimeBaseInitStructure.TIM_Prescaler = 0;//设置用来作为TIMx时钟频率预分频值,100Khz计数频率
        TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;//设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;        //TIM向上计数模式
        TIM_TimeBaseInit(TIM3, & TIM_TimeBaseInitStructure);

        GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);//改变指定管脚的映射        //PC6,7,8,9
        /*************************** 通道1 ********************************/
        //PWM初始化          //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
        TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能

        TIM_OCInitStructure.TIM_Pulse = CCR1_Val_34;
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;

        TIM_OC1Init(TIM3,&TIM_OCInitStructure);
        TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
        //注意此处初始化时TIM_OC2Init而不是TIM_OCInit,否则会出错。因为固件库的版本不一样。
        /*************************** 通道2 ********************************/
        TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能

        TIM_OCInitStructure.TIM_Pulse = CCR1_Val_34;
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;

        TIM_OC2Init(TIM3,&TIM_OCInitStructure);
        TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
        /*************************** 通道3 ********************************/
                TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能

        TIM_OCInitStructure.TIM_Pulse = CCR1_Val_34;
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;

        TIM_OC3Init(TIM3,&TIM_OCInitStructure);
        TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
        /*************************** 通道4 ********************************/
                TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能

        TIM_OCInitStructure.TIM_Pulse = CCR1_Val_34;
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;

        TIM_OC4Init(TIM3,&TIM_OCInitStructure);

        TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能或者失能TIMx在CCR2上的预装载寄存器
       
        TIM_Cmd(TIM3,ENABLE);//使能或者失能TIMx外设
}
/*******************************************************************************
* 函 数 名         : pwm_init
* 函数功能                   : IO端口及TIM初始化函数          
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Pwm_tim4_init(u16 CCR1_Val_12,u16 CCR1_Val_34)
{
        GPIO_InitTypeDef GPIO_InitStructure;   //声明一个结构体变量,用来初始化GPIO

        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//声明一个结构体变量,用来初始化定时器

        TIM_OCInitTypeDef TIM_OCInitStructure;//根据TIM_OCInitStruct中指定的参数初始化外设TIMx

        /* 开启时钟 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

        /*  配置GPIO的模式和IO口 */
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
        GPIO_Init(GPIOD,&GPIO_InitStructure);


        //TIM4定时器初始化
        TIM_TimeBaseInitStructure.TIM_Period = 900;           //不分频,PWM 频率=72000/900=8Khz//设置自动重装载寄存器周期的值
        TIM_TimeBaseInitStructure.TIM_Prescaler = 0;//设置用来作为TIMx时钟频率预分频值,100Khz计数频率
        TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;//设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;        //TIM向上计数模式
        TIM_TimeBaseInit(TIM4, & TIM_TimeBaseInitStructure);

        GPIO_PinRemapConfig(GPIO_Remap_TIM4,ENABLE);//改变指定管脚的映射        //PD2,13,14,15
        /*************************** 通道1 ********************************/
        //PWM初始化          //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
        TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能

        TIM_OCInitStructure.TIM_Pulse = CCR1_Val_12;
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;

        TIM_OC1Init(TIM4,&TIM_OCInitStructure);
        TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);
        //注意此处初始化时TIM_OC2Init而不是TIM_OCInit,否则会出错。因为固件库的版本不一样。
        /*************************** 通道2 ********************************/
                TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能

        TIM_OCInitStructure.TIM_Pulse = CCR1_Val_12;
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;

        TIM_OC2Init(TIM4,&TIM_OCInitStructure);
        TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
        /*************************** 通道3 ********************************/
                TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能

        TIM_OCInitStructure.TIM_Pulse = CCR1_Val_34;
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;

        TIM_OC3Init(TIM4,&TIM_OCInitStructure);
        TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);
        /*************************** 通道4 ********************************/
                TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能

        TIM_OCInitStructure.TIM_Pulse = CCR1_Val_34;
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;

        TIM_OC4Init(TIM4,&TIM_OCInitStructure);

        TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);//使能或者失能TIMx在CCR2上的预装载寄存器
       
        TIM_Cmd(TIM4,ENABLE);//使能或者失能TIMx外设
}
我这个为啥没有波输出来

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

528

主题

2095

帖子

8

粉丝