【STM32F103】TIM定时器PWM
定时器分类
STM32F1中除了互联型产品(STM32F103C8T6为64KB Flash 中容量产品),其余有8个定时器。
可以8个定时器分为高级,通用,基本三种。
高级定时器有两个,分别是TIM1和TIM8。
通用定时器有四个,是TIMx(x=2~4)
基本定时器有两个,是TIMx(x=6~7)
功能上高级>通用>基本
不过高级定时器一般也用不着,如果只是普通的计时的话基本定时器也就够用了,但是基本定时器没有输出比较,没法实现PWM(脉冲宽度调制),因此我们主要使用的是通用定时器,并且STM32F103中通用定时器的资源也是最多的。
下图截自《ARM Cortex-M3嵌入式原理及应用(基于STM32F103微控制器)》的第150页。

通用定时器
下图截自《STM32F10xxx参考手册(中文)》第253页


不太严谨地介绍一下定时器的工作流程。时钟源每传来n(n=预分频器的值)次脉冲,都会使得计数器工作一次。如果选择的是向上计数模式,那么计数器每工作一次都会使得计数器的值+1,直到值等于了自动重装载寄存器的值,那么触发一次中断,并且计数器清零。
如果选择的是向下计数模式,那么计数器每工作一次都会使得计数器的值-1,直到值等于0,那么触发一次中断,并且计数器的值变为自动重装载寄存器的值。
如果选择向上向下计数模式,那么计数器工作一次会使得计数器的值+1或者-1,计数器的值不会被重置,会一直在0和自动重装载寄存器的值之间上下跳动。
一般情况下这三种工作模式对于计数的效果都是一样的,但是当我们需要利用到计数器里的值的时候就有差别了(例如PWM),通常我们使用的是向上计数模式,这也比较符合我们的直觉。
上述的介绍中提到的是以下三个寄存器。

可以看出它们都是只有16位,也就是说可以设置的最大数值为2^16-1(65535)。
并且从工作流程中也可以得知,定时器溢出的频率公式为
时钟源频率/(自动重装载寄存器的值+1)/(预分频器的值+1)=CK_INT/(ARR+1)/(PSC+1)
PWM脉冲宽度调制
STM32F103中每个通用定时器都可以输出4路PWM,而每个高级定时器都可以输出7路PWM,所以理论上,STM32最多是可以同时产生30路PWM。
PWM简单来说就是一段有高电平也有低电平的脉冲信号。
我们一般点亮一个LED灯,就是把LED灯的短脚接地,然后通过GPIO口从LED灯的长脚传入高电平,我们假设此刻LED的亮度为100。如果我们改用PWM来代替原本的高电平,并且PWM传入的脉冲信号中高低电平各占50%,那么此刻LED的亮度就为50%了,因为人眼大概只能接受每秒25帧左右的图像,因此只要PWM够快,那么我们就看不出LED实际上是亮灭亮灭的,由于人眼的残留影像,我们看到的只是LED灯变得暗了些。
之所以把PWM和定时器放在一起,是因为定时器的硬件中就含有捕获比较寄存器。
我们可以给这个寄存器设置一个阈值,当定时器的计数器的值小于这个阈值的时候我们就输出高电平,反之输出低电平(具体看选择的PWM输出模式)。
综上我们可以得知,PWM输出的频率等于定时器的溢出中断频率。
固件库函数
定时器相关的函数还是非常多的,接下来就以计数1ms为目的来说明相关函数。
首先需要打开相关定时器的外设时钟,不过不属于定时器库函数里的,就不介绍。
下一步选择时钟源,默认是使用内部时钟源(72MHz),所以也可以不指定。
然后初始化时基单元(配置自动重装载寄存器,预分频器,时钟分频,计数模式)
接着是中断使能以及配置NVCI相关的中断优先级
最后是使能计数器就可以开始计数了。
TIM_InternalClockConfig

上面三个函数是常用的用来指定时钟源的函数。
第一个也是默认的,使用的是内部时钟作为时钟源。
第二个可以将其他定时器的溢出信号作为时钟源,也就是两个定时器联动,这样可以将最大的计时数平方一次,也就是可以记更久的时间,不过我们也是可以使用软件来完成这种效果的。
第三个可以将时钟源接到外部的时钟。

TIM_TimeBaseInit

初始化时基单元,参数一指定定时器资源,参数二传入一个TIM_TimeBaseInitTyepDef类型的结构体变量用于初始化配置。

