STM32 PWM驱动设计

单片机学习!

目录

文章目录

前言

一、PWM驱动配置步骤

二、代码示例及注意事项

2.1 RCC开启时钟

2.2 配置时基单元

2.3 配置输出比较单元

2.4 配置GPIO

2.5 运行控制

三、PWM周期和占空比计算

总结


前言

        PWM本质是利用面积等效原理来改变波形的有效值。


一、PWM驱动配置步骤

第一步、RCC开启时钟,将需要的TIM外设和GPIO外设的时钟打开。

第二步、配置时基单元,包括时钟源选择的配置。

第三步、配置输出比较单元,包括CCR的值、输出比较模式、极性选择、输出使能这些参数。(在库函数中也是用结构体统一来配置)。

第四步、配置GPIO,把PWM对应的GPIO口初始化为复用推挽输出的配置。

第五步、运行控制,启动计数器就可以输出PWM了。

二、代码示例及注意事项

2.1 RCC开启时钟

        将需要的TIM外设GPIO外设的时钟打开。打开时钟后定时器的基准时钟和整个外设的工作时钟就会同时打开。

代码示例:

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使用APB1的开启时钟函数,因为TIM2是APB1总线的外设。RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

2.2 配置时基单元

        配置时基单元,包括时钟源选择的配置。

  1. 时基单元的选择时钟源。对于定时中断可选择内部时钟源。
  2. 配置时基单元,包括预分频器、自动重装器、计数模式等,这些参数可用结构体配置。

代码示例:

	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_ClockDivision:指定时钟分频,用于信号经过滤波器时的滤波采样频率。
  • TIM_CounterMode:计数器模式,这里选择向上计数模式TIM_CounterMode_Up。
  • TIM_Period :ARR自动重装器的值。
  • TIM_Prescaler:PSC预分频器的值。
  • TIM_RepetitionCounter:重复计数器的值,只有高级定时器才有,本文初始化通用寄存器,所以值给0。

        时基单元中关键寄存器参数ARR、PSC都有设置,但是这里没有CNT计数器的参数,CNT参数的配置可根据需要在函数 TIM_SetCounter 和函数 TIM_GetCounter 中操作。

        决定定时时间的参数是 TIM_Period 和 TIM_Prescaler 。定时时间可用计数器溢出频率公式计算,定时频率=72M/(PSC+1)/(ARR+1)。

2.3 配置输出比较单元

        配置输出比较单元,包括CCR的值、输出比较模式、极性选择、输出使能这些参数。(在库函数中也是用结构体统一来配置)。

void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

        这里4个初始化函数对应4个输出比较通道(单元),不同的通道对应的GPIO口也不一样,函数的选择需要根据GPIO口的配置选择。代码示例中使用PA0口,对应第一个输出比较通道,选择TIM_OC1Init函数。

代码示例:

	TIM_OCInitTypeDef TIM_OCInitStructture;TIM_OCStructInit(&TIM_OCInitStructture);TIM_OCInitStructture.TIM_OCMode=TIM_OCMode_PWM1; //设置输出比较的模式。TIM_OCInitStructture.TIM_OCPolarity=TIM_OCPolarity_High; //设置输出比较的极性TIM_OCInitStructture.TIM_OutputState=TIM_OutputState_Enable; //设置输出使能TIM_OCInitStructture.TIM_Pulse=50; //设置CCRTIM_OC1Init(TIM2,&TIM_OCInitStructture);   

        代码示例中的程序并没有给结构体的所有成员赋值,而是用TIM_OCStructInit函数先给结构体成员赋一个初始值,再修改部分的结构体成员。这个结构体变量是局部变量,若不给成员赋初始值,它成员的值就是不确定的,这会导致一些问题。比如当你想把高级定时器当作通用定时器输出PWM时,只配置了通用定时器需要的结构体成员,剩下这些没赋值成员就会导致高级定时器输出PWM出现一些奇怪的问题。

        TIM_OCStructInit函数需要把结构体变量的地址传进去,才能给结构体赋初始值。

1. TIM_OCMode设置输出比较的模式。

        TIM_OCMode输出比较模式参数对应含义:

  • TIM_OCMode_Timing 冻结模式                
  • TIM_OCMode_Active 相等时置有效电平                 
  • TIM_OCMode_Inactive 相等时置无效电平               
  • TIM_OCMode_Toggle 相等时电平翻转                 
  • TIM_OCMode_PWM1 PWM模式1                   
  • TIM_OCMode_PWM2 PWM模式2                   
  • TIM_ForcedAction_Active 强制输出有效电平
  • TIM_ForcedAction_InActive 强制输出无效电平

        注:强制输出两种模式的参数不可以在初始化时使用

