STM32入门学习之定时器PWM输出

1.脉冲宽度调制PWM(Pulse Width Modulation)是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。PWM可以理解为高低电平的占空比,即输出高电平时间与低电平时间的比值。PWM的应用是否广泛,比如在步进电机的控制中,可以通过PWM来控制电机的速度。PWM的原理图如下所示。

 如图中所示,当CNT的值小于ARR时,I/O输出低电平;当CNT的值大于等于ARR时,I/O输出高电平。当CNT的值等于ARR时,CNT的值归零,然后重新向上计数(向上或向下计数可以自行设置)。CNT(TIMx_CNT寄存器是定时器的计数器,该寄存器存储了当前定时器的计数值。)。因此,通过修改自动装载寄存器ARR的值,就可以改变PWM的输出频率。

简单来说,就是设置了自动装载寄存器ARR的值,然后定时器计数CNT,根据CNT与ARR的大小关系,使I/O输出不同的电平。

2.相关寄存器介绍:(寄存器TIMx_CR1、TIMx_PSC、TIMx_ARR、TIMx_SR的介绍请查看:CSDN)

(1)捕获比较模式寄存器(TIMx_CCR1/2):TIMx_CCR1、TIMx_CCR2。

如图所示,第一行为输出时的设置,第二行是输入时的配置。

OCxM是模式设置位,由3位组成,可以控制7种模式。使用PWM模式时,必须设置为110/111。这两种模式的区别是输出的电平极性相反。

CCxS是通道方向的设置位(输入/输出),默认为0,即作为输出使用。

(2)捕获比较使能寄存器(TIMx_CCER):该寄存器控制着各个输入输出通道的开关。

本次实验中只使用到了CC1E位(输入/输出使能位),需要设置为1。

(3)捕获/比较寄存器(TIMx_CCR1~4):TIMx_CCR1、TIMx_CCR2、TIMx_CCR3、TIMx_CCR4。

 在输出模式下,该寄存器的值与定时器的计数值CNT比较,并根据结果使I/O输出高低电平。

(4)刹车和死区寄存器(TIMx_BDTR):该寄存器只有高级定时器需要配置,普通定时器不需要配置此寄存器。本次实验中,实验的普通定时器TIM1,不需要配置此定时器。

如果想要高级定时器正常输出PWM,MOR为必须设置为1。

3.设计思路:首先,使能相应的时钟。然后,配置PA8为复用输出(TIM1_CH1的是和PA8复用的。同时,PA8外接了LED)。其次,设置TIM1的ARR和PSC。最后设置TIM1_CH1的PWM模式和通道方向,使能TIM1的CH1输出。

4.代码:

(1)delay:

#ifndef __DELAY_H
#define __DELAY_H#include "stm32f10x.h"void delay_us(uint32_t us);									//ÑÓʱ΢Ãë
void delay_ms(uint32_t ms);									//ÑÓʱºÁÃë#endif
#include "delay.h"void delay_us(uint32_t us)
{uint32_t i;//1.Ñ¡ÔñHCLKʱÖÓ£¬²¢ÉèÖõδðʱÖÓ¼ÆÊýÖµSysTick_Config(72);for(i = 0;i < us;i++){while(!((SysTick->CTRL) & (1 << 16)));		//µÈ´ý¼ÆÊýÍê³É}SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;	//Ñ¡ÔñSTCLKʱÖÓÔ´£¬²¢Ê§Äܶ¨Ê±Æ÷
}void delay_ms(uint32_t ms)
{uint32_t i;//1.Ñ¡ÔñHCLKʱÖÓÔ´£¬²¢ÉèÖõδðʱÖÓ¼ÆÊýÖµSysTick_Config(72000);for(i = 0;i < ms;i++){while(!((SysTick->CTRL) & (1 << 16)));		//µÈ´ý¼ÆÊýÍê³É}SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;	//Ñ¡ÔñSTCLKʱÖÓÔ´£¬²¢Ê§Äܶ¨Ê±Æ÷
}

