【正点原子STM32连载】第十八章 通用定时器PWM输出实验 摘自【正点原子】APM32F407最小系统板使用指南

news2024/12/23 9:46:08

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 例程功能

  1. LED0由暗变亮,再从亮变暗,依次循环
    18.1.2 硬件资源
  2. LED
    LED0 - PF9
  3. 定时器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先由暗慢慢变亮,再由亮慢慢变暗,依次循环,实现了呼吸灯的效果。

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

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

相关文章

【附安装包】Solid Edge2023安装教程最强CAD选择

软件下载 软件:Solid Edge版本:2023语言:简体中文大小:3.85G安装环境:Win11/Win10/Win8/Win7硬件要求:CPU2.0GHz 内存4G(或更高)下载通道①百度网盘丨64位下载链接:https://pan.bai…

Python 如何复制列表,高效复制列表,列表复制效率对比,copy 与 deepcopy 差距对比

背景 在python中,避免不了经常使用 list 类型的变量,list 变量的复制也是经常遇到的需求,那么如何高效的复制一个 list呢? 代码 下面代码给出了 4 种不同的list复现方法,观察其代码效率: # -*- coding:…

Vue3 中引入液晶数字字体(通常用于大屏设计)

一、下载 .ttf 字体文件到本地,放在 src 中的 assets 文件下 下载液晶字体 DS-Digital.ttf 二、在 css 文件中引入字体 /* src/assets/fonts/dsfont.css */ font-face {font-family: electronicFont;src: url(./DS-Digital.ttf);font-weight: normal;font-styl…

CS144 计算机网络 Lab2:TCP Receiver

前言 Lab1 中我们使用双端队列实现了字节流重组器,可以将无序到达的数据重组为有序的字节流。Lab2 将在此基础上实现 TCP Receiver,在收到报文段之后将数据写入重组器中,并回复发送方。 实验要求 TCP 接收方除了将收到的数据写入重组器中外…

记录:ubuntu20.04+ORB_SLAM2_with_pointcloud_map+ROS noetic

由于相机实时在线运行需要ROS,但Ubuntu22.04只支持ROS2,于是重装Ubuntu20.04。上一篇文章跑通的是官方版本的ORB_SLAM2,不支持点云显示。高翔修改版本支持RGB-D相机的点云显示功能。 高翔修改版本ORB_SLAM2:https://github.com/ga…

vue中css修改滚动条样式

vue中css修改滚动条样式 效果图: 代码(在app.vue中全局增加下面样式即可): &::-webkit-scrollbar {width: 8px;height: 8px;border-radius: 3px;}/*定义滚动条轨道 内阴影圆角*/&::-webkit-scrollbar-track {//-webkit-box-shadow: inset 0 0 …

服务器的介绍

1.服务器概述 1.1 服务器的基本概念 服务器是计算机的一种,是网络中为客户端计算机提供各种服务的高性能计算机; 服务器在网络操作系统的控制下,将与其相连的硬盘、磁带、 打印机及昂贵的专用通讯设备提供给网络上的客户站点共享&#xf…

HTML动态爱心特效代码【一】(附源码)

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

2023七夕小程序

又是一年七夕节 往年七夕小程序 2020 https://blog.csdn.net/chen_227/article/details/107062998 2022 视频 QiXi2022 代码 https://gitee.com/chen227/qixi2022-qt-qml 2023 效果 代码 https://gitee.com/chen227/qixi2023-qt-qml

ICC2工具如何避免对mux选择信号端口进行检查

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?拾陆楼知识星球入口 time.clock_gating_user_seeting_only这个option设置成false,导致对选择器的S端进行了时序分析,进而可能出现违例。 设置成true即可。

cuda面试准备(一),架构调试

1 cuda架构 硬件方面 SP (streaming Process) ,SM (streaming multiprocessor) 是硬件(GPUhardware) 概念。而thread,block,grid,warp是软件上的(CUDA) 概念 SP:最基本的处理单元,streaming processor,也称为CUDA core,最后具体的指令和任务都是在SP上处理的。GPU进行并行…

QT中按钮的基类QAbstractButton

QT中按钮的基类QAbstractButton 关于控件类的学习方法继承关系信号槽函数标题和图标按钮的 Check 属性 关于控件类的学习方法 控件类很多,API更多,但是不需要记忆知道控件对应的类名,通过帮助文档随用随查优先看帮助文档中控件对应的信号和槽…

速通蓝桥杯嵌入式省一教程:(八)ADC测量模拟电压

ADC(Analog to Digital Converter),模拟数字转换器,是电子工程师必须掌握的一个内容。由于单片机、计算机等是由0和1组成的,因此其无法直接测量或使用连续的模拟信号,需要用ADC将模拟信号转换为离散的数字信号。ADC的具体原理在此…

AM62x GPMC并口如何实现“小数据-低时延,大数据-高带宽”—ARM+FPGA低成本通信方案

GPMC并口简介 GPMC(General Purpose Memory Controller)是TI处理器特有的通用存储器控制器接口,支持8/16bit数据位宽,支持128MB访问空间,最高时钟速率133MHz。GPMC是AM62x、AM64x、AM437x、AM335x、AM57x等处理器专用于与外部存储器设备的接口…

SpringCloud之Stream3.0广播消息

SpringCloud之Stream消息驱动RocketMQ讲解_rocketmq stream_爱吃牛肉的大老虎的博客-CSDN博客3.0使用的函数式消费,如果使用广播消费,就是配置2个group,destination和生产者保持一致即可 spring.cloud.stream:bindings:testData-in-0:destin…

【3Ds Max】可编辑多边形“边”层级的简单使用

目录 简介 示例 1. 编辑边 (1)插入顶点 (2)移除 (3)分割 (4)挤出 (5)切角 (6)焊接 (7)桥 &…

一阶线性微分方程

形如: y ′ p ( x ) y q ( x ) (1.first) y p(x)y q(x) \tag{1.first} y′p(x)yq(x)(1.first) 的方程叫做一阶线性微分方程。 同济版教材的求解方法是常数变异法,初次接触感觉主编的脑回路异常清奇,自己怎么也get不到核心要义。一直到现…

隧道HTTP具备的条件

作为一名专业的爬虫代理供应商,我们都知道使用代理是保证爬虫的高效性和稳定性的重要手段之一。而隧道代理则是近年来备受推崇的一种代理形式,它通过将请求通过隧道传输,可以有效地隐藏爬虫的真实IP地址,提高爬虫的反爬能力。 在…

【中危】 Apache NiFi 连接 URL 验证绕过漏洞 (CVE-2023-40037)

漏洞描述 Apache NiFi 是一个开源的数据流处理和自动化工具。 在受影响版本中,由于多个Processors和Controller Services在配置JDBC和JNDI JMS连接时对URL参数过滤不完全。使用startsWith方法过滤用户输入URL,导致过滤可以被绕过。攻击者可以通过构造特…

【面试】项目经理面试题

文章目录 一、项目管理面试中通常会问到的问题1.项目管理软件工具知识2.做项目计划的技能3.人员管理技能4.沟通技巧5.方法论知识 二、问面试官的问题三. 面试系列推荐 一、项目管理面试中通常会问到的问题 1.项目管理软件工具知识 问题 1: 工期和工作量之间的差异是什么? 答案…