2. TIM_OCPolarity设置输出比较的极性。

  • TIM_OCPolarity_High 高级性,是极性不翻转,REF波形直接输出。意思是有效电平是高电平,REF有效时,输出高电平。
  • TIM_OCPolarity_Low  低级性,REF电平取反,意思是有效电平为低电平。

3. TIM_OutputState设置输出使能。

4.TIM_Pulse置CCR。 ARR,PSC,CCR共同决定PWM的周期和占空比
 

        以上配置已经把输出比较通道初始化好了,在TIM2的OC1通道上就可以输出PWM波形了,最终这个波形需要通过GPIO口才可以输出。那TIM2的OC1通道是借用哪个GPIO口呢?下文来选择并配置GPIO。


注:TIM_OC1Init是通道1的初始化函数,若通道1、2、3、4都需要的话可以直接在后面加TIM_OC2Init、TIM_OC3Init、TIM_OC4Init,这样就可以同时使用4个通道来输出4个PWM了。

代码示例:

	TIM_OCInitTypeDef TIM_OCInitStructture;TIM_OCStructInit(&TIM_OCInitStructture);TIM_OCInitStructture.TIM_OCMode=TIM_OCMode_PWM1; //设置输出比较的模式。TIM_OCInitStructture.TIM_OCPolarity=TIM_OCPolarity_High; //设置输出比较的极性TIM_OCInitStructture.TIM_OutputState=TIM_OutputState_Enable; //设置输出使能TIM_OCInitStructture.TIM_Pulse=50; //设置CCRTIM_OC1Init(TIM2,&TIM_OCInitStructture);TIM_OC2Init(TIM2,&TIM_OCInitStructture);TIM_OC3Init(TIM2,&TIM_OCInitStructture);TIM_OC4Init(TIM2,&TIM_OCInitStructture);   

        同一个定时器的不同通道输出的PWM,因为不同通道是共用一个计数器的,所以它们的频率必须是一样的;它们的占空比由各自的CCR决定,所以占空比可以各自设定;他们的相位由于计数器更新,所有PWM同时跳变,所以它们的相位是同步的。

        这就是同一个定时器不同通道输出PWM的特点。如果使用多个设备如电机或者舵机,那使用同一个定时器不同通道的PWM就完全可以。


2.4 配置GPIO

        输出比较通道借用GPIO口可以在引脚定义表中查看:

        默认复用功能这一列就是片上外设的端口和GPIO的连接关系。可以找到 TIM2_CH1_ETR 在 PA0 这一行,这说明 TIM2 的 ETR 引脚和通道1的引脚都是借用了 PA0 这个引脚位置,就是TIM2的引脚复用在了PA0引脚上。所以使用TIM2的OC1通道也就是CH1通道输出PWM,就只能在PA0引脚上输出,而不能任意选择引脚输出。

同理:

  • 使用TIM2_CH2只能在PA1端口输出
  • 使用TIM2_CH3只能在PA2端口输出
  • 使用TIM2_CH4只能在PA3端口输出

表中其他外设也是同理:如使用SPI1_MISO只能在PA6端口输出。虽然引脚与外设都是规定好的,但是还可以根据情况做一次改动。在引脚定义表重定义(重映射)这一列,还可以对应更改。如既要使用 USART2_TX 引脚又要使用 TIM2_CH3 通道,但是它俩都在PA2端口输出,这就冲突了没法同时使用。这时可以在重定义列表里找一下,有 TIM2_CH3 ,那么 TIM2_CH3 就可以从PA2端口输出换为从PB10端口输出。这样就避免了两个外设引脚的冲突。但是如果重映射的列表里找不到,那外设复用的GPIO就不能挪位置。配置重映射需要用AFIO来完成。

        配置GPIO,把PWM对应的GPIO口初始化为复用推挽输出的配置。

代码示例:

	GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode= GPIO_Mode_AF_PP;//这里选择复用推挽输出。GPIO_InitStruct.GPIO_Pin= GPIO_Pin_0;GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);

        这里选择复用推挽输出。
        原因:对于普通的开漏/推挽输出,引脚的控制权是来自于输出数据寄存器的,定时器控制引脚需要使用复用开漏/推挽输出的模式,复用开漏/推挽输出模式中输出数据寄存器将被断开,输出控制权将转移给片上外设,通过引脚定义表可知,这里片上外设引脚连接的就是TIM2的CH1通道。所以只有把GPIO设置为复用推挽输出,引脚的控制权才能交给片上外设,PWM波形才能通过引脚输出。
  

