STM32学习笔记---定时器/PWM/输入捕获

1 篇文章 0 订阅
1 篇文章 0 订阅

定时器及相关应用

STM32相关定时器(原理部分)

stm32的定时器十分常用,以下为32的定时器相关数据:

在这里插入图片描述
定时器一般用于输入捕获和输出比较,32位定时器相对于16位定时器的精度更佳高,而根据实际情况我们选择不同的计数方式(仅输出比较而言,上或下技术和仅能够向上计数可以实现不同功能)

定时器有三种计数模式:
1.向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。
2.向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。
3.中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。

在这里插入图片描述
下图为32定时器原理图(TIM2-TIM5,四个通道,如果是9-14的话下方仅有两个通道)

在这里插入图片描述
上边的框图可以分为4个部分:
1.时钟选择部分
2. 时基单元
3. 输入捕获
4. 输出比较
(1)时钟选择部分:
在这里插入图片描述
1.TIMxCLK_INT,即内部时钟CK_INT;
2.外部捕获比较引脚,引脚TI1FP1和TI1F_ED,外部引脚TI2FP2
3.外部触发输入ETR
4.内部触发输入,来自于另一个定时器的输出,对应于框图中的TRGO

在这里插入图片描述

(2)时基单元

在这里插入图片描述
其中包括:1.PSC分频器,分频后产生CK_CNT;2.CNT计数器,负责技术;3.自动重装载器,在相关事件触发后,将寄存器中的值装载到计时器中。
(3)输出比较(即PWM)
在这里插入图片描述
图为输出比较部分的示意图(4通道)
在这里插入图片描述
图中的计数模式为向上计数,使用PWM模式2,有效电平高(极性高)。具体的模式如下:
在这里插入图片描述
(4)输入捕获
在这里插入图片描述
使用时候需要以下步骤:
(1)设置输入捕获滤波器
在这里插入图片描述

在这里插入图片描述
(2)设置输入捕获极性
在这里插入图片描述
在这里插入图片描述
(3)设置输入捕获映射通道
在这里插入图片描述
在这里插入图片描述
(4)设置输入捕获分频器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(5)捕获到有效信号可以开启中断
在这里插入图片描述

代码部分

定时器中断代码

1.初始化部分

void TIM3_Int_Init(u16 arr,u16 psc)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); 使用定时器3的时钟
	
    TIM_TimeBaseInitStructure.TIM_Period = arr; //自动重装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  //波特率
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //分频为1
	
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//定时器初始化
	
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //定时器3溢出中断
	TIM_Cmd(TIM3,ENABLE); //使能定时器3
	
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3的中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级1ÇÀÕ¼ÓÅÏȼ¶1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //响应优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//中断使能
	NVIC_Init(&NVIC_InitStructure);


void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) 
	{
		LED1=!LED1;
	
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //发生溢出中断后要清除中断标志位
}

这里有两个函数查看中断状态标志位,
TIM_GetITStatus和TIM_GetFlagStatus
TIM_GetITStatus 函数中会先判断这种中断是否使能,使能了才去判断中断标志位,而TIM_GetFlagStatus 直接用来判断状态标志位。

PWM输出代码

1.初始化部分
检测高电平持续时间

void TIM14_PWM_Init(u32 arr,u32 psc)
{		 					 
	
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;//输出比较用的结构体
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);  	//
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); 	//
	
	GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;           //
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
	GPIO_Init(GPIOF,&GPIO_InitStructure);              //
	  
	TIM_TimeBaseStructure.TIM_Prescaler=psc;  //
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上技术
	TIM_TimeBaseStructure.TIM_Period=arr;   //
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	
	TIM_TimeBaseInit(TIM14,&TIM_TimeBaseStructure);
	
	
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWM1输出
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //有效电平为低
	TIM_OC1Init(TIM14, &TIM_OCInitStructure);  //通道1初始化,其实按理说不同通道的比较值可以不一样,但是要用到TIM_SetCompare1

	TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); //CCRx寄存器使用
 	TIM_ARRPreloadConfig(TIM14,ENABLE);//ARR寄存器使能
	
	TIM_Cmd(TIM14, ENABLE); 
 
										  
}  

