OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8399|回复: 8

转载《STM32F103ZET6 用定时器级联方式输出特定数目的PWM》

[复制链接]

10

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2013-10-20
在线时间
0 小时
发表于 2013-10-21 15:37:18 | 显示全部楼层 |阅读模式
 
STM32F103ZET6里共有8个定时器,其中高级定时器有TIM1-TIM5、TIM8,共6个。

这里需要使用定时器的级联功能,ST的RM0008 REV12的P388和P399页上有说明对于特定的定时器,怎么去选择级联功能,参见表86。

我这里输出PWM的定时器是TIM2,空闲的定时器是TIM3。以TIM2为主定时器,TIM3为从定时器对TIM2的输出脉冲数进行计数。查表可知,TIM3为从定时器选择TIM2为触发源,需要配置TS=001,即选择ITR1。

实现通过定时器控制输出PWM个数的功能,可以有如下一种配置方式:




void TIM2_Master__TIM3_Slave_Configuration(u32 PulseFrequency)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef       TIM_OCInitStructure;

    u16 nPDTemp ;
    /* -----------------------------------------------------------------------
    TIMx Configuration: generate 4 PWM signals with 4 different duty cycles:
    TIMxCLK = 72 MHz, Prescaler = 0x0, TIMx counter clock = 72 MHz
    TIMx ARR Register = 0 => TIMx Frequency = TIMx counter clock/(ARR + 1)
    TIMx Frequency = 72MHz.
    ----------------------------------------------------------------------- */
    TIM_Cmd(TIM2, DISABLE);
    nPDTemp = 72000000UL/PulseFrequency;   

// 时基配置:配置PWM输出定时器——TIM2
    /* Time base configuration */
    TIM_TimeBaseStructure.TIM_Period          = nPDTemp-1;
    TIM_TimeBaseStructure.TIM_Prescaler       = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision   = 0;
    TIM_TimeBaseStructure.TIM_CounterMode     = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

   
// 输出配置:配置PWM输出定时器——TIM2
    /* PWM1 Mode configuration: Channel1 */
    TIM_OCInitStructure.TIM_OCMode            = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OCPolarity        = TIM_OCPolarity_High;   
    TIM_OCInitStructure.TIM_OutputState       = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse             = nPDTemp>>1;//50%

    TIM_OC1Init(TIM2, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
   
// 时基配置:配置脉冲计数寄存器——TIM3
    TIM_TimeBaseStructure.TIM_Period        = 0xFFFF;
    TIM_TimeBaseStructure.TIM_Prescaler     = 1;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode   = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);   
   
    /* Output Compare Active Mode configuration: Channel1 */
    TIM_OCInitStructure.TIM_OCMode                        = TIM_OCMode_Inactive;
    TIM_OCInitStructure.TIM_OCPolarity                = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OutputState                = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse                        = 0xFFFF;                                        // 这里的配置值意义不大
   
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);
   
// 配置TIM2为主定时器
    /* Select the Master Slave Mode */
    TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);
    /* Master Mode selection */
    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
   
// 配置TIM3为从定时器
    /* Slave Mode selection: TIM3 */
    TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated);
    TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1);
   
    TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
   
    TIM_Cmd(TIM2, DISABLE);
    TIM_Cmd(TIM3, DISABLE);
}

中断服务程序如下:


u8  TIM2_Pulse_TIM3_Counter_OK = 0;
void TIM3_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);    // 清除中断标志位
        
        TIM_Cmd(TIM2, DISABLE); // 关闭定时器
        TIM_Cmd(TIM3, DISABLE); // 关闭定时器
        
        TIM2_Pulse_TIM3_Counter_OK = 1;
    }
}

应用程序为:

u16 pulsecnt = 10000;
void main(void)
{
    SystemSetup();        // 初始化内核和外设
    TIM2_Master__TIM3_Slave_Configuration(10000);//配置TIM2的脉冲输出为10k
    while(1)
    {
        TIM_ITConfig(TIM3, TIM_IT_CC1, DISABLE);        /* TIM enable counter */
        TIM_Cmd(TIM3, ENABLE);
        TIM3->CCR1  = pulsecnt;
        TIM3->CNT   = 0;
        TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
        TIM_Cmd(TIM2, ENABLE);                                                /* TIM enable counter */
        
        while(TIM2_Pulse_TIM3_Counter_OK  == 0);
    }
}


这种配置方式下,使用的是TIM3的比较中断,我还没试验过其他的方式,想来应该也是可以的,比如用定时器更新中断……
以上是转载论坛的某位网友之作,找不到原作者,所以在这里请原子大大看下,为啥我下到自己板子上输出的是达到MHZ级别杂波,没有PWM输出,大家可以尝试下,互相讨论学习,谢谢
求学不怕苦才能坚持到彼岸
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-10-21 22:00:53 | 显示全部楼层
这是我以前弄的方法,定时器2用单脉冲模式,去控制定时器1,输出指定脉冲个数的PWM。定时器1采用门控模式,被定时器2控制。

//TIM2单脉冲模式
void TIM2_Init_One_Pause(u16 arr,u16 psc)
{
//此部分需手动修改IO口设置
RCC->APB1ENR|=1<<0;       //TIM2时钟使能 

TIM2->ARR=arr;//设定计数器自动重装值 
TIM2->SC=psc;//预分频器不分频

TIM2->CR2|=4<<4;    //OC1REF用于TRGO  

TIM2->CCMR1|=7<<4;  //CH1 WM2模式  
TIM2->CCMR1|=1<<3;  //CH1预装载使能    

TIM2->CCER|=1<<0;   //OC1 输出使能    

TIM2->CR1=0x0080;   //ARPE使能 
TIM2->CR1|=0x09;    //使能定时器3 
}