2.5 运行控制

        运行控制:整个模块配置完成后,还需要使能一下计数器,PWM波形就能通过PA0输出了。

代码示例:

    TIM_Cmd(TIM2,ENABLE);

三、PWM周期和占空比计算

计算公式:

  • PWM频率:    Freq = CK_PSC / (PSC + 1) / (ARR + 1)      PWM频率等于计数器更新频率。
  • PWM占空比:    Duty = CCR / (ARR + 1)
  • PWM分辨率:    Reso = 1 / (ARR + 1)

        ARR、PSC、CCR共同决定PWM的周期和占空比

代码示例中产生的是一个频率为1KHHz,占空比为50%,分辨率为1%的PWM波形。

代入公式:

  • 72M/(PSC+1)/(ARR+1)=1000
  • CCR/(ARR+1)=50%
  • 1/(ARR+1)=1%

得出:

  • (ARR+1)=100
  • CCR=50
  • (PSC+1)=720

对应代码中:

  • ARR 给 100-1;
  • PSC 给 720-1;
  • CCR 给 50。

        代码运行时,PWM占空比也可更改,可选择使用TIM_SetCompare1、TIM_SetCompare2、TIM_SetCompare3、TIM_SetCompare4 函数改变CCR寄存器的值来调节PWM占空比。但是PWM的占空比是由ARR、PSC、CCR共同决定。


总结

        以上就是今天要讲的内容,本文仅仅简单介绍了PWM驱动配置。

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

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

相关文章

C++初阶入门之命名空间和缺省参数的详细解析

个人主页:点我进入主页 专栏分类:C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂 目录 一.前言 二.命名空间 2.1命名冲突的例子 2.2解决方案 2.3命…

SPA单页面的讲解(超级详细)

