[STM32]定位器与PWM的LED控制

news2025/1/14 4:13:26

目录

1. 深入了解STM32定时器原理,掌握脉宽调制pwm生成方法。

(1)STM32定时器原理

原理概述

STM32定时器的常见模式

使用步骤

(2)脉宽调制pwm生成方法。

2. 实验

(1)LED亮灭  

代码

测试效果

(2)呼吸灯

 代码

测试效果

3.总结 


 

1. 深入了解STM32定时器原理,掌握脉宽调制pwm生成方法。

(1)STM32定时器原理

STM32定时器(Timer)是一种用于生成精确时间延时和执行周期性任务的外设。在STM32微控制器中,定时器通常由一组定时器单元组成,每个定时器单元都有自己的计数器和控制寄存器。这些定时器可以配置成多种模式,例如定时器模式、输入捕获模式、输出比较模式等。

原理概述

  1. 计数器:定时器内部有一个计数器,它会不断地自增直到达到预设的值,然后重新开始计数。计数器的增长速率由时钟源决定,可以是内部时钟源(如HSI、LSI)或者外部时钟源(如HSE、HCLK)。

  2. 时钟源:定时器的计数器工作时需要一个时钟源。STM32微控制器提供了多种时钟源供选择,可以通过寄存器配置选择。时钟源的选择影响了定时器的精度和范围。

  3. 预分频器:定时器还可以配置一个预分频器,用于减小时钟源的频率,从而降低计数器增长的速率。这个预分频器可以通过设置寄存器来配置,允许定时器适应不同的应用需求。

  4. 模式配置:STM32定时器可以配置成多种模式,包括计数模式、定时器模式、PWM输出模式等。每种模式有不同的应用场景和功能。

STM32定时器的常见模式

  1. 计数模式:定时器的计数器简单地递增直到达到最大值,然后重新从零开始计数。这种模式通常用于测量时间间隔或者生成延时。

  2. 定时器模式:在这种模式下,定时器的计数器到达预设值后会产生一个中断或者触发一个输出。这种模式常用于产生精确的定时事件。

  3. 输入捕获模式:定时器可以捕获外部信号的边沿,并记录捕获时的计数器值。这种模式常用于测量外部信号的脉冲宽度或者频率。

  4. 输出比较模式:定时器可以将计数器的值与预设的比较值进行比较,并在匹配时触发中断或者改变输出状态。这种模式常用于生成PWM信号或者控制外部设备。

使用步骤

  1. 时钟使能:首先需要启用定时器所需要的时钟源,通常需要配置相应的时钟控制寄存器。

  2. 寄存器配置:根据需要选择定时器、配置预分频器、选择工作模式以及设置相关参数。

  3. 中断配置:如果需要定时器中断,需要配置中断使能和相应的中断优先级。

  4. 启动定时器:配置完成后,启动定时器开始计数。

  5. 处理中断(可选):如果使用了定时器中断,需要编写中断处理函数来处理定时器触发的中断事件。

  6. 定时器应用:根据具体应用需求,在定时器中断或者定时器到期时执行相应的操作。

 定时器的主要功能:

(2)脉宽调制pwm生成方法。

PWM(Pulse Width Modulation,脉冲宽度调制)是一种利用脉冲宽度即占空比实现对模拟信号进行控制的技术,即是对模拟信号电平进行数字表示的方法。

    广泛应用于电力电子技术中,比如PWM控制技术在逆变电路中的应用;     PWM还应用于直流电机调速,如变频空调的交直流变频调速,除实现调速外,还具有节能等特性。

周期为10ms(频率为100Hz) 的PWM波形: 

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

PWM标准外设库输出配置步骤: 

2. 实验

(1)LED亮灭  

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

代码

main.c文件

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
 
uint8_t i;
 
int main(void)
{
	OLED_Init();
	PWM_Init();
	
	while (1)
	{
			PWM_SetCompare1(0);
			Delay_ms(2000);
 
			PWM_SetCompare1(100);
			Delay_ms(2000);
	}
}

PWM.h文件

#ifndef __PWM_H
#define __PWM_H
 
void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);
 
#endif

PWM.c文件

#include "stm32f10x.h"                  // Device header
 
void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启时钟
	
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
	
	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);
	
	TIM_InternalClockConfig(TIM2);
	
	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_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);//给结构体赋初始值
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//设置输出比较的模式
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//设置输出比较极性
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//设置输出状态
	TIM_OCInitStructure.TIM_Pulse = 0;		//设置CCR
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);//放入Init函数中
	
	TIM_Cmd(TIM2, ENABLE);
}
 
void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);
}

测试效果

(2)呼吸灯

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

 代码

main.c文件

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"

uint8_t i;			//定义for循环的变量

int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	PWM_Init();			//PWM初始化
	
	while (1)
	{
		for (i = 0; i <= 100; i++)
		{
			PWM_SetCompare1(i);			//依次将定时器的CCR寄存器设置为0~100,PWM占空比逐渐增大,LED逐渐变亮
			Delay_ms(10);				//延时10ms
		}
		for (i = 0; i <= 100; i++)
		{
			PWM_SetCompare1(100 - i);	//依次将定时器的CCR寄存器设置为100~0,PWM占空比逐渐减小,LED逐渐变暗
			Delay_ms(10);				//延时10ms
		}
	}
}

PWM.h

#ifndef __PWM_H
#define __PWM_H

void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);

#endif

 PWM.c

#include "stm32f10x.h"                  // Device header


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模式1
	TIM_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,定时器开始运行
}


void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);		//设置CCR1的值
}

测试效果

3.总结 

深入了解STM32定时器原理,掌握脉宽调制pwm生成方法,使用hal库制作定时器完成了led灯的亮灭与呼吸灯实验.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1797025.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MySQL】SQL通用语法

【MySQL】SQL通用语法 SQL是结构化查询语言&#xff08;Structured Query Language&#xff09;的缩写&#xff0c;是一种专门用来管理和操作关系型数据库的标准化语言。SQL能够实现数据库的创建、查询、更新和删除操作&#xff0c;以及对数据进行存储、检索和管理。通过SQL语句…

YOLOv5改进 | 主干网络 | 用SimRepCSP作为主干网络提取特征【全网独家 + 降本增效】

&#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; SimRepCSP 类似于 YOLOv7的主干网络&#xff0c;由卷积模块和重参数化卷积&#xff08;RepConv&#xff09;模块组合而成&#xff0c;以 Cro…

政安晨【零基础玩转各类开源AI项目】解析开源:IDM-VTON:改进真实虚拟试穿的扩散模型

目录 概述 要求 数据准备 服饰代码 推理 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 零基础玩转各类开源AI项目 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 项目地址&…

添加图片到资源文件,QPixmap ,QSplash的用法

实现1个QSplash加载之后&#xff0c;呈现主窗体的效果 1、创建资源文件&#xff0c;添加Splash.png文件 2、main.cpp 编码实现 将图像添加资源文件&#xff0c;复制文件的路径 main.cpp :/img/Splash.png 为资源的文件路径 #include "mainwindow.h" #include <…

Flink任务如何跑起来之 1.DataStream和Transformation

Flink任务如何跑起来之 1.DataStream和Transformation 1. 滥觞 在使用Flink完成业务功能之余&#xff0c;有必要了解下我们的任务是如何跑起来的。知其然&#xff0c;知其所以然。 既然重点是学习应用程序如何跑起来&#xff0c;那么应用程序的内容不重要&#xff0c;越简单…

【设计模式深度剖析】【4】【行为型】【策略模式】

文章目录 策略模式定义英文原话直译 角色类图策略接口Strategy&#xff1a;具体策略类上下文类Context测试类 策略模式的应用策略模式的优点策略模式的缺点策略模式的使用场景 策略模式 策略模式&#xff08;Strategy Pattern&#xff09; Strategy策略也称作Policy政策。 想…

快速搭建rtsp server(Ubuntu)

在现代视频监控和实时视频流媒体应用中&#xff0c;实时流协议&#xff08;RTSP&#xff09;服务器扮演着至关重要的角色。无论是家庭安防系统、企业级监控还是流媒体服务&#xff0c;RTSP服务器都能提供高效、稳定的解决方案。然而&#xff0c;对于许多初学者或开发者来说&…

单轮对话和多轮对话

参考&#xff1a;数据集对应关系说明 - 千帆大模型平台 | 百度智能云文档 (baidu.com) 什么是单轮对话 单轮对话和多轮对话是两种不同的对话形式&#xff0c;它们分别指的是在一次对话中只涉及一个问题和对应的回答&#xff0c;以及在一次对话中涉及多个问题和对应的回答。 …

【JMeter接口测试工具】第二节.JMeter基本功能介绍(上)【入门篇】

文章目录 前言一、获取所有学院信息接口执行二、线程组的介绍 2.1 并发和顺序执行 2.2 优先和最后执行线程组 2.3 线程组的设置细节三、HTTP请求的介绍四、查看结果树的配置使用总结 前言 一、获取所有学院信息接口执行 我们先针对一条简单的接口进行执行&#…

【Python报错】已解决AttributeError: ‘method‘ object has no attribute ‘xxx‘

解决Python报错&#xff1a;AttributeError: ‘method’ object has no attribute ‘xxx’ 在Python中&#xff0c;AttributeError通常表明你试图访问的对象没有你请求的属性或方法。如果你遇到了AttributeError: method object has no attribute xxx的错误&#xff0c;这通常意…

Mintegral数据洞察:全球中轻度游戏市场与创意更新频率

基于2024年3月大盘数据&#xff0c;汇量科技数据研究中心发现&#xff0c;超休闲品类仍是投流中轻度手游的中流砥柱。而投流力度较大的其他细分品类里&#xff0c;可以看到棋牌、模拟经营、非4X策略以及合成X游戏的身影&#xff0c;这些品类是近年来经常出现融合玩法的新兴赛道…

算法课程笔记——可撤销并查集

算法课程笔记——可撤销并查集 Gv

(学习笔记)数据基建-数据质量

数据基建-数据质量 数据质量数据质量保障措施如何推动上下游开展数据质量活动数据质量保障如何量化产出数据质量思考全链路数据质量保障项目 数据质量 概念&#xff1a;数据质量&#xff0c;意如其名&#xff0c;就是数据的准确性&#xff0c;他是数据仓库的基石&#xff0c;控…

【Java】static 类方法中注意事项

static 类方法中注意事项 目录 代码示例&#xff1a; package suziguang_d4_staticNote;public class Student {public int score 66;public static String name "zhangsan";// 1.类方法中可以直接访问类的成员&#xff0c;不可以直接访问实例成员public static v…

Unity Vuforia

首先在unity2019版本里可以在windows->PackageManager里搜Vuforia EngineAR; &#xff08;unity2021版本里搜不到&#xff09; 在官网注册账号&#xff1a; 添加识别图等&#xff1b; 将导出的unitypackage包导入unity中。 unity里导入package之后&#xff0c;新建场景&am…

【SpringBoot + Vue 尚庭公寓实战】房间支付方式管理接口实现(三)

【SpringBoot Vue 尚庭公寓实战】房间支付方式管理接口实现&#xff08;三&#xff09; 文章目录 【SpringBoot Vue 尚庭公寓实战】房间支付方式管理接口实现&#xff08;三&#xff09;1、查询全部支付方式列表2、保存或更新支付方式3、根据ID删除支付方式 房间支付方式管理…

C++设计模式——Adapter适配器模式

一&#xff0c;适配器模式简介 适配器模式是一种结构型设计模式&#xff0c;用于将已有接口转换为调用者所期望的另一种接口。 适配器模式让特定的API接口可以适配多种场景。例如&#xff0c;现有一个名为"Reader()"的API接口只能解析txt格式的文件&#xff0c;给这…

CF1553F Pairwise Modulo

#include<bits/stdc.h> #define int long long using namespace std; int n,s,ss,ma,l,r,a[300005],b[300005],c[300005]; //b 记录个数 //c 记录a[i]*k void insert(int x) {int yx;while(x<ma) b[x],x(x&-x); } void insert1(int x,int y) {while(x<ma) c[x]…

掌控数据流:深入解析 Java Stream 编程

Java 8 引入了一种新的抽象称为流&#xff08;Stream&#xff09;&#xff0c;它可以让你以一种声明的方式处理数据。Java 8 Stream API 可以极大提高 Java 程序员的生产力&#xff0c;使代码更简洁&#xff0c;更易读&#xff0c;并利用多核架构进行外部迭代。这里将详细介绍 …

电商核心技术系列58:电商平台的智能数据分析与业务洞察

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘相关系列文章合集&#xff08;3&#xff09; 电商核心技术揭秘56&#xff1a;客户关系管理与忠诚度提升 电商核心技术揭秘57:数…