//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM1_SLAVE_PWM_Init(u16 arr,u16 psc)
{    
//此部分需手动修改IO口设置
RCC->APB2ENR|=1<<11;   //TIM1时钟使能 
RCC->APB2ENR|=1<<3;    //使能PORTB时钟
     
  RCC->APB2ENR|=1<<0;    //开启辅助时钟
JTAG_Set(SWD_ENABLE);  //开启SWD

GPIOB->CRH&=0X0FFFFFFF;//PB15输出
GPIOB->CRH|=0XB0000000;//复用功能输出    
GPIOB->ODR|=1<<15;     //PB15上拉   

TIM1->ARR=arr;         //设定计数器自动重装值 
TIM1->CCR3=arr/2;    // 50%的方波
TIM1->SC=psc;         //预分频器不分频

TIM1->CCMR2|=7<<4;   //CH3 WM2模式  
TIM1->CCMR2|=1<<3;   //CH3预装载使能    

TIM1->CCER|=1<<10;   //OC3N 输出使能  
TIM1->BDTR|=1<<15;   //MOE使能.
//TIM1->BDTR|=1<<11;   //OSSR使能.

TIM1->SMCR|=5<<0;    //TIM1门控模式
TIM1->SMCR|=0X01<<4; //TIM1内部触发TIM1

TIM1->CR1|=0x0080;   //ARPE使能 
TIM1->CR1|=0x01;     //使能定时器3          
}

int main(void)
{
  u16 led0pwmval=450;
u8 dir=1;
  Stm32_Clock_Init(9); //系统时钟设置
delay_init(72);      //延时初始化
uart_init(72,9600);  //串口初始化 
LED_Init();     //初始化与LED连接的硬件接口

TIM2_Init_One_Pause(14400,1600);//12MHz  
    TIM1_SLAVE_PWM_Init(400,36);  //5Khz的频率
TIM2->CCR1=7200;

while(1)
{
if((TIM2->CR1&0x01)==0)
{
printf("A AUSE Will GEN!\n");
delay_ms(1);
TIM1->CNT=0;        
  TIM2->CR1|=0x01;   
}

// if(dir)led0pwmval++;
// else led0pwmval--;
//
//  if(led0pwmval>300)dir=0;
// if(led0pwmval==0)dir=1;
//  
// LED0_PWM_VAL=led0pwmval;    
}  
}
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 1 反对 0

使用道具 举报

10

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2013-10-20
在线时间
0 小时
 楼主| 发表于 2013-10-21 15:39:11 | 显示全部楼层
还有就是主函数一直死在 while(TIM2_Pulse_TIM3_Counter_OK  == 0);
求学不怕苦才能坚持到彼岸
回复 支持 反对

使用道具 举报

32

主题

72

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
227
金钱
227
注册时间
2013-10-16
在线时间
1 小时
发表于 2013-10-21 17:24:15 | 显示全部楼层
有没有控制寄存器的亲
回复 支持 反对

使用道具 举报

10

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2013-10-20
在线时间
0 小时
 楼主| 发表于 2013-10-21 17:27:14 | 显示全部楼层
回复【3楼】higerd_han:
---------------------------------
木有,我是从库函数开始学的,亲~估计大大们看到库函数就直接忽略我这帖子了哈~
下面是我自己建的工程文件,把他的TIM2用TIM4替换了。

STM32F103ZET6 用定时器级联方式输出特定数目的PWM.rar

5.7 MB, 下载次数: 542

求学不怕苦才能坚持到彼岸
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-10-21 21:55:04 | 显示全部楼层
帮顶下,这个模式我也没搞过。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

10

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2013-10-20
在线时间
0 小时
 楼主| 发表于 2013-10-21 21:58:25 | 显示全部楼层
回复【5楼】正点原子:
---------------------------------
呵呵,原作者联系不上,所以弄来求大神多解答下啦,多谢原子大大支持~
求学不怕苦才能坚持到彼岸
回复 支持 反对

使用道具 举报

10

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
127
金钱
127
注册时间
2013-10-20
在线时间
0 小时
 楼主| 发表于 2013-10-21 23:13:13 | 显示全部楼层
回复【7楼】正点原子:
---------------------------------
1、原文我奇怪管脚和定时器时钟都没有开,我测了输出是没信号的(有的也是杂波),不知道原作者怎么想的,程序仿真一直死在while(TIM2_Pulse_TIM3_Counter_OK  == 0);中
2、这么晚了,原子大大还这么辛勤回复,赞一个。你给的例子下了好好学习下,多谢!
求学不怕苦才能坚持到彼岸
回复 支持 反对

使用道具 举报

2

主题

5

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2014-7-19
在线时间
0 小时
发表于 2014-7-19 16:27:04 | 显示全部楼层
回复【4楼】爱在暖晴天:
---------------------------------楼主上传上来的程序我下载看了,定时器都没有时钟使能,难道这样也可以?小弟刚刚接触有很多不懂的地方,还请楼主跟各位大哥指点迷津
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-5 02:12

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表