(2)led:

#ifndef __LED_H
#define	__LED_H#include "stm32f10x.h"void LED_Init(void);#endif
#include "led.h"void LED_Init(void)
{//¶¨Òå¶Ë¿ÚµÄ½á¹¹Ìå:GPIO_InitTypeDef GPIO_InitStruct;//1.ʹÄÜʱÖÓ£ºRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOA,ENABLE);//2.ÅäÖö˿ڽṹÌåµÄÏà¹ØÐÅÏ¢£º£¨LED1£©GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOD,&GPIO_InitStruct);//ÅäÖÃLED0£ºGPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;GPIO_Init(GPIOA,&GPIO_InitStruct);//³õʼʱ½«LEDµÄ¶Ë¿Ú¶¼ÖÃΪ1£¬¼´Ï¨ÃðGPIO_SetBits(GPIOA,GPIO_Pin_8);GPIO_SetBits(GPIOD,GPIO_Pin_2);
}

(3)pwm:

#ifndef __PWM_H
#define __PWM_H#include "stm32f10x.h"void PWM_Init(u16 arr,u16 psc);#endif
#include "pwm.h"/*±¾´ÎʵÑéÖÐÊÇʹÓÃTIM1Êä³öPWM£¬TIM1ʹÓÃÐèÒª¸´ÓÃPA8ΪÊä³ö*/
void PWM_Init(u16 arr,u16 psc)
{	//¶¨ÒåÏà¹ØµÄ½á¹¹Ì壺GPIO_InitTypeDef GPIO_InitStrcture;TIM_TimeBaseInitTypeDef TIM_InitStructure;TIM_OCInitTypeDef TIM_OCInitStructure;//1.ʹÄÜʱÖÓ£ºRCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA,ENABLE);//2.ÅäÖÃGPIOA.8½á¹¹ÌåÐÅÏ¢£ºGPIO_InitStrcture.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStrcture.GPIO_Pin = GPIO_Pin_8;GPIO_InitStrcture.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStrcture);//3.ÅäÖÃTIM1½á¹¹ÌåÐÅÏ¢£ºTIM_InitStructure.TIM_Period = arr;TIM_InitStructure.TIM_Prescaler = psc;TIM_InitStructure.TIM_ClockDivision = 0;TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Down;TIM_TimeBaseInit(TIM1,&TIM_InitStructure);//4.ÅäÖÃTIM1_CH1µÄPWMģʽºÍͨµÀ·½Ïò£ºTIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_Pulse = 0;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OC1Init(TIM1,&TIM_OCInitStructure);//5.ʹÄÜÏà¹Ø¼Ä´æÆ÷£ºTIM_CtrlPWMOutputs(TIM1,ENABLE);			//ʹÄÜÖ÷Êä³öTIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);	//CH1ԤװÔØʹÄÜTIM_ARRPreloadConfig(TIM1,ENABLE);		//ʹÄÜTIMxµÄARRµÄԤװÔؼĴæÆ÷TIM_Cmd(TIM1,ENABLE);									//ʹÄÜTIM1
}

(4)main:
 

