STM32 定时器与PWM的LED控制

news/2024/10/22 16:45:18/

学习目标:

1.  使用定时器的某一个通道控制LED周期性亮灭;

2. 采用定时器PWM模式,让 LED 以呼吸灯方式渐亮渐灭。

一、定时器

1、STM32定时器介绍

STMicroelectronics是STM32微控制器中的重要块,具有丰富的外设和功能,其中包括定时器(Timer),用于执行任务或生成时间延迟。STM32的定时器包括基本、通用和高级类型,分别用于不同的应用场景,如PWM输出、输入捕获等。通过STM32定时器,开发人员可以实现时间测量、周期性任务执行、PWM输出控制等功能,满足各种需求。在STM32开发中,熟练掌握定时器的配置和使用至关重要。

下图为STM32定时器分类:

2、常见的定时器 

SysTick定时器

SysTick系统时钟位于Cortex-M3内核,是一个24位递减计数器

主要用于:

精确延时:在多任务操作系统中为系统提供时间基准(时基);

任务切换:为每个任务分配时间片。

WatchDog看门狗 

看门狗设计是用来监视MCU程序运行状态的,是确保系统可靠稳定运行的一种有效措施。

当微控制器受到外部干扰或程序中出现不可预知的逻辑故障导致应用程序脱离正常的执行流程时(俗称程序跑飞),在一定的时间间隔内使系统复位,回到初始状态。

其中,看门狗又分为两类: 

独立看门狗IWDG:

采用独立时钟,不受其他时钟和总线影响,可在停机和待机模式下工作。

适用于独立于主程序之外、能够独立工作且对时间精度要求不高的场合

窗口看门狗WWDG:

计数值有一个上限时间下限时间,低于下限时间或高于上限时间都会触发MCU复位 。

适用于精确计时窗口起作用的应用程序。 

3、STM32定时器模块

基本定时器

 STM32有2个基本定时器TIM6和TIM7,可用作: 通用的16位计数器;产生DAC触发信号。基本定时器的计数模式只有向上计数模式。

 

通用定时器

TIM2、TIM3、TIM4、TIM5为STM32的4个独立的16位通用定时器,具有定时、测量输入信号的脉冲长度(输入捕获)、输出所需波形(输出比较、产生PWM、单脉冲输出等)等功能。

高级定时器

TIM1和TIM8是STM32的2个16位的高级定时器;高级定时器相比基本定时器、通用定时器,功能更为强大。

作用:通用定时功能(TIM1还提供控制三相六步电机的接口,具有刹车功能、死区时间控制等功能,主要用于电机控制。)

二、PWM

1、PWM介绍

 PWM(Pulse Width Modulation,脉冲宽度调制)是一种利用脉冲宽度即占空比实现对模拟信号进行控制的技术,即是对模拟信号电平进行数字表示的方法。广泛应用于电力电子技术中,比如PWM控制技术在逆变电路中的应用;PWM还应用于直流电机调速,如变频空调的交直流变频调速,除实现调速外,还具有节能等特性。

占空比(Duty Cycle),是指在一个周期内,高电平时间占整个信号周期的百分比,即高电平时间与周期的比值: 占空比 = Tp / T 

2、工作原理

  • STM32的定时器除了TIM6和TIM7,其他定时器都可以用来产生PWM输出;
  • 高级定时器TIM1和TIM8可以同时产生多达7路的PWM输出;
  • 通用定时器能同时产生多达4路的PWM输出; STM32中每个定时器有4个输入通道:TIMx_CH1~TIMx_CH4;
  • 每个通道对应1个捕获/比较寄存器TIMx_CRRx,将寄存器值和计数器值相比较,通过比较结果输出高低电平,从而得到PWM信号;
  • 脉冲宽度调制模式可以产生一个由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号。

任务实现

1、使用定时器的某一个通道控制LED周期性亮灭

要求

使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin(与GPIOx管脚复用,见下图),连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮灭。

代码示例

Timer.c

