4.stm32定时器实验,基本定时器,高级定时器

一.定时器原理

1. stm32f407定时器

2. 定时器的功能

    2.1  基本定时器TIM功能

        ● 主要运用于定时计数以及驱动DAC

    2.2  通用定时器TIM功能

        ● 定时器定时计数

        ● 输入捕获

        ● 输出比较

        ● PWM输出

        ● 使用外部信号控制定时器和定时器互连的同步电路

   2.3  高级定时器TIM功能

        ● 通用定时器的有功能

        ● 带死区控制和紧急刹车,可用于PWM控制电机

3. 定时器计数功能

   ● 向上计数模式

        计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。

   ● 向下计数模式

        计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。

   ● 中央对齐模式(向上/向下计数)

        计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。

4. 定时器时钟的频率设定 

注意:不是连接了APB2或者APB1,时钟频率就是对应路的频率,可能时2倍 

● 定时器如何确定1倍还是2倍?

如果APBx Prescaler为/1,那么时钟频率就是与路段频率一样(即等于HCLK),如果APBx Prescaler不为/1,那么时钟频率就是APBx Prescaler的2倍.

5. 计数器会从0开始计时


二.基本定时器使用

1. 实验一: 利用基本定时器实现定时1秒中断,并在中断处理函数中打印输出字符

2. cubemx配置

(1)tim6配置<注意:TIM6的NVIC不要忘记使能>

 

 (2)RCC设置为外部晶振,RCC配置成高效率分频

设置的原因:使TIM6的输入时钟频率为84HZ(如下图)

如何确定上述第二章图Prescaler与counter Period的数值?(如下图)

实验步骤:

  1. HAL_TIM_Base_Start_IT(&htim6);函数使用TIM
  2. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)重写回调函数

注意:由于使用的是更新中断,所以找Update

(1)在tim.c中重写回调函数

由于我们设置TIM的是一秒一个中断

疑问:只需要使能一次就可以重复触发中断了,有些怎么不可以,每次都需要使能

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM6)
	{
		printf("tim6 int\n");
	}
}

三.高级定时器的功能分析

0. 总图

  1. 时钟源

2. 控制器

3. 时基单元

4. 输入捕获

5. 公共部分

6. 输出比较

实验二:利用定时器2的输入捕获功能测量按下KEY6键后低电平持续的时间

  1. 看原理图:key6对应PA0,TIM2在数据参考手册中对应APB1频率84MHZ
  2. Cubemx创建工程

        (1)TIM2定时器配置

        (2) RCC时钟配置(HSE设为晶振,时钟按25,336,/4,/2配置)

        (3)USART1串口异步通信

        (4)TIM时基单元的控制(TIM2->configuration->TIM2 control)

         (5)NVIC中断优先级的设定

3. 实验步骤

(1)main.c

HAL_TIM_Base_Start_IT(&htim2);//更新溢出中断
HAL_TIM_IC_Start_IT (&htim2, TIM_CHANNEL_1);//输入捕获中断

 (2)tim.c中更新溢出中断(回调函数)

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
	if(htim->Instance==TIM2){
		if(fall_flag){
			cap_value+=1000000;//每次溢出加一个ARR(单位毫秒)								printf("updata int\n");
		}
	}
}

(3)tim.c的输入捕获中断(回调函数)

uint8_t fall_flag = 0;  //下降沿捕获标记位
uint32_t cap_value = 0;

注意:下面有复制版 

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
	if(!fall_flag){
		printf("捕获下降沿\n");
		HAL_Delay(20);//防抖		            
        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET){
			fall_flag=1;
			
			__HAL_TIM_DISABLE(htim);					//关闭定时器	 
			__HAL_TIM_SET_COUNTER(htim,0);				//设置计数器值为0			        
            TIM_RESET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1); 	//清除原来的设置       
          TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);
//设置为上升沿捕获
			__HAL_TIM_ENABLE(htim);       				 //使能定时器
		}
	}
	else{
		printf("捕获上升沿\n");
		fall_flag = 0;
		//最终时间		  
        cap_value+=HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_1)+20000;
        //HAL_TIM_ReadCapturedValue()读取当前计数器的值
		printf("低电平持续时间= %d秒:%d毫秒:%d微秒\n",
cap_value/1000000,cap_value%1000000/1000,cap_value%1000);
		cap_value=0;
		
		__HAL_TIM_DISABLE(htim);					    //关闭定时器			 
		TIM_RESET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1); 	//清除原来的设置		TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);  //设置为下降沿捕获		
		__HAL_TIM_ENABLE(htim);       				 //使能定时器
		
		HAL_Delay(20);
	}
}

 复制版

