STM32小白入门(第七天)-------定时器

今天的定时器也是我们常用的一个32外设,PWM更不用说,电机的转速调节,家里的电灯亮度调节基本上用到的就是通过PWM。

一、定时器
1.定义
设置等待时间,到达后则执行指定操作的硬件。

2.STM32F407的定时器有以下特征
   具有基本的定时功能,也有PWM输出(灯光亮度控制、电机的转速)、脉冲捕获功能(红外捕捉)。

 2个高级控制定时器、10个通用定时器和2个基本定时器

a.高级控制定时器(TIM1和TIM8)

   具有16位定时器功能,也具有PWM输出高级控制功能,一个定时器支持多路的PWM输出。

b.通用定时器(TIM2到TIM5)

   具有16位定时功能,也具有PWM输出控制功能,一个定时器支持1路的PWM输出。

c.通用定时器(TIM9到TIM14)

  具有16位定时功能,也具有PWM输出控制功能,一个定时器支持1路的PWM输出。

d.基本定时器(TIM6和TIM7)
  具有16位定时功能

注:TIM是TIMER英文的缩写。

二、定时器初始化
1.选择时钟源,并初始化定时器分频值与定时时间

/* TIM3 clock enable ,定时器3时钟使能*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

/* Time base configuration ,定时器基本配置*/
TIM_TimeBaseStructure.TIM_Period = (10000/1000)-1;	        //定时时间的设置[非常重要],中断频率为1000Hz,也就是定时时间为1ms
TIM_TimeBaseStructure.TIM_Prescaler = 8400-1;                   //预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;         //时钟分频,也称之为二次分频,当前是1分频,说白了不分频,不降低频率
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;	//向上计数的方法
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);			//初始化

STM32小白入门(第七天)-------定时器_第1张图片

2. 中断的配置

/* TIM Interrupts enable,使能定时器3更新中断事件,也代表说定时已经到达的事件 */

TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);

/* TIM3 enable counter,使能定时器3工作 */

TIM_Cmd(TIM3, ENABLE);

3. 中断服务函数的编写

void TIM3_IRQHandler(void)
{
    static uint32_t cnt=0;

    //是否已经有更新中断事件
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)
    {
        //添加用户代码
        cnt++;
        if(cnt>=500)
        {
            cnt =0;
            PFout(9)^=1;
        }
    //清空标志位,告诉CPU我已经完成中断处理
    TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}

三、PWM概述

1、定义
PWM(Pulse Width Modulation),脉冲宽度调制。
脉冲:方波,频率(freq)
宽度:高电平的宽度,占空比(duty)

详细波形如下图。
STM32小白入门(第七天)-------定时器_第2张图片
2、用途
控制灯光的亮度(手机/平板/显示器背光灯)
电机的转速
....
3、灯光的控制细节

频率要大于25Hz,灯光的亮度的变化是跟着占空比而变化,占空比越大,灯光越暗;占空比越小,灯光越亮。

四、程序设计

1.原理图

STM32小白入门(第七天)-------定时器_第3张图片STM32小白入门(第七天)-------定时器_第4张图片

不同的定时器,输出通道的数目都有所不一样。在高级定时器输出多路的PWM,输出频率是一样的,但是占空比可以是不一样的,能够由TIM_SetComparex[1-3]来进行设置不同的通道占空比!


2.配置频率

/* TIM14 clock enable ,定时器14时钟使能*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);

/* Time base configuration ,定时器基本配置,TIM_Period是计数值*/
TIM_TimeBaseStructure.TIM_Period = (10000/100)-1;			//输出频率为100Hz,(10000/100)-1得到的结果就是计数值。

TIM_TimeBaseStructure.TIM_Prescaler = 8400-1;				//预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;		//时钟分频,也称之为二次分频,当前是1分频,说白了不分频,不降低频率

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;	//向上计数的方法

TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);			//初始化

STM32小白入门(第七天)-------定时器_第5张图片