#include "stm32f10x.h"                  // Device header/*** 函    数:定时中断初始化* 参    数:无* 返 回 值:无*/
void Timer_Init(void)
{/*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);			//开启TIM2的时钟/*配置时钟源*/TIM_InternalClockConfig(TIM2);		//选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟/*时基单元初始化*/TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;				//定义结构体变量TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;		//时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;	//计数器模式,选择向上计数TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1;				//计数周期,即ARR的值TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;				//预分频器,即PSC的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;			//重复计数器,高级定时器才会用到TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);				//将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元	/*中断输出配置*/TIM_ClearFlag(TIM2, TIM_FLAG_Update);						//清除定时器更新标志位//TIM_TimeBaseInit函数末尾,手动产生了更新事件//若不清除此标志位,则开启中断后,会立刻进入一次中断//如果不介意此问题,则不清除此标志位也可TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);					//开启TIM2的更新中断/*NVIC中断分组*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);				//配置NVIC为分组2//即抢占优先级范围:0~3,响应优先级范围:0~3//此分组配置在整个工程中仅需调用一次//若有多个中断,可以把此代码放在main函数内,while循环之前//若调用多次配置分组的代码,则后执行的配置会覆盖先执行的配置/*NVIC配置*/NVIC_InitTypeDef NVIC_InitStructure;						//定义结构体变量NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;				//选择配置NVIC的TIM2线NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				//指定NVIC线路使能NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;	//指定NVIC线路的抢占优先级为2NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;			//指定NVIC线路的响应优先级为1NVIC_Init(&NVIC_InitStructure);								//将结构体变量交给NVIC_Init,配置NVIC外设/*TIM使能*/TIM_Cmd(TIM2, ENABLE);			//使能TIM2,定时器开始运行
}/* 定时器中断函数,可以复制到使用它的地方
void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}
*/

LED.c 

#include "stm32f10x.h"                  // Device headervoid LED_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);
}

 main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "Timer.h"
#include "LED.h"int main(void)
{LED_Init();Timer_Init();	while (1){}
}void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){GPIO_WriteBit(GPIOA,GPIO_Pin_5,(BitAction)((1- GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_5))));TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}

实践结果

最后效果即绿色小灯泡间隔 亮 - 灭 - 亮 - 灭。

2、采用定时器PWM模式,让 LED 以呼吸灯方式渐亮渐灭

要求

采用定时器PWM模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整占空比变化到一个满意效果;使用Keil虚拟示波器,观察 PWM输出波形。

代码示例

PWM.c

#include "stm32f10x.h"                  // Device header/*** 函    数:PWM初始化* 参    数:无* 返 回 值:无*/
void PWM_Init(void)
{/*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);			//开启TIM2的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);			//开启GPIOA的时钟/*GPIO重映射*/
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);			//开启AFIO的时钟,重映射必须先开启AFIO的时钟
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);			//将TIM2的引脚部分重映射,具体的映射方案需查看参考手册
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);		//将JTAG引脚失能,作为普通GPIO引脚使用/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);							//将PA0引脚初始化为复用推挽输出	//受外设控制的引脚,均需要配置为复用模式		/*配置时钟源*/TIM_InternalClockConfig(TIM2);		//选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟/*时基单元初始化*/TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;				//定义结构体变量TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;					//计数周期,即ARR的值TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;				//预分频器,即PSC的值TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器,高级定时器才会用到TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);             //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元/*输出比较初始化*/TIM_OCInitTypeDef TIM_OCInitStructure;							//定义结构体变量TIM_OCStructInit(&TIM_OCInitStructure);							//结构体初始化,若结构体没有完整赋值//则最好执行此函数,给结构体所有成员都赋一个默认值//避免结构体初值不确定的问题TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;				//输出比较模式,选择PWM模式1TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;		//输出极性,选择为高,若选择极性为低,则输出高低电平取反TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//输出使能TIM_OCInitStructure.TIM_Pulse = 0;								//初始的CCR值TIM_OC1Init(TIM2, &TIM_OCInitStructure);						//将结构体变量交给TIM_OC1Init,配置TIM2的输出比较通道1/*TIM使能*/TIM_Cmd(TIM2, ENABLE);			//使能TIM2,定时器开始运行
}/*** 函    数:PWM设置CCR* 参    数:Compare 要写入的CCR的值,范围:0~100* 返 回 值:无* 注意事项:CCR和ARR共同决定占空比,此函数仅设置CCR的值,并不直接是占空比*           占空比Duty = CCR / (ARR + 1)*/
void PWM_SetCompare1(uint16_t Compare)
{TIM_SetCompare1(TIM2, Compare);		//设置CCR1的值
}

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "PWM.h"uint8_t i;			//定义for循环的变量int main(void)
{/*模块初始化*/PWM_Init();			//PWM初始化while (1){for (i = 0; i <= 100; i++){PWM_SetCompare1(i);			//依次将定时器的CCR寄存器设置为0~100,PWM占空比逐渐增大,LED逐渐变亮Delay_ms(15);			//延时500ms}for (i = 0; i <= 100; i++){PWM_SetCompare1(100 - i);	//依次将定时器的CCR寄存器设置为100~0,PWM占空比逐渐减小,LED逐渐变暗Delay_ms(15);		//延时500ms}}
}