TIM_Prescale:预分频器的值,0~65535。
TIM_CounteMode:计数器模式,一般使用向上计数TIM_CounterMode_Up
TIM_Period:自动重装载计数器的值,0~65535。
TIM_ClockDivision:时钟分频,TIM_CKD_DIV1。
TIM_RepetitionCounter:重复计数器的值,只有高级定时器才用的到,基本定时器和通用定时器随便给个0就行。
TIM_ITConfig

中断使能,参数一选择定时器资源,参数二选择中断源,参数三给个ENABLE。

中断源一般就指定第一个TIM_IT_Update
这样每计数一轮都会触发一次中断。
TIM_Cmd

使能计数器。
使能之后计数器就开始运作了,每次记满一轮之后就会进入一次中断,我们可以从“startup_stm32f10x_md.s”中找到对应的中断函数。

由于可进入这个中断函数的中断源有多个(参考上面中断使能的参数表),因为我们需要查询中断标志位是否是我们所规定的TIM_IT_Update触发的,是的话我们还需要手动把标志位清除(其他中断源也是一样)。
TIM_GetITStatus

查询中断标志位,参数二给的一样的TIM_IT_Update。
TIM_ClearITPendingBit

清除中断标志位,参数二给的一样的TIM_IT_Update。
上面的函数就是用来计数用的,接下来就是如何输出PWM的了。
把上面计数的流程走一遍,然后把中断相关的都删掉,再加上配置输出比较单元以及初始化GPIO口的函数即可。
TIM_OC1Init

配置通道1的输出比较单元。这里需要注意的是不同定时器资源的不同通道对应的GPIO输出口是不一样的,TIM2的通道1对应的是GPIOA的0号引脚,具体可以查询引脚定义表。并且需要配置为复用推挽输出模式GPIO_Mode_AF_PP。

参数一指定定时器资源,参数二传入TIM_OCInitTypeDef类型的参数。

一共有八个成员变量,但是我们只需要用到我圈起来的4个,其余为高级定时器使用的。
TIM_OCMode:设置输出比较的模式,一般我们选择TIM_OCMode_PWM1,在这个模式下,当计数器的值小于阈值时输出设置的极性(下面会设置),反之输出相反的极性。
TIM_OCPolarity:输出比较的极性,这个根据需求来设置,设置为高电平的参数为TIM_OCPolarity_High。
TIM_OutputState:设置输出使能,TIM_OutputState_Enable。
TIM_Pulse:设置阈值,0~65535。因此我们定时器的自动重装载寄存器的值最好不要超过这个阈值,并且由于容易计算PWM的占空比,一般我会把自动重装载寄存器的值设为10的倍数。
以上就足够我们输出PWM了,如果我们需要实现呼吸灯的效果,那么还需要动态地调整PWM的阈值。
TIM_SetCompare1

设置通道1的输出比较阈值。
参数一指定定时器资源,参数二重新设置阈值大小。
通用定时器计数1ms代码
#include "stm32f10x.h" // Device header
#include "OLED.h"uint32_t count=0;int main(void){OLED_Init();RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //打开TIM2的外设时钟TIM_InternalClockConfig(TIM2); //选择内部时钟(72MHz)作为时钟源TIM_TimeBaseInitTypeDef itd;itd.TIM_ClockDivision=TIM_CKD_DIV1; //时钟1分频itd.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式itd.TIM_Period=1000-1; //设置自动重装器的值itd.TIM_Prescaler=72-1; //设置预分频器的值//TIM2的计数器溢出频率(每秒中断次数)为//(72MHz/1(1分频)/(1000-1+1)(自动重装器的值+1)/(72-1+1)(预分频器的值+1))=1000(ms级,即1ms溢出一次)itd.TIM_RepetitionCounter=0; //重复计数器的值,但是仅高级定时器有效TIM_TimeBaseInit(TIM2,&itd);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //开启定时器中断,TIM为中断源//配置中断优先级NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //抢占优先级和响应优先级各占两位NVIC_InitTypeDef itd1;itd1.NVIC_IRQChannel=TIM2_IRQn; //指定TIM2的中断通道itd1.NVIC_IRQChannelCmd=ENABLE;itd1.NVIC_IRQChannelPreemptionPriority=2; //抢占优先级为2itd1.NVIC_IRQChannelSubPriority=2; //响应优先级为2NVIC_Init(&itd1);TIM_Cmd(TIM2,ENABLE); //使能定时器while(1){OLED_ShowNum(2,1,count,6);}
}void TIM2_IRQHandler(void){if(TIM_GetITStatus(TIM2,TIM_FLAG_Update)){ //判断是否是TIM中断源引发的中断++count; TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update); //清除标志位}
}
效果

通用定时器使用PWM实现LED呼吸灯
#include "stm32f10x.h" // Device header
#include "Delay.h"int main(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //打开TIM2的外设时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef gitd;gitd.GPIO_Mode=GPIO_Mode_AF_PP; //配置为复用推挽输出gitd.GPIO_Pin=GPIO_Pin_0;gitd.GPIO_Speed=GPIO_Speed_2MHz;GPIO_Init(GPIOA,&gitd);TIM_InternalClockConfig(TIM2); //选择内部时钟(72MHz)作为时钟源TIM_TimeBaseInitTypeDef itd;itd.TIM_ClockDivision=TIM_CKD_DIV1; //时钟1分频itd.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式itd.TIM_Period=100-1; //设置自动重装器的值itd.TIM_Prescaler=72-1; //设置预分频器的值itd.TIM_RepetitionCounter=0; //重复计数器的值,但是仅高级定时器有效TIM_TimeBaseInit(TIM2,&itd);TIM_OCInitTypeDef itd1;itd1.TIM_OCMode = TIM_OCMode_PWM1; //比较输出模式为PWM1itd1.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性为高电平itd1.TIM_OutputState=TIM_OutputState_Enable; //使能itd1.TIM_Pulse=0; //初始化输出比较的阈值 TIM_OC1Init(TIM2,&itd1);TIM_Cmd(TIM2,ENABLE); //使能定时器while(1){for(int i=0;i<=100;++i){ TIM_SetCompare1(TIM2,i);Delay_ms(10);}for(int i=100;i>=0;--i){TIM_SetCompare1(TIM2,i);Delay_ms(10);}}
}
效果