目录 一、什么是SPA 二、SPA和MPA的区别 单页应用与多页应用的区别 单页应用优缺点 三、实现一个SPA 原理 实现 hash 模式 history模式 四、题外话:如何给SPA做SEO SSR服务端渲染 静态化 使用Phantomjs针对爬虫处理 一、什么是SPA SPA(sin…

这是一片测试文章

这是一片测试文章 这是一片测试文章 这是一片测试文章 这是一片测试文章 这是一片测试文章 这是一片测试文章 真的是测试文章 -111122225555444433333333222211111 dddddaaa

❤css实用

❤ css实用 CSS渐变色边框(Gradient borders方法的汇总 5种-代码可直接下载) 资源链接 https://download.csdn.net/download/weixin_43615570/88779950?spm1001.2014.3001.5503 给 border 设置渐变色是很常见的效果,实现这个效果有很多思路…

近20k stars,GSYVideoPlayer一款优秀的视频播放器

近20k stars,GSYVideoPlayer一款优秀的视频播放器 引言 在现代社会中,视频已经成为人们获取信息和娱乐的重要形式。为了提供更好的观看体验,开发一款优秀的视频播放器变得至关重要。而GSYVideoPlayer作为一款功能强大、稳定可靠的视频播放器…

没指定spring-boot-maven-plugin版本导致编译失败,这坑你踩过没

文章目录 1. 前言2. 组件版本信息3. 事件经过3.1 本地通过maven命令打包3.2 定位问题步骤3.2.1 核对spring-boot-maven-plugin版本信息3.2.2 spring-boot-maven-plugin版本错误原因 3.3 解决方案 4.结论 1. 前言 我们在平时开发过程中关注的比较多的是项目开发时依赖包的版本以…

数据结构(绪论+算法的基本概念)

文章目录 一、绪论1.1、数据结构的基本概念1.2、数据结构三要素1.2.1、逻辑结构1.2.2、数据的运算1.2.3、物理结构(存储结构)1.2.4、数据类型和抽象数据类型 二、算法的基本概念2.1、算法的特性2.2、“好”算法的特质2.2.1、算法时间复杂度2.2.2、算法空…

java数学计算工具类 double精确的加法算法 double精确的减法算法

java数学计算工具类 double精确的加法算法 double精确的减法算法 精确的乘法算法 对精确的除法运算,当发生除不尽的 保留小数、数值精度 精确的加法算法:2.27 精确的减法算法:0.01 精确的乘法算法:1.2882 相对精确的除法运算,当发生除不尽的情况时&…

领域驱动设计(Domain-Driven Design DDD)——通过重构找到深层次模型1

一、概述 重构就是在不改变软件功能的前提下重新设计它。开发人员无需在着手开发之前做出详细的设计决策,只需要在开发过程中不断小幅调整设计即可,这不但能够保证软件原有的功能不变,还可使整个设计更加灵活易懂。 我们面临的真正挑战是找到…

java使用MD5加密

java使用MD5加密 源字符串:三四五 使用 UTF-8字符集字符集加密后的结果为:f2615f1dab4520fc1e1a79ed6a4f7b37 用 GB2312 字符集加密后的结果为:1dbb006b41466197c486592727af516f 用 GBK 字符集加密后的结果为:1dbb006b41466197c486592727af516f

TCP 状态转换以及半关闭

TCP 状态转换: 上图中还没有进行握手的时候状态是关闭的。 三次握手状态的改变: 客户端发起握手。 调用 connect() 函数时状态转化为:SYN_SENT。调用 listen() 函数时状态转换为:LISTEN。ESTABLISHED是被连接的状态。 四次挥手…

httprunnerV4.X的基本使用详解

目录 1、httprunner概述 1.1、httprunner的优点 2、httprunner的安装 3、基本命令的使用 3.1、生成脚手架 3.2、将har文件转换为测试用例文件 3.3、执行测试用例 3.4、为项目创建虚拟环境,然后安装httprunner库 3.4、执行测试用例生成测试报告 4、httprun…

CSS 双色拼接按钮效果

<template><view class="sss"><button> <!-- 按钮 --><view class="span"> 按钮 </view> <!-- 按钮文本 --></button></view></template><script></script><style>body {b…

【Git】windows系统安装git教程和配置

一、何为Git Git(读音为/gɪt/)是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。 二、git安装包 有2种版本&#xff0c;Git for Windows Setup和Git for Windows Portable(便携版)两个版本都可以。 三、Git for Windows Por…

应急响应红蓝工程师白帽子取证Linux和windows入侵排查还原攻击痕迹,追溯攻击者,以及各种木马和病毒以及恶意脚本文件排查和清除

应急响应红蓝工程师白帽子取证Linux入侵排查还原攻击痕迹,追溯攻击者,以及各种木马和病毒以及恶意脚本文件排查和清除。 一般服务器被入侵的迹象,包括但不局限于:由内向外发送大量数据包(DDOS肉鸡)、服务器资源被耗尽(挖矿程序)、不正常的端口连接(反向shell等)、服务…

Go 知识chan

Go 知识chan 1. 基本知识1.1 定义1.2 操作1.3 操作限定1.4 chan 读写 2. 原理2.1 数据结构2.2 环形队列2.3 等待队列2.4 类型消息2.5 读写数据2.6 关闭chan 3. 使用3.1 操作符使用3.2 select3.3 for-range https://a18792721831.github.io/ 1. 基本知识 chan是go里面里面提供…

源码篇--Redis 五种数据类型

文章目录 前言一、 字符串类型&#xff1a;1.1 字符串的编码格式&#xff1a;1.1.1 raw 编码格式:1.1.2 empstr编码格式:1.1.3 int 编码格式:1.1.4 字符串存储结构展示: 二、 list类型&#xff1a;2.1 List 底层数据支持&#xff1a;2.2 List 源码实现&#xff1a;2.3 List 结构…

微信小程序-04

rpx&#xff08;responsive pixel&#xff09;是微信小程序独有的&#xff0c;用来解决屏适配的尺寸单位。 import 后跟需要导入的外联样式表的相对路径&#xff0c;用 ; 表示语句结束。 定义在 app.wxss 中的样式为全局样式&#xff0c;作用于每一个页面。 在页面的 .wxss 文…

独享http代理安全性是更高的吗?

不同于共享代理&#xff0c;独享代理IP为单一用户提供专用的IP&#xff0c;带来了一系列需要考虑的问题。今天我们就一起来看看独享代理IP的优势&#xff0c;到底在哪里。 我们得先来看看什么是代理IP。简单来说&#xff0c;代理服务器充当客户机和互联网之间的中间人。当你使用…

幻兽帕鲁一键开私服?超简单小白教程一看就会!

如何自建幻兽帕鲁服务器&#xff1f;基于阿里云服务器搭建幻兽帕鲁palworld服务器教程来了&#xff0c;一看就懂系列。本文是利用OOS中幻兽帕鲁扩展程序来一键部署幻兽帕鲁服务器&#xff0c;阿里云服务器网aliyunfuwuqi.com分享官方基于阿里云服务器快速创建幻兽帕鲁服务器教程…