【正点原子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 都能为…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...
《Docker》架构
文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...
Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