实验结果

本人在keil仿真观察波形图时遇到了一些问题,无法更新,目前也在寻找方法不断尝试,等尝试成功会第一时间更新博客

总结

学习定时器和PWM仿佛打开了时间控制与信号调节的大门,为单片机开发提供了新的视角。通过定时器,我能够精确地控制任务执行的时间点,实现预期的动作;而PWM的应用则使LED灯的控制更加灵活多样,可以通过调节脉冲宽度和频率实现各种亮度和闪烁效果。这不仅提升了我对时间和信号调节的理解,也为后续舵机等外设的学习奠定了扎实基础。透过这些学习,我不仅增强了技能,更激发了创造力和探索精神,为未来的单片机开发之路注入了更多动力。


http://www.ppmy.cn/news/1465859.html

相关文章

宝塔面板搭建thinkphp(fastadmin)项目注意事项

thinkphp宝塔面板部署时可能遇到的问题总结 设置静态伪静态为thinkphp模版数据库要同步代码要全部上传,不要拉下重要文件,原有的ignore文件没有上传thinkphp和vendor文件夹,简单处理的话一起放入git库,push上去权限问题会导致打不开,注意要用www用户775权限fastadmin项目php需…

打造云计算时代的仿真软件

2024年5月25日&#xff0c;北京云道智造科技有限公司&#xff08;下称“云道智造”&#xff09;在深圳成功举办了2024新品发布会暨用户大会。来自全国各地的近500位客户和合作伙伴代表齐聚一堂&#xff0c;共同见证了云道智造新产品的隆重发布&#xff0c;交流分享了仿真领域的…

chrome 浏览器历史版本下载

最近做一个项目,要使用到chrome浏览器比较久远的版本,在网上查找资源时,发现chrome比较老的版本的安装包特别难找,几经寻找,总算找到,具体方法如下 打开百度,搜索关键字【chrome版本号‘浏览迷’】&#xff0c;例如“chrome41浏览迷”&#xff0c;找到“全平台”开头的链接&am…

在iPhone上恢复已删除的Safari历史记录的最佳方法

您是否正在寻找恢复 iPhone 上已删除的 Safari 历史记录的最佳方法&#xff1f;好吧&#xff0c;这篇文章提供了 4 种在有/无备份的情况下恢复 iPhone 上已删除的 Safari 历史记录的最佳方法。现在按照分步指南进行操作。 iPhone 上的 Safari 历史记录会被永久删除吗&#xff1…

装甲车启动电源的安全性能分析

装甲车辆启动电源是一种为装甲车辆提供启动动力的专业设备。它通常被用于 火箭兵 、步兵战车、装甲运兵车等JS车辆&#xff0c;这些车辆通常需要较高的启动功率来启动其发动机&#xff0c;尤其是装甲车的发动机&#xff0c;由于其功率大&#xff0c;启动对电力要求很高。在现代…

STM32高级控制定时器应用之检测输入PWM周期和占空比

目录 概述 1 PWM 输入模式 1.1 原理介绍 1.2 应用实例 1.3 示例时序图 2 使用STM32Cube配置工程 2.1 软件环境 2.2 配置参数 2.3 生成项目文件 3 功能实现 3.1 PWM占空比函数 3.2 输入捕捉回调函数 4 功能测试 4.1 测试软件框架结构 4.2 实验实现 4.2.1 测试实…

Ubuntu 20.04 上安装和配置 VNC

先决条件 请确保以具有 sudo 权限的用户身份登录。建议使用具有 sudo 权限的普通用户进行处理&#xff0c;而不是直接使用 root 用户。创建用户并加入 sudoers 可自行百度。 安装桌面环境 大多数服务器没有安装桌面环境&#xff0c;因此我们首先要安装轻量级桌面环境。 Ubu…

网络安全等级保护,三级等保技术建议书(word原件获取)

1信息系统详细设计方案 1.1安全建设需求分析 1.1.1网络结构安全 1.1.2边界安全风险与需求分析 1.1.3运维风险需求分析 1.1.4关键服务器管理风险分析 1.1.5关键服务器用户操作管理风险分析 1.1.6数据库敏感数据运维风险分析 1.1.7“人机”运维操作行为风险综合分析 1.2…