STM32F4 TIM(外設定時器)


TIM概述

  外設定時器除了和系統定時器一樣具有基本定時功能外,還具有PWM(Pulse width modulation)輸出的功能,stm32f4的外設定時器非常多,一 共有14個,分為2個高級控制定時器、10 個通用定時器 和 2 個基本定時器:
    1.高級控制定時器(TIM1和TIM8),掛載到APB2:具有16位定時器功能,具有4通道、輸入捕獲、PWM輸出高級控制功能;
    2.通用定時器(TIM2到TIM5),掛載到APB1:具有16或32位定時功能,具有4通道、輸入捕獲、PWM輸出控制功能;
      通用定時器(TIM9到TIM14),掛載到AP1或APB2:具有16位定時功能,具有2通道、輸入捕獲、PWM輸出控制功能;
    3.基本定時器(TIM6和TIM7),掛載到APB1:具有16位定時功能。

定時計算

  對於TIM的外設定時器的時鍾頻率,需要注意參考手冊RCC章節中如下兩句話

STM32F405xx/07xx 和 STM32F415xx/17xx 的定時器時鍾頻率由硬件自動設置。分為兩種
情況:
1. 如果APB預分頻器為1,定時器時鍾頻率等於APB域的頻率。
2. 否則,等於APB域的頻率的兩倍 (×2)。

  而在函數SetSysClock中可以看到,APB1=1/4 x AHB,APB2=1/2 x AHB,也就是掛載在APB下的TIM,其時鍾頻率為對應的APB時鍾頻率的兩倍,而外設TIM也不會對所得到時鍾頻率進行再次分頻才使用,而是直接使用。但是在使用PWM輸出/比較或定時功能時需要使用預分頻器對其分頻,從TIM的框圖中可以看出:

實驗程序1

  通過原理圖發現LED4的引腳連接了TIM14的通道1,便可以通過TIM14通道1實現呼吸燈。
led.c

#include "stm32f4xx.h"
#include "common.h"
#include "led.h"

void breathinglight_init()
{
        GPIO_InitTypeDef 	GPIO_InitStructure ;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;        
	//初始化對應端口的引腳 
	GPIO_InitStructure.GPIO_Pin  = LED_PIN_4;//指定第9根引腳 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF ;//配置為復用模式
	GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz ;//配置引腳的響應時間=1/50MHz 
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP ;//推挽的輸出模式,增加輸出電流和灌電流的能力
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL ;//不使能內部上下拉電阻
	GPIO_Init(LED_PORT2,&GPIO_InitStructure);
	
	//將LED4的引腳連接到TIM14
	GPIO_PinAFConfig(LED_PORT2, LED4_PinSource, GPIO_AF_TIM14);

	//配置TIM14的相關參數:計數值(決定定時時間)、分頻值
	//TIM14的硬件時鍾頻率=AHBCLK/4*2=APB1CLK*2=84000000Hz
        //設置預分頻器為8400:84000000/8400
	//只要進行10000次計數,就是1秒時間的到達,也就是1Hz的頻率輸出
	TIM_TimeBaseStructure.TIM_Period = 10000/200-1;//如:計數值10000/100-1,決定了輸出頻率為100Hz,計數值為10000/50-1,頻率為50Hz
	TIM_TimeBaseStructure.TIM_Prescaler = 8400-1;//預分頻,也就是第一次分頻,當前8400分頻,就是84MHz/8400
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;//時鍾分頻,也稱之二次分頻這個F407是不支持的,因此該參數是不會生效的
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//就是從0開始計數,然后計數到TIM_Period
	TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);
	
	//占空比的配置
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//工作在PWM1模式,當計時器值小於比較器設定值時則輸出腳此時輸出有效電位。
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//脈沖的輸出開關,當前是輸出脈沖
	TIM_OCInitStructure.TIM_Pulse = 25;//這個值是決定了占空比,配置比較值,現在的輸出占空比為50%
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//有效電平為高電平

	//TIM14的通道1配置
	TIM_OC1Init(TIM14, &TIM_OCInitStructure);
	//使能定時器14工作
	TIM_Cmd(TIM14, ENABLE);
}

led_test.c

#include "led_test.h"
#include "sys_tick.h"

void breathinglight_test()
{
	uint32_t pwm = 50;
	uint32_t flag = 0;
        while(1)
	{
		//設置TIM14的通道1比較值為20,亮度高
		if (0 == flag)
		{
			TIM_SetCompare1(TIM14, pwm);//設置TIM14通道1的比較值
			pwm  = pwm  - 1;
			if (pwm <= 0)
			{
				flag = 1;
			}
		}
		delay_ms(50);
		if (1 == flag)
		{
			TIM_SetCompare1(TIM14,l);
			pwm = pwm  + 1;
			if (pwm >= 50)
			{	
				flag = 0;
			}
		}
	}
}

main.c

#include "hwconf.h"
#include "led.h"
#include "led_test.h"

int main()
{
    init_board(); //初始化相關時鍾
    breathinglight_init();
    breathinglight_test();
}

實驗程序2

  使用TIM3的定時器中斷功能實現LED4閃爍。
tim.c

#include "stm32f4xx.h"
#include "tim.h"

void tim3_init()
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStruct;
	NVIC_InitTypeDef 	NVIC_InitStruct;

	TIM_TimeBaseStruct.TIM_Period = 10000/2-1;//計數值5000-1,決定了定時時間500ms,即頻率為2Hz
	TIM_TimeBaseStruct.TIM_Prescaler = 8400-1;//預分頻,也就是第一次分頻,當前8400分頻,就是84MHz/8400
	TIM_TimeBaseStruct.TIM_ClockDivision = 0;
	TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct);
	
	//配置TIM3的中斷觸發方式:時間更新中斷
	TIM_ITConfig(TIM3,TIM_IT_Update , ENABLE);

	//配置TIM3的優先級
	NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);
	
	//使能定時器3工作
	TIM_Cmd(TIM3, ENABLE);
}

main.c

#include "hwconf.h"
#include "common.h"
#include "led.h"
#include "tim.h"

void main()
{
    init_board();//初始化相關時鍾
    led4_init();//初始化LED4
    tim3_init();
}

void TIM3_IRQHandler(void)
{
	//檢測是否超時時間到達
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
	{
		FLASH_LED4;
		//清空標志位,告訴CPU當前數據接收完畢,可以響應新的中斷請求
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
	}
}

  以上的程序都是基於作者本人之前工程模板,和文件進行編寫的,有需要可以參考我之前的stm32相關隨筆。

總結

  1.注意區分不同類型的TIM;
  2.TIM的輸出頻率計數有些復雜,需要謹慎計算;
  3.注意PWM占空比的計算:假設高電平有效,比較器值/(計數器值+1)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM