【正点原子STM32连载】第十八章 通用定时器PWM输出实验 摘自【正点原子】APM32F407最小系统板使用指南
1)实验平台:正点原子stm32f103战舰开发板V4
2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html#
第十八章 通用定时器PWM输出实验
本章将介绍使用APM32F407的通用定时器输出PWM。通过本章的学习,读者将学习到通用定时器输出比较的使用。
本章分为如下几个小节:
18.1 硬件设计
18.2 程序设计
18.3 下载验证
18.1 硬件设计
18.1.1 例程功能
- LED0由暗变亮,再从亮变暗,依次循环
18.1.2 硬件资源 - LED
LED0 - PF9 - 定时器14
通道1 - PF9
18.1.3 原理图
本章实验使用的定时器14为APM32F407的片上资源,因此没有对应的连接原理图。
18.2 程序设计
18.2.1 Geehy标准库的TMR驱动
本章实验将使用TMR14从通道1(PF9引脚)输出PWM,因此除了像上章实验配置定时器的基本参数外,还需要配置通用定时器的输出比较通道,具体的步骤如下:
①:配置TMR14的自动重装载值和预分频器数值等参数
②:配置输出比较通道1
③:使能TMR14
④:使能输出比较通道1输出
⑤:修改比较值以修改PWM输出的占空比
在Geehy标准库中对应的驱动函数如下:
①:配置TMR
请见第16.2.1小节中配置TMR的相关内容。
②:配置输出比较通道
该函数用于配置TMR的任意输出比较通道,其函数原型如下所示:
void TMR_ConfigOC1(TMR_T* tmr, TMR_OCConfig_T* OCConfig);
void TMR_ConfigOC2(TMR_T* tmr, TMR_OCConfig_T* OCConfig);
void TMR_ConfigOC3(TMR_T* tmr, TMR_OCConfig_T* OCConfig);
void TMR_ConfigOC4(TMR_T* tmr, TMR_OCConfig_T* OCConfig);
该函数的形参描述,如下表所示:
该函数的返回值描述,如下表所示:
该函数使用TMR_OCConfig_T类型的结构体变量传入TMR输出比较通道的配置参数,该结构体的定义如下所示:
typedef enum
{TMR_OC_MODE_TMRING = 0x00, /* 冻结 */TMR_OC_MODE_ACTIVE = 0x01, /* 匹配时输出置为高 */TMR_OC_MODE_INACTIVE = 0x02, /* 匹配时输出置为低 */TMR_OC_MODE_TOGGLE = 0x03, /* 匹配时输出翻转 */TMR_OC_MODE_LOWLEVEL = 0x04, /* 强制输出为低 */TMR_OC_MODE_HIGHLEVEL = 0x05, /* 强制输出为高 */TMR_OC_MODE_PWM1 = 0x06, /* PWM模式1 */TMR_OC_MODE_PWM2 = 0x07 /* PWM模式2 */
} TMR_OC_MODE_T;typedef enum
{TMR_OC_STATE_DISABLE, /* 禁止输出 */TMR_OC_STATE_ENABLE /* 开启输出 */
} TMR_OC_STATE_T;typedef enum
{TMR_OC_NSTATE_DISABLE, /* 禁止互补输出 */TMR_OC_NSTATE_ENABLE /* 开启互补输出 */
} TMR_OC_NSTATE_T;typedef enum
{TMR_OC_POLARITY_HIGH, /* 高电平有效 */TMR_OC_POLARITY_LOW /* 低电平有效 */
} TMR_OC_POLARITY_T;typedef enum
{TMR_OC_NPOLARITY_HIGH, /* 互补高电平有效 */TMR_OC_NPOLARITY_LOW /* 互补低电平有效 */
} TMR_OC_NPOLARITY_T;typedef enum
{TMR_OC_IDLE_STATE_RESET, /* 空闲时为低电平 */TMR_OC_IDLE_STATE_SET /* 空闲时为高电平 */
} TMR_OC_IDLE_STATE_T;typedef enum
{TMR_OC_NIDLE_STATE_RESET, /* 互补空闲时为低电平 */TMR_OC_NIDLE_STATE_SET /* 互补空闲时为高电平 */
} TMR_OC_NIDLE_STATE_T;typedef struct
{TMR_OC_MODE_T mode; /* 模式 */TMR_OC_STATE_T outputState; /* 输出状态 */TMR_OC_NSTATE_T outputNState; /* 互补通道输出状态 */TMR_OC_POLARITY_T polarity; /* 极性 */TMR_OC_NPOLARITY_T nPolarity; /* 互补通道极性 */TMR_OC_IDLE_STATE_T idleState; /* 空闲状态 */TMR_OC_NIDLE_STATE_T nIdleState; /* 互补通道空闲状态 */uint16_t pulse; /* 比较值 */
} TMR_OCConfig_T;
该函数的使用示例,如下所示:
#include "apm32f4xx.h"
#include "apm32f4xx_tmr.h"void example_fun(void)
{TMR_OCConfig_T tmr_oc_init_struct;/* 配置TMR1输出比较通道1及其互补通道 */tmr_oc_init_struct.mode = TMR_OC_MODE_PWM1;tmr_oc_init_struct.outputState = TMR_OC_STATE_ENABLE;tmr_oc_init_struct.outputNState = TMR_OC_NSTATE_ENABLE;tmr_oc_init_struct.polarity = TMR_OC_POLARITY_LOW;tmr_oc_init_struct.nPolarity = TMR_OC_NPOLARITY_HIGH;tmr_oc_init_struct.idleState = TMR_OC_IDLE_STATE_RESET;tmr_oc_init_struct.nIdleState = TMR_OC_NIDLE_STATE_RESET;tmr_oc_init_struct.pulse = 255;TMR_ConfigOC1(TMR1, &tmr_oc_init_struct);
}
③:使能TMR
请见第16.2.1小节中使能TMR的相关内容。
④:使能捕获比较通道
该函数用于使能捕获比较通道,其函数原型如下所示:
void TMR_EnableCCxChannel(TMR_T* tmr, TMR_CHANNEL_T channel);
该函数的形参描述,如下表所示:
表18.2.1.3 函数TMR_EnableCCxChannel()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表18.2.1.4 函数TMR_EnableCCxChannel()返回值描述
该函数的使用示例,如下所示:
#include "apm32f4xx.h"
#include "apm32f4xx_tmr.h"void example_fun(void)
{/* 使能TMR1捕获比较通道1 */TMR_EnableCCxChannel(TMR1, TMR_CHANNEL_1);
}
⑤:配置捕获比较值
该函数用于配置TMR指定通道的捕获比较值,其函数原型如下所示:
void TMR_ConfigCompare1(TMR_T* tmr, uint32_t compare1);
void TMR_ConfigCompare2(TMR_T* tmr, uint32_t compare2);
void TMR_ConfigCompare3(TMR_T* tmr, uint32_t compare3);
void TMR_ConfigCompare4(TMR_T* tmr, uint32_t compare4);
该函数的形参描述,如下表所示:
形参 描述
tmr 指向TMR外设结构体的指针
例如:TMR1、TMR2等(在apm32f4xx.h文件中有定义)
comparen 捕获比较值
表18.2.1.5 函数TMR_ConfigComparen()形参描述
该函数的返回值描述,如下表所示:
返回值 描述
无 无
表18.2.1.6 函数TMR_ConfigComparen()返回值描述
该函数的使用示例,如下所示:
#include "apm32f4xx.h"
#include "apm32f4xx_tmr.h"void example_fun(void)
{/* 配置TMR1捕获比较寄存器1的值 */TMR_ConfigCompare1(TMR1, 200);
}
18.2.2 通用定时器驱动
本章实验的通用定时器驱动主要负责向应用层提供通用定时器的初始化函数。本章实验中,通用定时器的驱动代码包括gtmr.c和gtmr.h两个文件。
通用定时器驱动中,对TMR、GPIO的相关宏定义,如下所示:
#define GTMR_TMRX_PWM TMR14
#define GTMR_TMRX_PWM_CHY TMR_CHANNEL_1
#define GTMR_TMRX_PWM_CLK_ENABLE() \do { \RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR14); \} while (0)#define GTMR_TMRX_PWM_CHY_GPIO_PORT GPIOF
#define GTMR_TMRX_PWM_CHY_GPIO_PIN GPIO_PIN_9
#define GTMR_TMRX_PWM_CHY_GPIO_PIN_SOURCE GPIO_PIN_SOURCE_9
#define GTMR_TMRX_PWM_CHY_GPIO_AF GPIO_AF_TMR14
#define GTMR_TMRX_PWM_CHY_GPIO_CLK_ENABLE() \do { \RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOF); \} while (0)
通用定时器驱动中TMR14的初始化函数,如下所示:
/*** @brief 初始化通用定时器PWM输出* @note 当APB1PSC!=1时,定时器的时钟频率为APB1时钟的2倍* 因此定时器的时钟频率为84MHz* 定时器溢出时间计算方法:Tout = ((arr + 1) * (psc + 1)) / TMRxCLK* TMRxCLK=定时器时钟频率,单位MHz* @param arr: 自动重装载值* @param psc: 预分频器数值* @retval 无*/
void gtmr_tmrx_pwm_chy_init(uint16_t arr, uint16_t psc)
{GPIO_Config_T gpio_init_struct;TMR_BaseConfig_T tmr_init_struct;TMR_OCConfig_T tmr_oc_init_struct;/* 使能时钟 */GTMR_TMRX_PWM_CLK_ENABLE(); /* 使能通用定时器时钟 */GTMR_TMRX_PWM_CHY_GPIO_CLK_ENABLE(); /* 使能PWM输出引脚端口时钟 *//* 配置PWM输出引脚 */gpio_init_struct.pin = GTMR_TMRX_PWM_CHY_GPIO_PIN; /* PWM输出引脚 */gpio_init_struct.mode = GPIO_MODE_AF; /* 复用功能模式 */gpio_init_struct.speed = GPIO_SPEED_100MHz; /* 高速 */gpio_init_struct.otype = GPIO_OTYPE_PP; /* 推挽输出 */gpio_init_struct.pupd = GPIO_PUPD_DOWN; /* 下拉 *//* 配置PWM输出引脚 */GPIO_Config(GTMR_TMRX_PWM_CHY_GPIO_PORT, &gpio_init_struct);/* 配置引脚复用功能 */GPIO_ConfigPinAF( GTMR_TMRX_PWM_CHY_GPIO_PORT,GTMR_TMRX_PWM_CHY_GPIO_PIN_SOURCE,GTMR_TMRX_PWM_CHY_GPIO_AF);/* 配置通用定时器 */tmr_init_struct.countMode = TMR_COUNTER_MODE_UP; /* 向上计数 */tmr_init_struct.clockDivision = TMR_CLOCK_DIV_1; /* 时钟分频系数 */tmr_init_struct.period = arr; /* 自动重装载值 */tmr_init_struct.division = psc; /* 预分频器数值 */TMR_ConfigTimeBase(GTMR_TMRX_PWM, &tmr_init_struct); /* 配置通用定时器 *//* 配置输出比较通道 */tmr_oc_init_struct.mode = TMR_OC_MODE_PWM1; /* PWM模式1 */tmr_oc_init_struct.outputState = TMR_OC_STATE_DISABLE; /* 使能PWM输出 */tmr_oc_init_struct.polarity = TMR_OC_POLARITY_LOW; /* 低电平有效 */tmr_oc_init_struct.pulse = (arr + 1) >> 1; /* PWM有效电平脉宽 */TMR_ConfigOC1(GTMR_TMRX_PWM, &tmr_oc_init_struct); /* 配置输出比较通道1 *//* 使能通用定时器和PWM输出 */TMR_Enable(GTMR_TMRX_PWM); /* 使能通用定时器 */TMR_EnableCCxChannel(GTMR_TMRX_PWM, GTMR_TMRX_PWM_CHY);/* 使能输出比较通道输出 */
}
从TMR14的初始化代码中可以看到,不仅配置了TMR14的自动重装载值和预分频器数值等基本参数,还配置了TMR14的输出比较通道1,由于需要使用GPIO引脚输出PWM,因此对应的GPIO引脚也配置了复用功能。
18.2.3 实验应用代码
本章实验的应用代码,如下所示:
int main(void)
{uint32_t ledpwmval = 0;uint8_t dir = 1;NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_3); /* 设置中断优先级分组为组3 */sys_apm32_clock_init(336, 8, 2, 7); /* 配置系统时钟 */delay_init(168); /* 初始化延时功能 */usart_init(115200); /* 初始化串口 */gtmr_tmrx_pwm_chy_init(500 - 1, 84 - 1); /* 初始化通用定时器PWM输出 */while (1){delay_ms(10);/* 根据方向修改ledpwmval */if (dir == 1){ledpwmval++;}else{ledpwmval--;}/* 当ledpwmval大于300时,方向改为递减 */if (ledpwmval > 300){dir = 0;}/* 当ledpwmval等于0时,方向改为递增 */if (ledpwmval == 0){dir = 1;}/* 修改通用定时器输出占空比 */TMR_ConfigCompare1(GTMR_TMRX_PWM, ledpwmval);}
}
从上面的代码中可以看到,在初始化完TMR14输出PWM后,就不断地改变TMR14通道1的比较值,以达到改变PWM占空比,又因为PWM由PF9引脚输出,PF9引脚连接至LED0,因此LED0的亮度也将随之改变,实现呼吸灯的效果。
18.3 下载验证
在完成编译和烧录操作后,可以看到板子上的LED0先由暗慢慢变亮,再由亮慢慢变暗,依次循环,实现了呼吸灯的效果。
相关文章:

