STM32定时器原理与pwm波生成方式

本文章学习STM32HAL库通过定时器pwm模式生成pwm波,实现呼吸灯功能,并通过逻辑分析仪观察波形,并设计超声波模块测距方案。


一、预备知识

(1)定时器原理

STM32的定时器是一种非常常见且重要的外设,它可以用来生成精确的时间间隔,以及控制各种信号的产生和采集。STM32F103系列的单片机提供了多个独立的16位和32位定时器,其中包括3个基本的16位定时器(TIM2-TIM4)和1个高级的16位定时器(TIM1),以及2个16位高级控制定时器(TIM8和TIM5)和2个通用32位定时器(TIM6和TIM7)。

定时器的原理是基于一个内部的计数器来实现,计数器在每个时钟周期自动增加一个单位,从而可以测量时间间隔。定时器的时钟源可以是内部的时钟源(如APB1和APB2时钟),也可以是外部的时钟源(例如TIM1和TIM8的ETR输入)。定时器还可以通过预分频器来降低时钟频率,从而可以实现更长的时间间隔。

定时器可以通过多种模式来实现不同的应用场景,如定时模式、计数模式、输入捕获模式等。定时模式和计数模式是最基本的模式,定时模式可用于生成精确的时间延迟,计数模式可用于计算频率或计数信号的脉冲数。输入捕获模式可以捕获外部信号的电平信息,从而可以测量各种信号的时序和周期.

(2)通用定时器(TIM2、TIM3、TIM4和TIM5)

通用TIMx (TIM2、TIM3、TIM4和TIM5)定时器功能包括:
● 16位向上、向下、向上/向下自动装载计数器
● 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65536之间的任意
数值
● 4个独立通道:
─ 输入捕获
─ 输出比较
─ PWM生成(边缘或中间对齐模式)
─ 单脉冲模式输出
● 使用外部信号控制定时器和定时器互连的同步电路
● 如下事件发生时产生中断/DMA:
─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
─ 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
─ 输入捕获
─ 输出比较
● 支持针对定位的增量(正交)编码器和霍尔传感器电路
● 触发输入作为外部时钟或者按周期的电流管理

(3)什么是PWM波

脉冲宽度调制(PWM),简单来说就是调节信号周期内的占空比(高电平持续时间)来获得我们需要的波形。例如我们需要呼吸灯功能,用PWM波来实现就是在微小的时间周期(利用人眼视觉停留效果)内不断增加输出信号的占空比,也就是电压的大小来控制灯的亮度,达到呼吸灯的效果。
PWM的频率:
是指在1秒钟内,信号从高电平到低电平再回到高电平的次数,也就是说一秒钟PWM有多少个周期,单位Hz。
PWM的周期:
T=1/f,T是周期,f是频率。
如果频率为50Hz ,也就是说一个周期是20ms,那么一秒钟就有 50次PWM周期。
占空比:
是一个脉冲周期内,高电平的时间与整个周期时间的比例
例如下图(占空比不断增大):
在这里插入图片描述

二、CubeMX创建工程

关于CubeMX创建新工程的方法,在前面的博客中有详细提及,下面介绍相关配置:
1.开启外部高速时钟:
在这里插入图片描述
2.TIM3 CH2通道开启
在这里插入图片描述
TIM2 CH1通道开启
在这里插入图片描述

.打开串口usart1
在这里插入图片描述

3.设置计数器值和预分频值(PSC)
在这里插入图片描述
4.时钟源配置
在这里插入图片描述
5.生成工程
在这里插入图片描述


三、代码编写

(1)HAL库TIM相关函数

HAL_TIM_PWM_Start(&htimx,TIM_CHANNEL_x)
开启定时器PWM输出

__HAL_TIM_SetCompare(&htimx,TIM_CHANNEL_x,pwmVal)
设置PWM波的占空比为pwmVal(自定)

TIM_RESET_CAPTUREPOLARITY(&htimx,TIM_CHANNEL_x)
输入捕获清除原先捕获模式

HAL_TIM_IC_Start_IT(&htimx, TIM_CHANNEL_x);
启动输入捕获

