记:关于输出任意占空比与频率的一种方式——基于STM32单片机
0x00前言
写下这篇文章的主要目的时总结一下最近发现的一个较方便的波形调制方式。可以一定程度脱离手工计算,支持发出任意频率、任意占空比PWM控制信号的方式,使用了较为方便的寄存器的方式进行驱动。本文分为两部分,分别讲述了一个调制信号的思路以及实现的方式、一个计算死区的方式。
阅读本文,您可能需要掌握的知识:
技能 | 熟练度 |
---|---|
英语 | 熟练 |
知识检索 | 熟练 |
数学计算 | 基础 |
逻辑思维 | 熟练 |
0x10 调制信号的方式
项目的主要要求在于,可以随意的调制出任意占空比的1~10KHz的PWM方波。因为这个需求的难度,所以使得软件模拟变成了很难的一件事情。遂我使用STM32系列的高级定时器对波形进行模拟。再查阅了相关资料后我得出的结论,计算波形主要的参数在于占空比以及分频系数上。
0x11 占空比
计算占空比的公式主要是:
PWM占空比=占空比阈值定时器累加值PWM占空比= \frac {占空比阈值} {定时器累加值} PWM占空比=定时器累加值占空比阈值
项目除了较为宽泛的频率选择,还有宽泛的占空比选择。所以为了方便选择占空比,本人主要的思想在于:确认一个固定的定时器累加值。从而在给定了PWM占空比的情况下,就可以得到当前占空比的阈值。而且只需要调高定时器累加值(分母),就可以得到更高的占空比精度。一般的占空比范围于定时器累加值范围表述约为:
占空比范围 | 定时器累加值 |
---|---|
0~100 | 100 |
0~100.0 | 1000 |
0~100.00 | 10000 |
一般来说,占空比精度做到大约万分之一即可。
0x12 分频系数
仔细翻找了官方的一些文档,以及第三方标准库(StdLib)。得到了一个较为完备的公式:
1计时时间=(定时器累加值−1)∗(定时器分频值−1)当前系统时间\frac {1}{计时时间}=\frac{(定时器累加值 - 1) * (定时器分频值-1)}{当前系统时间} 计时时间1=当前系统时间(定时器累加值−1)∗(定时器分频值−1)
而频率对于计时时间的转换公式为:
频率=1计时时间频率=\frac{1}{计时时间} 频率=计时时间1
则公式可以简化成:
频率=(定时器累加值−1)∗(定时器分频值−1)当前系统时间频率=\frac{(定时器累加值 - 1) * (定时器分频值-1)}{当前系统时间} 频率=当前系统时间(定时器累加值−1)∗(定时器分频值−1)
根据此公式,在已知频率、累加器、系统时钟的情况下,可以轻松得出当前定时器分频系数为:
定时器分频系数=频率∗当前系统时钟定时器累加器−1+1定时器分频系数=\frac{频率*当前系统时钟}{定时器累加器-1}+1 定时器分频系数=定时器累加器−1频率∗当前系统时钟+1
直接带入即可计算出可以使用的分频系数,而且基本上不会溢出。也可以通过分频系数推断出当前最高输出的频率。
0x20 死区时间
根据官方给的记录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-omvJ2pJM-1611468191137)(https://www.abcde.engineer/wp-content/uploads/2019/04/7bd8743e14ab72157360d33fddfb9774.png)]
而官方的寄存器记录中并没有提到关于DTS相关的信息,但是在前面的地方就会有解释,这个DTS可以认为是定时器总线时钟片的原子单位。本人使用了120MHz的时钟,也就是说t_DTS=8μs。
单个分频比=死区时间tDTS单个分频比=\frac{死区时间}{t_{DTS}}单个分频比=tDTS死区时间
可以先得到官方例子中的125ns得到对应的分频比:
死区时间 | 单个分频比 | 十六进制 |
---|---|---|
0~15875 | 0~127 | 0~0x7F |
16000~31750 | 128~254 | 0x80~0xFE |
32000~63000 | 256~504 | 0x100~0x1F8 |
64000~126000 | 512~1008 | 0x1FF~0x3F0 |
对此,就可以根据这个分频比就可以分出几个层级,并套用上方给出的几个公式。这里需要注意的是,这个DT计算出DTC的值,需要将其拼接在一起。
根据:
1秒120MHz=8ns\frac{1秒}{120MHz} = 8ns 120MHz1秒=8ns
8ns的分片可以得到:
单个分频比 | 死区区间 |
---|---|
0~127 | 0~1000ns |
128~254 | 1024~2032ns |
256~504 | 2048~4032ns |
512~1008 | 4096~8064ns |
而计算方式反推示例:
DTG[区间]=死区时间(比例系数∗单个分频比)−固定比例DTG[区间]=\frac{死区时间}{(比例系数*单个分频比)}-固定比例 DTG[区间]=(比例系数∗单个分频比)死区时间−固定比例
其中,区间为上述文档中的数据区间,比例系数则为当前的区间比例(1,2,8,16),固定比例为64或者32。
0x30 伪代码
最后自然贴上一段伪代码,虽然加入了较为友好的注释,但是如果不仔细阅读前文估计还是会看的一头雾水…… 而且代码仅仅是伪代码,也就是表明了需要的变量以及一部分必要的流程,但是运行还需要一定的改进。仅供参考!!!!
void TIMER_Init(u16 Period,u16 dead_time,float PWM_Val)u16 PerTime,PerPsc,DeadTimeValue; /* 核心变量,分别是定时器累加值和分频系数以及死区时间 */float PreTemp; /* 关于分频系数计算,因为精度问题,所以需要浮点运算 */float DeadTimeGen = 1000000000 / SystemClock;//时钟频率值 /* 晶振周期,一般为固定值 */float death_time; /* 核心变量,单个分频比 */ death_time = dead_time / DeadTimeGen; /* 单个分频比基数 */if (death_time > 0 && death_time <= 127) /* 1倍DTG */ /* 第一个区间 */{ DeadTimeValue = (u16)death_time; /* 按照第一个区间定义而得 */} else if (death_time >128 && death_time <= 254)/* 2倍DTG */ /* 第二个区间 */{ /* */DeadTimeValue = 0x80 | (u16)(dead_time /(DeadTimeGen * 2) -64); /* 按照第二个区间定义公式而得 */} /* */else if (death_time > 256 && death_time <=504)/* 8倍DTG */ /* 第三个区间 */{ /* */DeadTimeValue = 0xC0 | (u16)(dead_time / (DeadTimeGen * 8) - 32); /* 按照第三个区间定义公式而得 */} /* */else if (death_time > 512 && death_time <= 1008)/* 16倍DTG */ /* 第四个区间 */{ /* */DeadTimeValue = 0xE0 | (u16)(dead_time / (DeadTimeGen * 16) - 32); /* 按照第四个区间定义公式而得 */}else{printf("OverFlow DeadTime!!,Please check your param,Error Value:%d",dead_time); /* 因为这样一定会出现没有包括的地区,所以需要提醒别人,查询配置表 */}PreTemp = 1000000 / Period; /* 计算出当前的周期,精度0.0 *//* 分频系数 */ PreTemp = (SystemCoreClock / 1000000 * PreTemp / 999) - 1; /* 根据上面计算分频系数的方式计算出当前的分频系数 */PerPsc = (u16)PreTemp; /* 人工去除浮点小数 *//* 定时器累加值 */ /* */PerTime = 999; /* 固定的定时器累加值 *//* 占空比--输入例如21.5这样的数字 */ /* */PWM_Val = (PWM_Val * 10); /* 占空比取千分之一0.1% */
0x40 更多
本文首发自 记:关于输出任意占空比与频率的一种方式——基于STM32单片机,更多文章可进入我的博客详查。
记:关于输出任意占空比与频率的一种方式——基于STM32单片机相关推荐
- 任意进制转换java_Java 任意进制转换(两种方式)
本文提供两种Java实现任意进制转换的方法: 方法一:利用 Integer 实现进制转换 1. Integer类的方法toBinaryString(),Integer.toOctalString(), ...
- C#程序输出信息到调试窗口的几种方式
网站项目: System.Diagnostics.Debug.WriteLine("aaa"); 控制项目:Console.WriteLine("bbb"); ...
- STM32单片机可变频率幅度DDS信号发生器正弦波三角波方波AD9833
实践制作DIY- GC0094-DDS信号发生器 一.功能说明: 基于STM32单片机设计-DDS信号发生器 功能介绍: 硬件组成:STM32F103C系列最小系统板 +LCD1602显示器+AD98 ...
- stm32f4 用一个定时器输出多个不同频率占空比PWM波(含代码)
之前有写过怎么使用定时器生成PWM波,以及怎么修改频率与占空比,具体大家可以看下面这篇 stm32f4 生成PWM波_居安士的博客-CSDN博客_stm32产生pwm波 STM32每一个定时器都有4路 ...
- io输出pwm且占空比和频率同时可调驱动实现
1.设计用户层传递方式 只需传递频率和占空比 参数范围:频率:1hz~1Mhz 占空比(高电平时间/周期):1-99 (代表1%~99%) 2.设计方式 思路手稿: 结论: ...
- 10. GD32F103C8T6 定时器-测量pwm的占空比和频率
一. 利用TIM2的输入通道0,通道1测量pwm的占空比和频率 1. 配置gpio void inpit_gpio_config(void) {rcu_periph_clock_enable(RCU_ ...
- STM32单片机一个定时器输出不同频率PWM波
在使用STM32单片机输出PWM波形的时候,通常可以直接使用定时器提供的PWM模式.可以通过自动重装载寄存器(TIMx_ARR)来设置定时器的输出频率,然后通过捕获/ 比较寄存器 1(TIMx_C ...
- PWM占空比,频率,周期之间关系
PWM占空比,频率,周期之间关系 频率所涉及的是周期,频率与周期成倒数.脉宽与占空比所涉及的是周期.脉宽是在一个周期内高电平所占的时间,占空比(如其名)为在一个周期内高电平所占的比例.例如:假设频率为 ...
- 【STM8】PWM 捕获实战:占空比和频率(TIM1)
1. 前言 基于<[众拳STM8 40 讲]PWM 输入捕获原理与实验(频率)>我们已经了解了利用 STM8 库函数 如何捕获和计算 PWM 的频率,但是确没有介绍占空比的捕获方法. 基于 ...
最新文章
- python3 判断字符串是否包含指定字符
- C语言之父,UNIX之父丹尼斯·里奇去世 享年70岁
- [BZOJ1385][Baltic2000]Division expression
- 行高 line-height
- [网络安全提高篇] 一〇八.Powershell和PowerSploit脚本渗透详解 (1)
- angular8 rest_带有Angular JS的Java EE 7 – CRUD,REST,验证–第2部分
- 一键生成通讯录的软件_橙瓜码字自动写作软件,外貌描写对话描写一键生成
- 雷军 1994 年写的代码,你见过吗?厉害了!
- RMAN报错:ORA-19573: 无法获得 exclusive 入队
- 留言系统 php 防攻击,php 留言板防刷新
- 做餐饮,要会算细账,要少折腾
- jdbc预编译插入数据操作
- 阿里巴巴高级Java面试题(首发,70道)
- 关于CAB打包的步骤
- 数据导入与预处理-第6章-04pandas综合案例
- 微信电子商务的B店战略和C店战术
- 2016 版 Laravel 系列入门教程(二)【最适合中国人的 Laravel 教程】
- vue2响应式通过数组下标赋值响应式问题
- 关于无法连接到报表服务器http://localhost/reportserver的解决方案
- 2020年光通信市场下光缆生产发展的宏观分析