#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "pwm.h"int main(void)
{u8 flag = 1;u16 pwm_value = 0;LED_Init();PWM_Init(899,0);while(1){delay_ms(20);if(flag){pwm_value ++;}else{pwm_value --;}if(pwm_value > 300){//pwm_value = 0;flag = !flag;}if(pwm_value == 0){flag = !flag;}//ÉèÖÃTIM1±È½Ï/²¶»ñͨµÀ¼Ä´æÆ÷µÄÖµ£¬Í¨¹ýÐ޸ĴËÖµ¸Ä±äPWMµÄÕ¼¿Õ±ÈTIM_SetCompare1(TIM1,pwm_value);}
}

5.运行结果:可以看到LED的亮度在自动变化。

 

 6.总结:PWM是通过微控制器的数字输出,控制模拟输出。通常可以利用定时器实现PWM。PWM可以控制I/O输出高低电平的时间,通过I/O输出高低电平的时间,就可以控制外部器件工作/不工作的时间,从而控制其速度或者亮度等。

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

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

相关文章

【MySQL系列】-回表、覆盖索引真的懂吗

【MySQL系列】-回表、覆盖索引真的懂吗 文章目录 【MySQL系列】-回表、覆盖索引真的懂吗一、MYSQL索引结构1.1 索引的概念1.2 索引的特点1.3 索引的优点1.4 索引的缺点 二、B-Tree与BTree2.1 B-Tree2.2 BTree2.3 B-Tree 与BTree树的区别2.4 那么为什么InnoDB的主键最好要搞成有…

记一次 .NET 某外贸ERP 内存暴涨分析

一&#xff1a;背景 1. 讲故事 上周有位朋友找到我&#xff0c;说他的 API 被多次调用后出现了内存暴涨&#xff0c;让我帮忙看下是怎么回事&#xff1f;看样子是有些担心&#xff0c;但也不是特别担心&#xff0c;那既然找到我&#xff0c;就给他分析一下吧。 二&#xff1…

【软件测试】接口测试工具APIpost

说实话&#xff0c;了解APIpost是因为&#xff0c;我的所有接口相关的文章下&#xff0c;都有该APIpost水军的评论&#xff0c;无非就是APIpost是中文版的postman&#xff0c;有多么多么好用&#xff0c;虽然咱也还不是什么啥网红&#xff0c;但是不知会一声就乱在评论区打广告…

【力扣每日一题】2023.8.14 合并二叉树

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 给我们合并两棵二叉树&#xff0c;合并的方式就是把对应位置的节点的值相加&#xff0c;最后把合并后的二叉树的根节点返回出去。 这类二…

You have docker-compose v1 installed, but we require Docker Compose v2.

curl -SL https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose chmod x /usr/local/bin/docker-compose docker-compose --version

一文看尽R-CNN、Fast R-CNN、Faster R-CNN、YOLO、SSD详解

一文看尽R-CNN、Fast R-CNN、Faster R-CNN、YOLO、SSD详解 以下六篇文章总结详细&#xff1a; 1. 一文读懂目标检测&#xff1a;R-CNN、Fast R-CNN、Faster R-CNN、YOLO、SSD 2. 【深度学习】R-CNN 论文解读及个人理解 3、R-CNN论文详解 4、一文读懂Faster RCNN 5、学一百遍都…

JAVA基础知识(六)——异常处理

异常 一、异常概述与异常体系结构二、常见异常三、异常处理机制一&#xff1a;try-catch-finally四、异常处理机制二&#xff1a;throws五、手动抛出异常&#xff1a;throw六、用户自定义异常类七、开发中如何选择使用try-catch-finally还是使用throws八、如何看待代码中的编译…

goland插件推荐Rider UI Theme Pack

推荐一个goland配色插件Rider UI Theme Pack&#xff0c;里面自带visual assist配色&#xff0c;配色截图如下&#xff1a; 直接在plugins里面进行搜索或者在插件home page下载后进行安装&#xff0c; 然后按照下图进行设置即可。 此插件还适用于Jetbrains旗下的Clion和Pycharm…

WX1860- ngbe-1.2.5 xdp程序在路由模式下,使用iperf工具测试数据包不转发,用jmeter可以

本地验证时重定向iperf包有出现calltrace错误&#xff0c;经推断&#xff0c;系统PAGE_SIZE<8k时可能出现&#xff08;getconf PAGE_SIZE指令可查看&#xff09;&#xff0c;按下图将ngbe_main.c的2350行ngbe_rx_bufsz改为ngbe_rx_pg_size可修复。其次&#xff0c;需要将加载…

鸿蒙3.1 基于Token的访问控制

介绍 代码路径:security_access_token: ATM(AccessTokenManager)是OpenHarmony上基于AccessToken构建的统一的应用权限管理能力。 ATM(AccessTokenManager)是OpenHarmony上基于AccessToken构建的统一的应用权限管理能力。 应用的Accesstoken信息主要包括应用身份标识APPID、…

什么是游戏出海运营?

游戏出海运营&#xff0c;也称为游戏海外运营&#xff0c;是指将原本面向国内市场的游戏产品拓展到国际市场&#xff0c;以在海外地区推广、发行、运营游戏的过程。这涵盖了从市场调研、产品适应性优化、本地化翻译、推广营销、社区互动到客户支持等一系列策略和活动&#xff0…

阿里云对象存储服务OSS

1、引依赖 <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.15.1</version> </dependency> <dependency><groupId>javax.xml.bind</groupId><artifa…

Mocha and Red and Blue

一、题目 题面翻译 给定长为 n n n 的仅由 R \texttt{R} R、 B \texttt{B} B、 ? \texttt{?} ? 组成的字符串 S S S&#xff0c;请你在 ? \texttt{?} ? 处填入 R \texttt{R} R 或 B \texttt{B} B&#xff0c;使得相邻位置字符相同的数量最少。 译者 ajthreac 题…

Hadoop HA集群两个NameNode都是standby或者主NameNode是standby,从NameNode是active的情况集锦

文章目录 背景架构HDFS HA配置错误原因解决方案方案一方案二方案三&#xff08;首先查看自己各参数文件是否配置出错&#xff09; 后记补充failovertransitionToActive 常用端口号及配置文件常用端口号hadoop3.xhadoop2.x 常用配置文件 这里说一下配置Hadoop HA集群可能出现的两…

Linux多线程【初识线程】

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; Linux学习之旅 &#x1f383;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 文章目录 &#x1f307;前言&#x1f3d9;️正文1、什么是线程&#xff1f;1.1、基本概念1.2、线程理解1.3、进程与线程的关系…

分布式事务与解决方案

一、什么是分布式事务 首先我们知道本地事务是指事务方法中的操作只依赖本地数据库&#xff0c;可保证事务的ACID特性。而在分布式系统中&#xff0c;一个应用系统被拆分为多个可独立部署的微服务&#xff0c;在一个微服务的事务方法中&#xff0c;除了依赖本地数据库外&#…

【深入理解ES6】块级作用域绑定

1. var声明及变量提升机制 提升&#xff08;Hoisting&#xff09;机制&#xff1a;通过关键字var声明的变量&#xff0c;都会被当成在当前作用域顶部生命的变量。 function getValue(condition){if(condition){var value "blue";console.log(value);}else{// 此处…

代码随想录算法训练营第三十六天 | 435. 无重叠区间,763.划分字母区间,56. 合并区间

代码随想录算法训练营第三十六天 | 435. 无重叠区间&#xff0c;763.划分字母区间&#xff0c;56. 合并区间 435. 无重叠区间:eyes:题目总结:eyes: 763.划分字母区间:eyes:题目总结:eyes: 56. 合并区间:eyes:题目总结:eyes: 435. 无重叠区间 题目链接 视频讲解 给定一个区间的…

并发编程系列-Semaphore

Semaphore&#xff0c;如今通常被翻译为"信号量"&#xff0c;过去也曾被翻译为"信号灯"&#xff0c;因为类似于现实生活中的红绿灯&#xff0c;车辆是否能通行取决于是否是绿灯。同样&#xff0c;在编程世界中&#xff0c;线程是否能执行取决于信号量是否允…

8.10 用redis实现缓存功能和Spring Cache

什么是缓存? 缓存(Cache), 就是数据交换的缓冲区,俗称的缓存就是缓冲区内的数据,一般从数据库中获取,存储于本地代码。 通过Redis来缓存数据&#xff0c;减少数据库查询操作; 逻辑 每个分类的菜品保存一份缓存数据 数据库菜品数据有变更时清理缓存数据 如何将商品数据缓存起…