1. 程式人生 > >STM32 定時器2 CH1 CH2 PWM輸出 產生呼吸燈效果

STM32 定時器2 CH1 CH2 PWM輸出 產生呼吸燈效果

     PWM一般用來驅動電機(控制速度),控制LED亮度,驅動開關電源電路等等,本例項通過改變PWM佔空比的方式來驅動LED燈,形成呼吸燈的效果。用這種方式來學習STM32 TIM2輸出PWM的配置。

      以STM32F103C8T6為例,從其資料手冊中可以看到,PA0、PA1的複用功能(Default alternate functions)分別是定時器2的CH1和CH2。

    由圖2 TIM2_REMP重對映控制表可以看到,TIM2_CH1_ETR表示,PA0既可以復位為TIM2_CH1,也可以複用為TIM2_ETR功能,我們這裡將PA0當做TIM2_CH1使用。


圖1 TIM2 CH1、CH2引腳

(圖來自資料手冊)

       由圖2可以看到TIM2的CH1、CH2沒有重映像時指向PA0和PA1,所以我們這裡不進行重對映配置,在配置PA0、PA1埠時,配置為複用推輓輸出即可。

圖2 TIM2_REMP重對映控制表

配置步驟

1.    PWM時鐘配置

    l  TIM2時鐘

    l  GPIOA時鐘

2.    初始化TIM2,設定ARR(週期),PSC(主時鐘分頻係數)

3.    設定TIM2_CH1, TIM2_CH2的PWM模式,使能TIM2_CH1和TIM2_CH2輸出。

4.    使能TIM2

Small Tips

  1. 讀取當前計數器計數值,讀取暫存器 [ TIM2->CNT ]的值
  2. 改變定時器輸出PWM佔空比,使用函式[ TIM_SetCompare1(TIM2, DUTY) ; ]

程式碼實現

下列為STM32應用程式碼,已經驗證能夠穩定使用。

timer.c

void TIM2_PWM_Init(u16 arr,u16 psc)
{  
	GPIO_InitTypeDef 		GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  	TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  	        TIM_OCInitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);	 //使能定時器2時鐘
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  	 //使能GPIO外設時鐘
	
 
        //引腳功能配置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; //TIM2_CH1 TIM2_CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;          //複用推輓輸出!!
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
 
        //初始化TIM2
	TIM_TimeBaseStructure.TIM_Period = arr;                     //設定在下一個更新事件裝入活動的自動重灌載暫存器週期的值
	TIM_TimeBaseStructure.TIM_Prescaler =psc;                   //設定用來作為TIMx時鐘頻率除數的預分頻值 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;                //設定時鐘分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);             //根據TIM_TimeBaseInitStruct中指定的引數初始化TIMx的時間基數單位
	
	//初始化TIM2 Channel1、Channel2 PWM模式	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;           //選擇定時器模式:TIM脈衝寬度調製模式2
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;   //輸出極性:TIM輸出比較極性高
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);                    //根據T指定的引數初始化外設TIM2 OC1
	TIM_OC2Init(TIM2, &TIM_OCInitStructure);                    //根據T指定的引數初始化外設TIM2 OC2

	TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);  //使能TIM2在CCR2上的預裝載暫存器
	TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);  //使能TIM2在CCR2上的預裝載暫存器
 
	TIM_Cmd(TIM2, ENABLE);  //使能TIM2
}

timer.h

#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"

void TIM2_PWM_Init(u16 arr,u16 psc);    //arr-定時器週期,psc--定時器時鐘分頻

#endif

main.h (部分) 實現呼吸燈效果,在PA0和PA1外接LED燈

//微控制器標頭檔案
#include "stm32f10x.h"

#include "delay.h"
#include "usart.h"
#include "timer.h"

//C庫
#include <string.h>
int main(void)
{
	unsigned int pulse = 0;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);		//中斷控制器分組設定 
	Delay_Init();						//Systick初始化,用於普通的延時 
	DelayMs(200);	//等待電源穩定
	TIM2_PWM_Init(100,719);					//720分頻,72000_000/720 = 100Khz的計數頻率,計數到100為1KHz
	while(1)
	{		
		pulse = 0;
		for(i = 0; i < 100;i ++)
		{
			pulse += 1;
			TIM_SetCompare1(TIM2, pulse) ;
			TIM_SetCompare2(TIM2, pulse) ;
			DelayMs(50);
		}
		
		for(i = 0; i < 100;i ++)
		{
			pulse -= 1;
			TIM_SetCompare1(TIM2, pulse) ;
			TIM_SetCompare2(TIM2, pulse) ;
			DelayMs(50);
		}
	}

}