---------------------------------------------------------------------------
int main(void)
{ 
	u16 led0pwmval=0;    
	u8 dir=1;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//
	delay_init(168);  
	
 	TIM14_PWM_Init(500-1,84-1);	
   while(1)//呼吸灯程序
	{
 		delay_ms(10);	 
		if(dir)led0pwmval++;
		else led0pwmval--;	
 		if(led0pwmval>300)dir=0;
		if(led0pwmval==0)dir=1;
 
		TIM_SetCompare1(TIM14,led0pwmval);	//改变通道一比较值,修改占空比

输入比较代码

void TIM14_PWM_Init(u32 arr,u32 psc)
{		 						
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);  	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); 	//
	
	GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); 
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init(GPIOF,&GPIO_InitStructure); 
	
	TIM_TimeBaseStructure.TIM_Prescaler=psc;  
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //
    TIM_TimeBaseStructure.TIM_Period=arr; 
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	
	TIM_TimeBaseInit(TIM14,&TIM_TimeBaseStructure);
	 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //
 	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //
	TIM_OCInitStructure.TIM_Pulse=0;
	TIM_OC1Init(TIM14, &TIM_OCInitStructure);  
	TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);  
    TIM_ARRPreloadConfig(TIM14,ENABLE);
	
	TIM_Cmd(TIM14, ENABLE); //发出脉冲的部分
}  

TIM_ICInitTypeDef  TIM5_ICInitStructure;


void TIM5_CH1_Cap_Init(u32 arr,u16 psc)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);  	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; 
	GPIO_Init(GPIOA,&GPIO_InitStructure); 

	GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5); 
  
	TIM_TimeBaseStructure.TIM_Prescaler=psc;  
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; 
	TIM_TimeBaseStructure.TIM_Period=arr;  
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 

	TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);
	
	TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; 
    TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;	
    TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到T1上
    TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//
    TIM5_ICInitStructure.TIM_ICFilter = 0x00;//不滤波
    TIM_ICInit(TIM5, &TIM5_ICInitStructure);
		
	TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);
	
    TIM_Cmd(TIM5,ENABLE ); 	

    NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;		
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			
	NVIC_Init(&NVIC_InitStructure);	
	
	
}

u8  TIM5CH1_CAPTURE_STA=0;			
u32	TIM5CH1_CAPTURE_VAL;	
void TIM5_IRQHandler(void)
{ 		    

 	if((TIM5CH1_CAPTURE_STA&0X80)==0)
	{
		if(TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET)
		{	     
			if(TIM5CH1_CAPTURE_STA&0X40)
			{
				if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)
				{
					TIM5CH1_CAPTURE_STA|=0X80;		
					TIM5CH1_CAPTURE_VAL=0XFFFFFFFF;
				}else TIM5CH1_CAPTURE_STA++;
			}	 
		}
		if(TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET)
		{	
			if(TIM5CH1_CAPTURE_STA&0X40)	//捕获到高电平,前提是捕获到低电平
				TIM5CH1_CAPTURE_STA|=0X80;	
		        TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5);
	 			TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //极性改变为上升沿
			}else  						
			{
				TIM5CH1_CAPTURE_STA=0;		//每次遇到高电平就归零	
				TIM5CH1_CAPTURE_VAL=0;
				TIM5CH1_CAPTURE_STA|=0X40;	//捕获到高电平的标志	
				TIM_Cmd(TIM5,DISABLE); 	
	 			TIM_SetCounter(TIM5,0);//清零,开始进入
	 			TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling);	//把极性改变为下降沿	
				TIM_Cmd(TIM5,ENABLE ); 
			}		    
		}			     	    					   
 	}
	TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); 
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值