uint8_t fall_flag = 0;  //ϽµÑز¶»ñ±ê¼Çλ
uint32_t cap_value = 0;


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM2)
	{
		if(fall_flag)
		{
			cap_value += 1000000;   //ÿ´ÎÒç³ö×öÒ»¸ö¼ÓARRµÄ¼Ç¼
			
			printf("update int \n");
		}
	}
}
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM2)
	{
		if(!fall_flag)       //µ±Ç°²¶»ñµ½µÄÊÇϽµÑØ
		{
			printf("²¶»ñµ½ÁËϽµÑØ\n");
			
			HAL_Delay(20);        //ÑÓʱ20msÏû¶¶
			
			if( HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)  == GPIO_PIN_RESET)
			{
			
				fall_flag = 1;
				
				__HAL_TIM_DISABLE(htim);					    //¹Ø±Õ¶¨Ê±Æ÷
				 
				__HAL_TIM_SET_COUNTER(htim,0);				//ÉèÖüÆÊýÆ÷µÄֵΪ0
				TIM_RESET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1); 	//Çå³ýÔ­À´µÄÉèÖÃ
				TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING);  //ÉèÖÃΪÉÏÉýÑز¶»ñ
			
				__HAL_TIM_ENABLE(htim);       				 //ʹÄܶ¨Ê±Æ÷
			}

		}
		else									//µ±Ç°²¶»ñµ½µÄÊÇÉÏÉýÑØ£¬±¾´Î²¶»ñ½áÊø
		{
			printf("²¶»ñµ½ÁËÉÏÉýÑØ\n");
			
			fall_flag = 0;
			
			//×îÖÕµÄʱ¼ä= Òç³öµÄʱ¼ä + Á½´Î¼ÆÊý²îÖµ + ÑÓʱ¶¶¶¯µÄʱ¼ä
			cap_value = cap_value + HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + 20000 ;
			
			printf("µÍµçƽ³ÖÐøµÄʱ¼ä= %dÃ룺%dºÁÃ룺%d΢Ãî\n",cap_value/1000000,cap_value%1000000/1000,cap_value%1000);
			
			
			cap_value = 0;
			
		  __HAL_TIM_DISABLE(htim);					    //¹Ø±Õ¶¨Ê±Æ÷
			 
			TIM_RESET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1); 	//Çå³ýÔ­À´µÄÉèÖÃ
		  TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING);  //ÉèÖÃΪϽµÑز¶»ñ
		
			__HAL_TIM_ENABLE(htim);       				 //ʹÄܶ¨Ê±Æ÷
			
			HAL_Delay(20);

		}
	}
}

 注意:下面为固定的函数

//关闭定时器

__HAL_TIM_DISABLE(htim);     

//设置计数器值为0

__HAL_TIM_SET_COUNTER(htim,0);

//清除原来的设置

TIM_RESET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1);

//设置为上升沿捕获

TIM_SET_CAPTUREPOLARITY(htim,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);  

 //使能定时器

__HAL_TIM_ENABLE(htim);       

实验三:定时器pwm呼吸灯

1.实验要求,D7(对应PF7)灯实现呼吸灯.

2.cubemx创建工程

(1)RCC时钟使用外部晶振,配置(25,336,/4,/2)

(2)PF7设置TIM11,TIM11设置pwm模式

 

(3)TIM11配置 

(4)没有使用到中断,所以没有使用NVIC

3. 步骤

(1)main.c中

//改变CCR(用来确定有效范围)的值

void TIM11_Set_Compare(uint32_t compare)
{
	TIM11->CCR1 = compare;
}

(2)main.c中

第一步:打开PWM,while()循环之外

	HAL_TIM_PWM_Start(&htim11, TIM_CHANNEL_1);   //Æô¶¯PWM¶¨Ê±Æ÷

第二步:

    int32_t compare = 0;    //设置CCR
    uint8_t dir = 0;        //设置方向
    while(1){
		if(!dir){    //向上增长(变亮)
			compare += 10;
			
			if(compare>=1000)
			{
				compare = 1000-1;
				dir = 1;
			}
		}
		else           //向下减少(变暗)
		{
			compare -= 10; 		
			if(compare<=0)
			{
				compare = 0;
				dir = 0;
			}
			
		}
		
		TIM11_Set_Compare(compare);	//改变CCR
		HAL_Delay(20);

    }

(4)运行结果:D6灯由亮到灭,渐进转变

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值