提示:本文章基于stm32F103C8T6最小系统板展开实验
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
定时器作为微控制器不可缺少的外设,在STM32中也是如此。相信不少初学者学到定时器的时候对STM32的学习热情就大打折扣甚至想要放弃了,因为这一部分知识确实比较复杂。但是,如果你在之前对GPIO、串口通信、外部中断的学习中把这些外设掌握了的话,学习这个新知识并不难。
提示:以下是本篇文章正文内容,下面案例可供参考
一、定时器原理
1.定时器简介
STM32定时器总的来说就是用来定时的机器,是存在于STM32单片机中的一个外设。STM32总共有8个定时器,分别是2个高级定时器(TIM1、TIM8),4个通用定时器(TIM2、TIM3、TIM4、TIM5)和2个基本定时器(TIM5、TIM6),如下图所示:
这三种定时器的区别如下:
即:高级定时器具有捕获/比较通道和互补输出,通用定时器只有捕获/比较通道,基本定时器没有以上两者。
2.通用定时器功能和特点
通用定时器功能和特点
STM32的众多定时器中我们使用最多的是高级定时器和通用定时器,而高级定时器一般也是用作通用定时器的功能,下面我们就以通用定时器为例进行讲解,其功能和特点包括:
位于低速的APB1总线上(APB1)
16 位向上、向下、向上/向下(中心对齐)计数模式,自动装载计数器(TIMx_CNT)。
16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数 为 1~65535 之间的任意数值。
4 个独立通道(TIMx_CH1~4),这些通道可以用来作为:
① 输入捕获
② 输出比较
③ PWM 生成(边缘或中间对齐模式)
④ 单脉冲模式输出
可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。
如下事件发生时产生中断/DMA(6个独立的IRQ/DMA请求生成器):
①更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
②触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
③输入捕获
④输出比较
⑤支持针对定位的增量(正交)编码器和霍尔传感器电路
⑥触发输入作为外部时钟或者按周期的电流管理
STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。
使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源
3.定时器工作原理
时钟源
STM32 定时器有多种时钟源。内部时钟(CK_INT)是最常用的一种,它来自于芯片内部的时钟系统,通常是系统时钟(SYSCLK)经过预分频得到的。例如,系统时钟为 72MHz,通过对定时器的预分频器设置,可以得到合适频率的时钟信号作为定时器的计数时钟。
除了内部时钟,还可以使用外部时钟源。外部时钟可以是外部引脚输入的脉冲信号,通过定时器的外部时钟模式配置,使定时器根据外部引脚的脉冲信号进行计数,这种方式适用于需要与外部信号同步计数的应用场景。
预分频器(PSC - Prescaler)
预分频器用于对时钟源进行分频。假设定时器的时钟源频率为,预分频器的值为,那么提供给定时器计数器的实际时钟频率的计算公式为。
例如,如果时钟源频率是 72MHz,预分频器设置为 71,那么实际提供给计数器的时钟频率就是 1MHz。预分频器的存在使得我们可以灵活地调整定时器的计数频率,以适应不同的定时需求。
计数器(CNT)和自动重装载寄存器(ARR)
计数器按照选定的时钟信号进行计数操作。在向上计数模式下,当计数器的值达到自动重装载寄存器的值时,会产生更新事件,计数器重新从初始值开始计数。自动重装载寄存器的值可以根据具体的定时要求进行设置。
比如,要实现一个 1ms 的定时周期,假设计数器时钟频率为 1MHz(即 1 个计数周期为 1μs),那么自动重装载寄存器的值可以设置为 1000,这样计数器从 0 计数到 1000 就刚好是 1ms。
定时器工作模式
定时模式:用于产生精确的时间延迟或周期性的定时操作。通过设置计数器和自动重装载寄存器的值以及时钟源和预分频器,可以实现不同时间长度的定时。
计数模式:可以对外部事件进行计数。例如,对外部传感器产生的脉冲信号进行计数,以统计事件发生的次数。
PWM(脉冲宽度调制)模式:定时器在这种模式下可以产生 PWM 信号。PWM 信号在电机控制、灯光调光等领域有广泛应用。它通过比较计数器的值和比较寄存器(CCR - Capture/Compare Register)的值来控制输出信号的占空比。
中断和 DMA(直接内存访问)请求
当定时器产生更新事件或者其他特定事件(如比较匹配事件)时,可以触发中断请求。在中断服务程序中,可以执行相应的操作,比如更新一些变量、控制其他外设等。同时,定时器事件也可以触发 DMA 请求,通过 DMA 可以实现数据的自动传输,不需要 CPU 的过多干预,提高了系统的效率。例如,在定时器定时采集数据的应用中,利用 DMA 可以将采集到的数据直接存储到内存中。
二、定时器实验
1.实验要求:
请设置一个5秒的定时器,每隔5秒从串口发送“hello windows!”;同时设置一个2秒的定时器,让LED等周期性地闪烁,实现一个多任务并发运行的功能。思考,如果不采用定时器,如何同时完成上面两个周期性任务?
2.工程建立
我们通过stm32cubemx建立工程,根据实验要求,我们可以发现总共需要配置GPIO,串口,定时器等外设,下面是具体操作:
1)打开STM32CubeMX,在主界面点击:ACCESS TO MCU SELECTOR:
(2)选择的单片机型号以及点击开始工程项目:
(3)配置RCC,如图:
(4)配置sys,如图:
5)配置GPIO:PA0。如果仅仅是完成串口通信的话,这一步可以跳过。但是根据实验要求,为了区分串口通信的开启与关闭,要使用一个LED灯来显示。当串口通信开启(STM32向电脑发送信息)的时候,LED灯亮,当串口通信关闭(STM32停止向电脑发送消息)的时候,LED灯灭。
(6)配置USART1,使能UART1,选择异步模式,软件会自动帮我们选择最合适的引脚,配置串口通信的位数大小,校验位,停止位,通信速率等(需要注意,通信双方的数据格式必须一样,一般来说,使用cubemx默认的数据格式就行,不用修改)
(7)配置定时器
我们配置两个定时器,分别是tim2和tim3,按照下图所示进行配置,由于stm32内部时钟我们一般配置为72MHZ,所以分频系数我设置为7200-1,计数周期设置为10000-1,最后我们使能中断,这样的话,定时器2就会每隔1S产生一次中断,定时器3配置方法与定时器2一样,我们也设置为每隔1秒中断一次。
按照下图操作,使能定时器中断:
(8)配置时钟树
(9)进入Project Manager(工程管理),进行工程设置点击生成工程与代码:
注意:路径不能包含中文和空格,不然生成的工程文件无法在Keil中打开;
3.编写程序代码
首先,我们使能定时器,代码如下:
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_Base_Start_IT(&htim3);
然后我们需要编写中断回调函数,当中断发生后,就会执行中断回调函数里面的程序,我们在主函数里面编写中断回调函数,代码如下:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static uint32_t time_cnt2 =0;
static uint32_t time_cnt3 =0;
if(htim->Instance == TIM2)//中断源为定时器2
{
if(++time_cnt2 >= 2)//定时器2中断两次,说明间隔为2秒
{
time_cnt2 =0;
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);
}
}
if(htim->Instance == TIM3)//中断源为定时器3
{
if(++time_cnt3 >= 5)//定时器3中断5次,说明间隔为5秒
{
time_cnt3 =0;
HAL_UART_Transmit(&huart1,hello,20,100000);
}
}
}
编译烧录到单片机后,观察实验现象:
VID_20241211_113914
三、PWM的基本原理
1.pwm简介:
含义:
PWM(Pulse Width Modulation)即脉冲宽度调制,简称脉宽调制。它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术;它是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳压电源输出的改变。
基本原理:
PWM就是对逆变电路开关器件的通断进行控制,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替正弦波或所需要的波形。也可以这样理解,PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。只要带宽足够,任何模拟值都可以使用 PWM 进行编码。
优点及应用范围:
由于其控制简单、灵活和动态响应好等优点而成为电力电子技术应用最广泛的控制方式,其应用领域包括测量,通信, 功率控制与变换,电动机控制、伺服控制、调光、开关电源,甚至某些音频放大器,因此学习PWM具有十分重要的现实意义。
2.stm32的pwm
PWM产生
STM32的定时器除了TIM6和7,其他的定时器都可以用来产生PWM输出。其中高级定时器TIM1和TIM8可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样,STM32 最多可以同时产生 30 路 PWM 输出。
脉冲宽度调制模式可以产生一个由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号。通用定时器产生PWM 的定时器框图如下:(其他定时器框图类似)
3.PWM相关寄存器
包含三个寄存器:捕获/比较模式寄存器(TIMx_CCMR1/2)、捕获/比较使能寄存器(TIMx_CCER)、捕获/比较寄存器(TIMx_CCR1~4)。设置TIMx_CCMRx寄存器OCxPE位以使能相应的预装载寄存器,最后还要设置TIMx_CR1寄存器的ARPE位,(在向上计数或中心对称模式中)使能自动重装载的预装载寄存器。在TIMx_CCMRx寄存器中的OCxM位写入110(PWM模式1)或111(PWM模式2),能够独立地设置每个OCx输出通道产生一路PWM。
这里需要使用的是模式设置位OCxM,总共有两种PWM模式,这两种PWM 模式的区别就是输出电平的极性相反。
110:PWM模式1。在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。
111:PWM模式2。 在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。
该寄存器控制着各个输入输出通道的开关。这里只用到了CC2E位,该位是输入/捕获 2 输出使能位,要想PWM 从 I/O 口输出,这个位必须设置为 1。
在输出模式下,该寄存器的值与 CNT 的值比较,根据比较结果在OC1端口上产生输出信号。利用这点,我们通过修改这个寄存器的值实现控制 PWM 的输出脉宽。
四、PWM的实验
1.实验要求
使用TIM3和TIM4,分别输出一个PWM波形,PWM的占空比随时间变化,去驱动你外接的一个LED以及最小开发板上已焊接的LED(固定接在 PC13 GPIO端口),实现2个 LED呼吸灯的效果。
2.创建工程
1)打开STM32CubeMX,在主界面点击:ACCESS TO MCU SELECTOR:
(2)选择的单片机型号以及点击开始工程项目:
(3)配置RCC,如图:
(4)配置sys,如图:
5)配置GPIO:
(6)配置定时器
我们配置两个定时器,分别是tim3和tim4,按照下图所示进行配置,由于stm32内部时钟我们一般配置为72MHZ,所以分频系数我设置为72-1,计数周期设置为500-1(根据需要是否配置中断),定时器4配置方法与定时器3一样。
(7)配置PWM,首先在通道1设置模式为PWM Generation CH1(PWM输出通道1),接着配置PWM模式,占空比,极性等
(8)配置时钟树
(9)进入Project Manager(工程管理),进行工程设置点击生成工程与代码:
注意:路径不能包含中文和空格,不然生成的工程文件无法在Keil中打开;
3.编写程序
(1)找到主函数,设置占空比,定义一个变量,用来存储占空比:初值设为10,代码如下:
uint16_t duty_num3 = 10;
uint16_t duty_num4 = 10;
(2)开启PWM通道:开始TIM3通道3,输出PWM;开始TIM4通道4,输出PWM,代码如下:
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);
(3)然后在while(1)中设置每隔50毫秒,占空比加10,如果超过500,自动变成低电平,代码如下:
while (1)
{
/* USER CODE END WHILE */
HAL_Delay(50);
duty_num3 = duty_num3 + 10;
duty_num4 = duty_num4 + 10;
if(duty_num3 > 500)
{
duty_num3 = 0;
}
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,duty_num3);
if(duty_num4 > 500)
{
duty_num4 = 0;
}
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_1,duty_num4);
/* USER CODE BEGIN 3 */
}
然后编译下载即可
4.实验现象
注意:处了开发板的指示灯外,另一个管脚是设置的PB6,查手册可知,定时器3,4的一通道分别对应引脚PA6和PB6,其中PB6已经连接了LED灯,但是PA6却是空的,而另一个LED是MCU最小开发板上已焊接的LED(固定接在 PC13 GPIO端口),怎么办呢?其实很简单,只要找一根杜邦线把PA6和P13连在一起后,就可以了,具体硬件连接见下图:
实验现象如下:
VID_20241211_230957
总结
通过本次定时器与 PWM 实验,深入理解了嵌入式系统中定时器和 PWM 的工作原理和实现方法。掌握了如何根据实际需求对定时器进行精确的参数配置,以实现各种定时任务;同时也学会了利用定时器的输出比较功能生成 PWM 信号,并通过调节占空比来控制外部设备的运行状态。
此次实验也让我体会到了嵌入式开发中理论与实践相结合的重要性。虽然在学习过程中对定时器和 PWM 的原理有了一定的了解,但只有通过实际动手实验,才能真正掌握其应用技巧,发现并解决实际问题。在今后的学习和工作中,将继续加强实践操作能力的培养,不断提高自己的嵌入式开发水平。
参考链接:https://blog.csdn.net/qq_44016222/article/details/123507270
https://blog.csdn.net/m0_63323712/article/details/134209896?sharetype=blog&shareId=134209896&sharerefer=APP&sharesource=2401_84314772&sharefrom=qq
https://blog.csdn.net/qq_45237293/article/details/111997424