HAL_TIM_SET_CAPTUREPOLARITY(&htimx,TIM_CHANNEL_x,TIM_ICPOLARITY_FALLING//RISING)
设置捕获上升沿或者下降沿

HAL_TIM_ReadCapturedValue(&htimx,TIM_CHANNEL_x);
获取当前捕获值

HAL_TIM_IC_Stop_IT(&htimx,TIM_CHANNEL_x);
停止捕获

HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
输入捕获中断函数

(2)参数定义

    uint16_t pwmVal = 500;           //占空比
    uint32_t capture_Buf[3] = {0};   //存放计数值
    uint8_t capture_Cnt = 0;         //状态标志位
    uint32_t high_time;              //高电平时间

(3)呼吸灯效果

通过不断改变占空比实现:

	 while(pwmVal)
	{
		pwmVal-=5;
		__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,pwmVal);
		HAL_Delay(10);
	}
	while(pwmVal<500)
	{
		pwmVal-=5;
		__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,pwmVal);
		HAL_Delay(10);
	}

(4)输入捕获

主函数中:

	case 0:
		capture_Cnt++;
	      TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1);
		__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_ICPOLARITY_RISING);
		HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);	//启动输入捕获 
		break;
	case 3:
		high_time = capture_Buf[1]- capture_Buf[0];    //高电平时间
	    printf ( "高电平时间 :%d us\n",high_time);
//        HAL_UART_Transmit(&huart1, (uint8_t *)high_time, 1, 0xffff);   //发送高电平时间	
		capture_Cnt = 0;  //清空标志位
	    HAL_Delay(10);
		break;		

捕获中断函数:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//输入捕获中断函数
{
	if(htim->Instance == TIM2)//是否是定时器2触发中断
	{
		switch(capture_Cnt){
			case 1:
				capture_Buf[0] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取当前的捕获值.
			    TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1);//清空状态
				__HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);  //设置为下降沿捕获
				capture_Cnt++;
				break;
			case 2:
				capture_Buf[1] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取当前的捕获值.
				HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_1); //停止捕获
				capture_Cnt++;    
		}
	}
}

四、仿真波形

在这里插入图片描述
可以看见高电平时间即(占空比)逐渐减小的过程

五、板级验证

呼吸灯效果:
在这里插入图片描述
输入捕获效果:

在这里插入图片描述

六、HC-SR04超声波测距模块

(1)HC-SR04测距原理

外部 MCU 给模块 Trig 脚一个大于 10uS 的高电平脉冲;模块会给出一个与距离等比的高电平脉冲信号,可根据脉宽时间“T”算出:
距离=T*C/2 (C 为声速)
声速温度公式:c=(331.45+0.61t/℃)m•s-1 (其中 330.45 是在 0℃)
0℃声速: 330.45M/S
20℃声速: 342.62M/S
40℃声速: 354.85M/S

在这里插入图片描述

(2)使用STM32实现测距方案

通过本次定时器的学习,
在实现HC-SR04的超声波模块测距我们可以用到定时器的PWM输出功能和输入捕获功能:
一方面,trig信号通过调节PWM波的占空比来输出;
另一方面,输入捕获模块返回的回响信号,记录高电平时间;随后计算,向串口打印输出。

主函数代码编写:

	  __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,10);//10us trig信号输入
	  case 0:
		capture_Cnt++;
	      TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1);
		__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1, TIM_ICPOLARITY_RISING);
		HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);	//启动输入捕获 
		break;
	case 3:
		high_time = capture_Buf[1]- capture_Buf[0];    //高电平时间
	    printf ( "高电平时间 :%d us\n",high_time);
		capture_Cnt = 0;  //清空标志位
	    HAL_Delay(10);
		break;	

配合定时器捕获中断函数,实现测距功能。

七、总结

本次实验,通过定时器来输出PWM波和实现输入捕获。在实现输入捕获功能时,由于在捕获到相应信号时,由于没有清除原始捕获状态,导致功能不能完全实现。避免下次踩雷。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值