定时器&PWM应用编程

一、STM32定时器原理

1、基本概念
定时器是一种计时的工具,它具有延时、频率测量、PWM输出、电机控制及编码接口等功能.STM32F103微控制器内部集成了多个可编程定时器,可以分为基本定时器(TIM6和TIM7)、通用定时器(TIM2~TIM5)和高级定时器(TIM1、TIM8)3种类型。从功能上看,基本定时器的功能是通用定时器的子集,而通用定时器的功能又是高级定时器的一个子集。

2、工作原理

时钟源选择:首先需要选择定时器的时钟源。STM32定时器可以选择内部时钟源(如内部RC振荡器)或外部时钟源(如外部晶体振荡器)作为时钟输入。

预分频器设置:定时器的时钟源经过预分频器分频后作为计数器的时钟输入。预分频器可以将时钟源的频率降低,以适应不同的应用需求。

计数器配置:配置计数器的计数模式(向上计数、向下计数、向上/向下计数)、计数方向(递增或递减)以及计数器的初始值。

中断和事件配置:可以配置定时器的中断和事件,以便在计数器达到特定值或特定条件满足时触发中断或事件。

定时器操作:启动定时器后,计数器开始根据时钟源的输入递增或递减。可以通过读取计数器的值来获取定时器的当前计数值。
3、应用
STM32定时器广泛应用于各种领域,例如工业自动化、智能家居、医疗设备、汽车电子等。其中,常见的应用包括PWM波控制、脉冲计数、定时中断、输入捕获等。通过使用STM32定时器,可以实现对各种设备的精确控制和调节,提高系统的稳定性和可靠性

二、用定时器计数方式,控制LED以2s的频率周期性地亮-灭

1、创建工程

在这里插入图片描述
2.
在这里插入图片描述
3.在这里插入图片描述
4.在这里插入图片描述
5.在这里插入图片描述
6.在这里插入图片描述
7.在这里插入图片描述
8.在这里插入图片描述

2、代码修改

1.打开定时器

  HAL_TIM_Base_Start_IT(&htim2);   //打开定时器TIM2 

2.mian.c添加定时器中断回调函数

  void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{

	static uint32_t time_cnt =0;   //记录中断次数
	if(htim->Instance == TIM2)   
	{
		if(++time_cnt >= 40)   //判断是否已经达到两秒
		{
			time_cnt =0;       //点灯用的中断次数归零
			HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_7);    //改变LED所接引脚的电平
		}
	}
	
}

3、烧录执行结果

用定时器计数方式,控制LED以2s的频率周期性地亮-灭

三、采用定时器pwm模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒

1、工程创建

以下为变动处
1.输出管脚为A1
在这里插入图片描述
2.
在这里插入图片描述
3.
在这里插入图片描述

2、代码编写

  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); 
  int pwm = 0;

2.主函数while循环中添加

	  while(pwm<500)
	  {
	   pwm = pwm + 10;
	   __HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,pwm);
	   HAL_Delay(20);//延时20毫秒
	  }
	  while(pwm>0)
	  {
	  pwm = pwm - 10;
	  __HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_2,pwm);
	  HAL_Delay(20);
	  }

3、烧录执行结果

呼吸灯

4、观察PWM输出波形

在这里插入图片描述
2.
在这里插入图片描述
3.
在这里插入图片描述
4.结果

PWM波形图

四、采用定时器的另外一个通道,编程采集上面的pwm输出信号,获得其周期和脉宽,并重定向输出到串口显示

1、工程创建

在这里插入图片描述

2、代码编写

#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "string.h"
#include "stdio.h"

void SystemClock_Config(void);

uint8_t i = 0;
float Duty = 0;
float Frequency = 0;
uint16_t Cap_val1 = 0;
uint16_t Cap_val2 = 0;

int main(void)
{

  HAL_Init();

  MX_GPIO_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  MX_USART1_UART_Init();

  
	printf("串口通信测试\r\n");
    HAL_TIM_Base_Start_IT(&htim2); // 使能定时器及其更新中断
    HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // 使能定时器及其PWM输出
    HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);       // 使能定时器及其输入捕获
    HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2);       // 使能定时器及其输入捕获
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 10); // 设置一个PWM波形进行测量

  while (1)
  {
// 串口发送 频率 占空比
      	  
      printf("Cap_val1 is :%d ,  Cap_val2 is : %d \r\n", Cap_val1, Cap_val2);
        printf("Duty is :%0.2f%% Frequency is : %0.2f ms\r\n", Duty, Frequency);
	  HAL_Delay(1000);

  }
  /* USER CODE END 3 */
}

// 定时输入捕获回调函数 计算占空比和频率
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM1)
    {
        if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
        {
            Cap_val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
        }
        if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
        {
            Cap_val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
            Duty = 100 - (float)Cap_val2 / (float)Cap_val1 * 100;
            Frequency = 0.001 * Cap_val1;
        }
    }
	
}

int fputc(int ch, FILE *f)
 
{
 
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
 
  return ch;
 
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}


void Error_Handler(void)
{

  __disable_irq();
  while (1)
  {
  }

}

#ifdef  USE_FULL_ASSERT

void assert_failed(uint8_t *file, uint32_t line)
{

}
#endif /* USE_FULL_ASSERT */

3、烧录执行结果

在这里插入图片描述
参考:
1.https://blog.youkuaiyun.com/liuwei1015/article/details/134234729
2.https://blog.youkuaiyun.com/qq_64120195/article/details/134222208
3.https://blog.youkuaiyun.com/m0_63650001/article/details/134169585

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值