当前位置: 首页 > news >正文

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

目录

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_Hvoid PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);#endif

PWM.c文件

#include "stm32f10x.h"                  // Device headervoid 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;		//ARRTIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSCTIM_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;		//设置CCRTIM_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_Hvoid PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);#endif

 PWM.c

#include "stm32f10x.h"                  // Device headervoid 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,定时器开始运行
}void PWM_SetCompare1(uint16_t Compare)
{TIM_SetCompare1(TIM2, Compare);		//设置CCR1的值
}

测试效果

3.总结 

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

相关文章:

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

目录 1. 深入了解STM32定时器原理&#xff0c;掌握脉宽调制pwm生成方法。 (1)STM32定时器原理 原理概述 STM32定时器的常见模式 使用步骤 (2)脉宽调制pwm生成方法。 2. 实验 (1)LED亮灭 代码 测试效果 (2)呼吸灯 代码 测试效果 3.总结 1. 深入了解STM32定时器原…...

可视化数据科学平台在信贷领域应用系列五:零代码可视化建模

信贷风控模型是金融机构风险管理的核心工具&#xff0c;在信贷风险管理工作中扮演着至关重要的角色。随着信贷市场的环境不断变化&#xff0c;信贷业务的风险日趋复杂化和隐蔽化&#xff0c;开发和应用准确高效的信贷风控模型显得尤为重要。信贷风险控制面临着越来越大的挑战和…...

Windows 11广告植入“另辟蹊径”:PC Manager暗示若不使用必应搜索,你的系统可能需要“修复”

Edge浏览器近期增添了许多实用的新功能&#xff0c;如侧边栏、休眠标签页和沉浸式阅读器。话虽如此&#xff0c;浏览器中仍有一部分功能被部分用户视为“冗余软件”和不必要的累赘。 随着Windows 11用户逐渐习惯操作系统关键位置出现越来越多的广告&#xff0c;微软似乎正尝试以…...

一线教师教学工具汇总

亲爱的教师们&#xff01;我们的教学工具箱里也该更新换代啦&#xff01;今天&#xff0c;就让我来给大家安利一波超实用的教学神器&#xff1a; 百度文库小程序 —— 在线图书馆 百度文库&#xff0c;一个宝藏级的在线文档分享平台&#xff01;在这里&#xff0c;你可以找到海…...

【数据结构】栈和队列-->理解和实现(赋源码)

Toc 欢迎光临我的Blog&#xff0c;喜欢就点歌关注吧♥ 前面介绍了顺序表、单链表、双向循环链表&#xff0c;基本上已经结束了链表的讲解&#xff0c;今天谈一下栈、队列。可以简单的说是前面学习的一特殊化实现&#xff0c;但是总体是相似的。 前言 栈是一种特殊的线性表&…...

一篇教会你CSS定位

前言&#xff1a;在网页布局的时候&#xff0c;我们需要将想要的元素放到指定的位置上&#xff0c;这个时候我们就可以使用CSS中的定位操作。 先让我们看一下本篇文章的大致内容&#xff1a; 目录 什么是定位 1.相对定位 2.绝对定位 3. 固定定位 4. 粘性定位 5. 定位层级…...

Hive的常规操作

Hive常规操作 hive常用交互命令 -e执行sql语句 [rootmaster ~]# hive -e "show databases";-f执行sql脚本 [rootmaster ~]# hive -f /usr/local/demo.sql查看hive中输入的所有命令 [rootmaster ~]# cat ~/.hivehistory操作库 创建库 语法&#xff1a; create…...

redis做为缓存,mysql的数据如何与redis进行同步呢?

让我们一步步来实现如何让MySQL数据库的数据和Redis缓存保持同步。想象一下&#xff0c;MySQL是一个大仓库&#xff0c;存放着所有重要的货物&#xff08;数据&#xff09;&#xff0c;而Redis则像是一个快速取货窗口&#xff0c;让你能更快拿到常用的东西。为了让两者保持一致…...

【Map】集合总结

一、Map 之前学习的Collection集合体系是单列集合,即一次存取一个元素 Map是双列集合,一次存取一对元素,这一对儿称为键值对,key-value,且key是映射到value 所谓键映射到值,是指只能通过键找到值,无法通过值找键 Map中键不能重复!值允许重复 Map中一个键,只能对应一个值 Ma…...

SpringBoot实现发送邮件功能

目录 一、开启邮件服务 二、导入pom依赖 三、配置yml文件 四、发送邮件 4.1、发送文字邮件 4.2、发送html邮件 4.3、发送附件邮件 4.4、发送图片邮件 一、开启邮件服务 这里拿QQ邮箱举例。 翻到下面进行开启,之后获取授权码。 二、导入pom依赖 <dependency><…...

外观数列 ---- 模拟

题目链接 题目: 分析: 题目的意思如下:所以我们需要引用双指针来找到连续的字符有几个, 并添加到答案中, 接着将此字符添加到答案中, 让left right , 继续向后遍历整个字符串, 重复上面的操作将答案重新赋给字符串, 继续重复上述操作, 应该重复n - 1 次, 因为n为1的时候, 直…...

上心师傅的思路分享(二)

Druid monitor 与Springboot常见报错界面渗透小技巧 目录 前言 1.Druid monitor介绍 2.Druid未授权(1rank) 3.druid弱口令 4.Druid进一步利用 4.1 URL监控 4.2 Session监控 利用思路 EditThisCookie(小饼干插件) 5.SpringBoot Actuator未授权访问漏洞 5.1 简介 5…...

116页 | 2024年中国金融行业网络安全研究报告(免费下载)

以上是资料简介和目录&#xff0c;如需下载&#xff0c;请前往星球获取&#xff01;&#xff01;&#xff01;...

基于fabric封装一个简单的图片编辑器(vue 篇)

介绍 前言vue demo版本react 版本 前言 对 fabric.js 进行二次封装&#xff0c;实现图片编辑器的核心功能。核心代码 不依赖 ui响应式框架vue ,react 都适用。 只写了核心编辑相关代码便于大家后续白嫖二次开发 核心代码我就没有打包发布 会 和 业务代码一起放到项目中。 vu…...

Linux中 .PHONY 和 all 在 Makefile 中的作用

1 .PHONY 和 all .PHONY 是 GNU make 工具中的一个特殊指令&#xff0c;用于指示某个目标是一个伪目标。伪目标并不对应于实际的文件&#xff0c;而是用来执行一系列命令的标识符。使用 .PHONY 的好处包括避免与现有文件同名造成的冲突&#xff0c;以及提高 make 的执行效率&am…...

Flutter 中的 FlexibleSpaceBar 小部件:全面指南

Flutter 中的 FlexibleSpaceBar 小部件&#xff1a;全面指南 Flutter 是一个由 Google 开发的跨平台 UI 框架&#xff0c;它提供了丰富的组件来帮助开发者构建高性能、美观的移动、Web 和桌面应用。在 Flutter 的组件库中&#xff0c;FlexibleSpaceBar 是一个与 SliverAppBar …...

每天一个数据分析题(三百五十四)-分析报表

分析报表的主要作用是通过可视化图表的形式将各种分析结果完整、准确地呈现给阅读者&#xff0c;帮助阅读者读懂数据&#xff0c;从而进一步发现数据背后隐藏的业务问题。下列说法正确的是&#xff1f; A. 静态报表的主要载体是电子表格工具 B. BI报表的数据源获取方式是应用…...

卫星通信频段有哪些

卫星通信使用到的频段涵盖L, S, C, Ku, Ka等&#xff0c;而最常用的频段是C(4~8GHz)和Ku(12~18GHz)频段&#xff0c;而Ka(27-40GHz)频段是后起之秀。目前地球赤道上空有限的地球同步卫星轨位几乎已被各国占满&#xff0c;C和Ku频段内的频率资源被大量使用&#xff0c;而Ka频段的…...

RobotMaster编程语言:深度探索与实践挑战

RobotMaster编程语言&#xff1a;深度探索与实践挑战 RobotMaster编程语言&#xff0c;作为机器人编程领域的一颗璀璨明珠&#xff0c;其独特性与复杂性吸引了无数探索者的目光。本文将从四个方面、五个方面、六个方面和七个方面深入剖析这一编程语言的奥秘&#xff0c;同时揭…...

Ascend训练软件栈了解

一.分布式大模型训练的完整流程及注意事项 1. 迁移分析 模型选取与约束说明 &#xff1a; 确保模型能在GPU或CPU上运行并获取性能基线&#xff0c;了解不支持场景&#xff0c;如DP模式、APEX库、bmtrain框架等。支持度分析 &#xff1a; 使用msFmkTransplt工具分析模型算子、…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

鸿蒙(HarmonyOS5)实现跳一跳小游戏

下面我将介绍如何使用鸿蒙的ArkUI框架&#xff0c;实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...

macOS 终端智能代理检测

&#x1f9e0; 终端智能代理检测&#xff1a;自动判断是否需要设置代理访问 GitHub 在开发中&#xff0c;使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新&#xff0c;例如&#xff1a; fatal: unable to access https://github.com/ohmyzsh/oh…...

当下AI智能硬件方案浅谈

背景&#xff1a; 现在大模型出来以后&#xff0c;打破了常规的机械式的对话&#xff0c;人机对话变得更聪明一点。 对话用到的技术主要是实时音视频&#xff0c;简称为RTC。下游硬件厂商一般都不会去自己开发音视频技术&#xff0c;开发自己的大模型。商用方案多见为字节、百…...

Heygem50系显卡合成的视频声音杂音模糊解决方案

如果你在使用50系显卡有杂音的情况&#xff0c;可能还是官方适配问题&#xff0c;可以使用以下方案进行解决&#xff1a; 方案一&#xff1a;剪映替换音色&#xff08;简单适合普通玩家&#xff09; 使用剪映换音色即可&#xff0c;口型还是对上的&#xff0c;没有剪映vip的&…...

C++ 使用 ffmpeg 解码 rtsp 流并获取每帧的YUV数据

一、简介 FFmpeg 是一个‌开源的多媒体处理框架‌&#xff0c;非常适用于处理音视频的录制、转换、流化和播放。 二、代码 示例代码使用工作线程读取rtsp视频流&#xff0c;自动重连&#xff0c;支持手动退出&#xff0c;解码并将二进制文件保存下来。 注意&#xff1a; 代…...