【正点原子STM32连载】第十八章 通用定时器PWM输出实验 摘自【正点原子】APM32F407最小系统板使用指南
1)实验平台:正点原子stm32f103战舰开发板V4 2)平台购买地址:https://detail.tmall.com/item.htm?id609294757420 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html# 第十…...

分类预测 | MATLAB实现BWO-TCN-Attention数据分类预测
分类预测 | MATLAB实现BWO-TCN-Attention数据分类预测 目录 分类预测 | MATLAB实现BWO-TCN-Attention数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.BWO-TCN-Attention数据分类预测程序; 2.无Attention适用于MATLAB 2022b版及以上版本…...
6.链路追踪-Zipkin
链路追踪(Distributed Tracing)是一种用于监视分布式应用程序的技术,通过收集和展示分布式系统中不同组件之间的调用和交互情况,帮助开发人员和运维团队理解系统中的请求流程、性能瓶颈和异常情况。 1.Zipkin Zipkin 是一个开源的…...

基于ACF,AMDF算法的语音编码matlab仿真
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .......................................................................... plotFlag …...

python 基础篇 day 1 初识变量和数据类型
文章目录 变量变量作用——用于存储和表示数据。变量命名规则命名法大驼峰小驼峰下划体n j i a x 通常作为临时变量使用 建议 变量种类全局变量(Global Variables)局部变量(Local Variables)静态变量(Static Variables…...

Window下部署使用Stable Diffusion AI开源项目绘图
Window下部署使用Stable Diffusion AI开源项目绘图 前言前提条件相关介绍Stable Diffusion AI绘图下载项目环境要求环境下载运行项目打开网址,即可体验文字生成图像(txt2img)庐山瀑布 参考 本文里面的风景图,均由Stable Diffusion…...

【MySQL】好好学习一下InnoDB中的页
文章目录 一. 前言二. 从宏观层面看页三. 页的基本内容3.1 页的数据结构3.2 用户空间内的数据行结构3.3 页目录 四. 问题集4.1 索引 和 数据页 有什么区别4.2 页的大小是什么决定的4.3 页的大小对哪些情况有影响4.4 一般情况下说的链表有哪几个4.5 如果页的空间满了怎么办4.6 如…...
git开发常用命令
版本回退 soft:git reset --soft HEAD^ 将版本库回退一个版本,且这次提交的所有文件都移动到暂存区 mixed(默认):git reset HEAD^ 将版本库回退一个版本,且这次提交的所有文件都移动到工作区,会…...

WEB APIs day5
一、window对象 BOM属于window对象 1.BOM(浏览器对象模型) bom里面包含着dom,只不过bom我们平时用得比较少,我们经常使用的是dom操作,因为我们页面中的这些标签都是在dom中取的,所以我们操作dom多一点。 window对象…...

html动态爱心代码【一】(附源码)
前言 七夕马上就要到了,为了帮助大家高效表白,下面再给大家带来了实用的HTML浪漫表白代码(附源码)背景音乐,可用于520,情人节,生日,表白等场景,可直接使用。 效果演示 文案修改 var loverNam…...

【仿写tomcat】六、解析xml文件配置端口、线程池核心参数
线程池改造 上一篇文章中我们用了Excutors创建了线程,这里我们将它改造成包含所有线程池核心参数的形式。 package com.tomcatServer.http;import java.util.concurrent.*;/*** 线程池跑龙套** author ez4sterben* date 2023/08/05*/ public class ThreadPool {pr…...

Android Studio 接入OpenCV最简单的例子 : 实现灰度图效果
1. 前言 上文 我们在Windows电脑上实现了人脸功能,接下来我们要把人脸识别的功能移植到Android上。 那么首先第一步,就是要创建一个Native的Android项目,并且配置好OpenGL,并能够调用成功。 这里我们使用的是openCV-4.8.0&#x…...
(1)、扩展SpringCache一站式解决缓存击穿,穿透,雪崩
1、问题描述 我们在使用SpringCache的@Cacheable注解时,发现并没有设置过期时间这个功能。 @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @I...

Rancher使用cert-manager安装报错解决
报错: rancher-rke-01:~/rke/rancher-helm/rancher # helm install rancher rancher-stable/rancher --namespace cattle-system --set hostnamewww.rancher.local Error: INSTALLATION FAILED: Internal error occurred: failed calling webhook "webhook…...

Harvard transformer NLP 模型 openNMT 简介入门
项目网址: OpenNMT - Open-Source Neural Machine Translation logo: 一,从应用的层面先跑通 Harvard transformer GitHub - harvardnlp/annotated-transformer: An annotated implementation of the Transformer paper. git clone https…...

【数据结构OJ题】用栈实现队列
原题链接:https://leetcode.cn/problems/implement-queue-using-stacks/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 用两个栈实现,一个栈进行入队操作,另一个栈进行出队操作。 出队操作: 当出队的栈…...

通达信指标公式15:除权除息数据统计分析
#1.关于除权除息指标的介绍:本指标是小红牛原创指标之一,觉得有必要研究一下这个问题,所以就花时间整理一下这个指标相关内容,大家可以在本源码基础上,进一步优化自己的思路。本指标为通达信幅图指标,可以做…...

day-27 代码随想录算法训练营(19)回溯part03
39.组合总和 分析:同一个数可以选多次,但是不能有重复的答案; 思路:横向遍历,纵向递归(不同的是递归的时候不需要跳到下一个位置,因为同一个数可以选多次) class Solution { publ…...
CSDN编程题-每日一练(2023-08-22)
CSDN编程题-每日一练(2023-08-22) 一、题目名称:最长递增区间二、题目名称:K树三、题目名称:小Q的价值无向图一、题目名称:最长递增区间 时间限制:1000ms内存限制:256M 题目描述: 给一个无序数组,求最长递增的区间长度。如:[5,2,3,8,1,9] 最长区间 2,3,8 长度为 3。…...

使用 KubeBlocks 为 K8s 提供稳如老狗的数据库服务
原文链接:https://forum.laf.run/d/994 大家好!今天这篇文章主要向大家介绍 Sealos 的数据库服务。在 Sealos 上数据库后端服务由 KubeBlocks 提供,为用户的数据库应用保驾护航。无论你是在公有云还是本地环境中使用,Sealos 都能为…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...

内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献
Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译: ### 胃肠道癌症的发病率呈上升趋势,且有年轻化倾向(Bray等人,2018&#x…...
Linux中INADDR_ANY详解
在Linux网络编程中,INADDR_ANY 是一个特殊的IPv4地址常量(定义在 <netinet/in.h> 头文件中),用于表示绑定到所有可用网络接口的地址。它是服务器程序中的常见用法,允许套接字监听所有本地IP地址上的连接请求。 关…...