参考
《STM32F10xxx参考手册(中文)》
《STM32F103xx固件函数库用户手册》
b站江科大自化协
《STM32库开发实战指南(基于STM32F103)》
《ARM Cortex-M3嵌入式原理及应用(基于STM32F103微控制器)》
相关文章:
【STM32F103】TIM定时器PWM
定时器分类 STM32F1中除了互联型产品(STM32F103C8T6为64KB Flash 中容量产品),其余有8个定时器。 可以8个定时器分为高级,通用,基本三种。 高级定时器有两个,分别是TIM1和TIM8。 通用定时器有四个&…...
图论及其应用的一些论断---选择题
在任意一个网络N=(X,Y,I,A,c)中,最大流的值等于最小割的容量。在任意6个人的集会上,要么有3个人互相认识,要么有3个人互不认识。若G为无向简单图,则图G的边数ε,点数v之间有: ε < = ( v 2 ) ε<=\binom{v}{2} ε<=...
腾讯云轻量应用服务器镜像操作系统如何选择?
腾讯云轻量应用服务器镜像怎么选择?镜像是指轻量服务器的操作系统,可以选择宝塔Linux面板8.0.4腾讯云专享版,如果需要Win系统建议选择Windows Server 2012 R2 中文版,腾讯云服务器网txyfwq.com分享腾讯云轻量应用服务器镜像操作系…...
鸿蒙原生应用/元服务开发-发布基础类型通知类型与接口
基础类型通知主要应用于发送短信息、提示信息、广告推送等,支持普通文本类型、长文本类型、多行文本类型和图片类型。 表 基础类型通知中的内容分类 目前系统仅通知栏订阅了通知,将通知显示在通知栏里。基础类型通知呈现效果示意图如下所示。 图1基础类…...
Apisix常见问题
1.通过接口操作路由时X-API-KEY cd /usr/local/apisix/conf vim config-default.yaml注释掉这一部分 #allow_admin: # http://nginx.org/en/docs/http/ngx_http_access_module.html#allow# - 0.0.0.0/24 # If we dont set any IP list, then a…...
Docker 安装Mysql
目录 Docker Mysql安装 ✨安装和配置mysql ✨远程连接mysql远程连接 MySQL 是世界上最流行的开源数据库。根据 DB-Engines的调查数据,MySQL 是第二受欢迎的数据库,仅次于 Oracle 数据库。MySQL在过去由于性能高、成本低、可靠性好,已经成…...
Pillow图像处理(PIL.Image类的详细使用)
文章目录 Opencv、Matplotlib(plt)、Pillow(PIL)、Pytorch读取数据的通道顺序Python图像处理库(PIL、Pillow、Scikit-image、Opencv)Pillow 官方文档(超详细,超推荐)一、PIL库与Pillow库的区别二、Pillow库(…...
嵌入式开发——ADC开发
学习目标 了解ADC开发流程掌握采样方式能够使用ADC进行芯片内部通道进行采样能够使用ADC对外部电路进行采样学习内容 GD32F4的ADC 特点: 16个外部模拟输入通道;1个内部温度传感通道(VSENSE);1个内部参考电压输入通道(VREFINT);1个外部监测电池VBAT供电引脚输入通道。ADC开…...
FreeSWITCH t38测试
主叫 192.168.100.205 被叫 192.168.100.121 主叫侧发送multipage.tif 被叫侧接收传真,保存为recv.tif 主叫侧: originate [fax_enable_t381][fax_verbose1][fax_disable_v170][fax_ident77777777][fax_enable_t38_request1]sofia/internal/1234192.168.100.121:…...
跑腿配送系统技术探析
概述 跑腿配送系统是一种基于现代科技的服务平台,通过智能化的技术手段,实现用户需求的快速响应和高效配送。本文将探讨该系统的核心技术原理,以及在实际开发中的一些代码示例。 技术原理 1. 用户请求与任务分配 跑腿配送系统的第一步是…...
【数据不完整?用EM算法填补缺失】期望值最大化 EM 算法:睹始知终
期望值最大化算法 EM:睹始知终 算法思想算法推导算法流程E步骤:期望M步骤:最大化陷入局部最优的原因 算法应用高斯混合模型(Gaussian Mixture Model, GMM)问题描述输入输出Python代码实现 算法思想 期望值最大化方法&a…...
PMP证书可以挂靠吗?
PMP证书不是国内的证书,挂靠不了呀,想挂靠,可以考软考/一建等,里面也有项目管理相关的证书。 PMP证书虽然不能挂靠,但是用处还是很大的,例如提升个人能力、薪资待遇,还有持证可享一些城市的福利…...
HTML语义化的理解
HTML语义化是指在编写HTML代码时,合理地选择适当的标签和属性来描述页面的结构和内容,使得代码更具有可读性、可维护性和可访问性。 可读性:通过使用语义化的标签,可以清晰地表达页面的结构和内容,使得代码更易于阅读和…...
(Java企业 / 公司项目)注册,配置中心Nacos的怎么使用?(含相关面试题)(一)
在企业项目中使用Nacos实现的功能操作,以及如何在自己的环境中搭建Nacos环境,包含demo 一. 官网介绍:home (nacos.io) 文档地址:Nacos 快速开始 二. 准备Nacos环境 在公司里面很多的服务以及环境都是自己搭建的所以我在这里就从…...
计算机网络---知识点
ARPANET----NFSNET—ANSNET—Internet发展及协议 移动互联网 物联网 无线自组网、无线传感器网络、无线个域网 ISO/OSI网络体系结构 TCP/IP网络体系结构 对等通信、PDU 电路交换、报文交换、分组报文交换 虚电路、数据报 信道复用技术 网络性能的主要指标(…...
力扣42. 接雨水
双指针法 思路: 将数组前后设置为 left、right 指针,相互靠近;在逼近的过程中记录两端最大的值 leftMax、rightMax,作为容器的左右边界;更新指针规则: 如果数组左边的值比右边的小,则更新 left…...
SpringSecurity-2.7中跨域问题
SpringSecurity-2.7中跨域问题 访问测试 起因 写这篇的起因是会了解到 SSM(CrosOrigin)解决跨域,但是会在加入SpringSecurity配置后,这个跨域解决方案就失效了,而/login这个请求上是无法添加这个注解或者通过配置(WebMvcConfig)去解决跨域,所以只能使用SpringSecurity提供的.c…...
Java解决字典序最小回文串
Java解决字典序最小回文串 01 题目 给你一个由 小写英文字母 组成的字符串 s ,你可以对其执行一些操作。在一步操作中,你可以用其他小写英文字母 替换 s 中的一个字符。 请你执行 尽可能少的操作 ,使 s 变成一个 回文串 。如果执行 最少 操…...
【力扣100】207.课程表
添加链接描述 class Solution:def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:# 思路是计算每一个课的入度,然后使用队列进行入度为0的元素的进出# 数组:下标是课程号,array[下标]是这个课程的入度# 哈希…...
2024年生成式AI支出将翻倍,到2027年将超1500亿美元
据国际数据公司(IDC)的预测,2023年全球企业在生成式人工智能(GenAI)解决方案上的投资已达194亿美元,预计在2024年将翻番。该预测还指出,包括GenAI软件、相关硬件和服务在内的支出将在2027年达到1511亿美元,…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