/* PWM1 Mode configuration: Channel1 ,让PWM的通道1工作在模式1*/
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;    //PWM模式1,在递增模式下,只要 TIMx_CNT < TIMx_CCR1,通道 1 便为有效状态(高电平),否则为无效状态(低电平)。

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//允许输出

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;	//有效的时候,输出高电平

TIM_OC1Init(TIM14, &TIM_OCInitStructure);

TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);		//自动重载初值,不断输出PWM脉冲

TIM_ARRPreloadConfig(TIM14, ENABLE);				//自动重载初值使能

/* TIM14 enable counter,使能定时器14工作 */
TIM_Cmd(TIM14, ENABLE);

4.配置引脚的复用功能

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);

/* 配置PF9引脚为输出模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;					//第9根引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;				//复用功能模式,使用引脚的第二功能
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;				//推挽模式,增加驱动电流
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;			//设置IO的速度为100MHz,频率越高性能越好,频率越低,功耗越低
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;			//不需要上拉电阻
GPIO_Init(GPIOF, &GPIO_InitStructure);
//将PF9引脚连接到定时器14
GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_TIM14);

2. 计数值与比较值之间的关系




STM32小白入门(第七天)-------定时器_第6张图片

void tim14_init(void)
{
	/* TIM14 clock enable ,定时器14的时钟使能*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);

	/* Time base configuration ,定时器的基本配置,用于配置定时器14输出方波的频率为100Hz*/
	TIM_TimeBaseStructure.TIM_Period = (10000/100)-1;			//10000是10KHz,是定时器3的时钟源,100就是定时器14输出方波的频率			
	TIM_TimeBaseStructure.TIM_Prescaler = 8400-1;				//预分频,也就是说第一次分频,降低频率
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;		//第二次分频,当前是实现1分频,也就是不降低频率
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;	//向上计数方法,从0开始计算
	TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);
	
	/* Output Compare Timing Mode configuration: Channel1 ,让PWM工作是模式1*/
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;				//PWM1模式1:只要 TIMx_CNT < TIMx_CCR1,通道 1 便为有效状态,否则为无效状态。
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//允许输出PWM
	//TIM_OCInitStructure.TIM_Pulse = CCR1_Val;						//待会有专门的函数用于设置比较值,说白就是设置占空比
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;		//通道1有效的状态为高电平
	TIM_OC1Init(TIM14, &TIM_OCInitStructure);
	
	TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);				//定时器14自动重装载初值,那个初值指的是TIM_TimeBaseStructure.TIM_Period,当计数值加到99的时候,又重新从0加到99.		
	TIM_ARRPreloadConfig(TIM14, ENABLE);							//自动重装载初值使能		
	
	/* TIM14 enable counter,使能定时器14工作,开始计数 */
	TIM_Cmd(TIM14, ENABLE);	
}
int main(void)
{
	uint32_t pwm_cmp=0;
	/* GPIOA GPIOE GPIOF硬件时钟使能,就是让GPIOA GPIOE GPIOF工作 */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	
	/* 配置PF9 为复用功能模式 */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;				//第9 引脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;			//输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;			//推挽输出,增强驱动能力,引脚的输出电流更大
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;		//引脚的速度最大为100MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;		//没有使用内部上拉电阻
	GPIO_Init(GPIOF, &GPIO_InitStructure);
	
	/* Connect TIM14 pins to AF9 */  
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_TIM14);//PF9引脚连接到TIM14
	
	//配置系统定时器基于168MHz进行8分频,得到21MHz
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
	
	//设置中断优先级的分组为2,那么支持设置4个中断抢占优先级、4个中断响应优先级
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	
	
	tim14_init();
	
	while(1)
	{
		//不断增加比较值,渐亮还是渐灭?答案:这是渐灭过程
		for(pwm_cmp=0; pwm_cmp<=100; pwm_cmp++)
		{
			TIM_SetCompare1(TIM14,pwm_cmp);
			
			delay_ms(20);
		}
	}
}


你可能感兴趣的:(STM32)