Renesas R7FA8D1BH (Cortex®-M85)的 General PWM的应用实践

embedded/2025/1/17 17:37:57/

目录

概述

1  General PWM介绍

1.1 特性

1.2 定时器选择注意点

2 时钟配置

3 应用案例

3.1 基本定时器应用

3.2 定时器回调函数案例

3.3 输入捕捉功能案例

3.4 更新周期案例

3.5 更新占空比案例

3.6 单次触发脉冲案例

4 测试

4.1 代码介绍

4.2 验证


概述

本文主要介绍Renesas R7FA8D1BH (Cortex®-M85)的 General PWM各种模式的使用方法,包括PWM的特性介绍,并编写多个案例,详细介绍了各种模式下API函数的使用方法,还编写一个具体的案例,实现PWM的输出,并使用逻辑分析仪捕捉器波形。

1  General PWM介绍

1.1 特性

GPT模块可用于计数事件,测量外部输入信号,产生周期性中断,或输出周期性或PWM信号到GTIOC引脚。该模块支持GPT外设GPT32EH、GPT32E、GPT32和GPT16。GPT16是一个16位定时器。其他外设(GPT32EH、GPT32E和GPT32)是32位定时器。从API的角度来看,这个模块中的32位计时器都是一样的。

GPT模块具有以下特点:

1)支持周期模式、单次模式和PWM模式。
2)支持计数源的PCLK, gtegg引脚,GTIOC引脚,或ELC事件。
3)支持GTIOC引脚上的脱波滤波器。
4)信号可以输出到一个引脚。
5)可配置周期(每个计时器周期的计数)。
6)可配置占空比PWM模式。
7)支持运行时周期的重新配置。
8)支持在PWM模式下运行时重构占空比。
9)支持运行时比较匹配值的重新配置。
10)提供了用于启动、停止和重置计数器的api。
11)提供api来获取当前周期、源时钟频率和计数方向。
12)提供api来获取当前定时器状态和计数器值。
13)支持启动、停止、清除、向上计数、向下计数,并通过外部源从gtegg引脚、GTIOC引脚或ELC事件捕获。
14)支持对称和非对称PWM波形生成。
15)支持一次同步脉冲波形生成。
16)支持自动添加死区时间。
17)支持生成ELC事件,以比较匹配值启动ADC扫描(参见事件链接控制器(r_elc))并更新比较匹配值。
18)支持与POEG通道连接,当检测到错误条件时自动禁用GPT输出。
19)支持定时器停止时设置计数器值。
20)支持启用和禁用输出引脚。
21)支持一次跳过最多七个溢出/下流(波峰/波谷)中断
22)支持通过配置引脚的输出电平在每个比较匹配和周期结束产生自定义PWM波形。

1.2 定时器选择注意点

RA mcu有两个定时器外设:通用PWM定时器(GPT)和异步通用定时器(AGT)。在他们之间进行选择时,要考虑以下因素:

GPTAGT
Low Power ModesThe GPT can operate in sleep mode.The AGT can operate in all low power modes.
Available ChannelsThe number of GPT channels is device specific. All currently supported MCUs have at least 7 GPT channels.All MCUs have 2 AGT channels.
Timer ResolutionAll MCUs have at least one 32-bit GPT timer.The AGT timers are 16-bit timers.
Clock SourceThe GPT runs off PCLKD with a configurable divider up to 1024. It can also be configured to count ELC events or external pulses.The AGT runs off PCLKB, LOCO, or subclock.

2 时钟配置

GPT时钟基于PCLKD频率。您可以使用RA Configuration编辑器的Clocks选项卡或在运行时使用CGC接口来设置PCLKD频率。

该模块可以使用GTETRGA、GTETRGB、GTETRGC、GTETRGD、GTIOCA和GTIOCB引脚作为计数源。该模块可以使用GTIOCA和GTIOCB引脚作为周期性或PWM信号的输出引脚。该模块可以使用GTIOCA和GTIOCB作为输入引脚来测量输入信号。

3 应用案例

3.1 基本定时器应用

这是在应用程序中最少使用GPT的一个基本示例。

void gpt_basic_example (void)
{fsp_err_t err = FSP_SUCCESS;/* Initializes the module. */err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);/* Handle any errors. This function should be defined by the user. */assert(FSP_SUCCESS == err);/* Start the timer. */(void) R_GPT_Start(&g_timer0_ctrl);
}

3.2 定时器回调函数案例

定时器回调函数的应用案例,范例代码如下:

/* Example callback called when timer expires. */
void timer_callback (timer_callback_args_t * p_args)
{if (TIMER_EVENT_CYCLE_END == p_args->event){/* Add application code to be called periodically here. */}
}

3.3 输入捕捉功能案例

这是一个使用GPT捕获脉冲宽度或脉冲周期测量的例子。

/* Example callback called when a capture occurs. */
uint64_t g_captured_time     = 0U;
uint32_t g_capture_overflows = 0U;
void timer_capture_callback (timer_callback_args_t * p_args)
{if ((TIMER_EVENT_CAPTURE_A == p_args->event) || (TIMER_EVENT_CAPTURE_B == p_args->event)){/* (Optional) Get the current period if not known. */timer_info_t info;(void) R_GPT_InfoGet(&g_timer0_ctrl, &info);uint64_t period = info.period_counts;/* The maximum period is one more than the maximum 32-bit number, but will be reflected as 0 in* timer_info_t::period_counts. */if (0U == period){period = UINT32_MAX + 1U;}g_captured_time     = (period * g_capture_overflows) + p_args->capture;g_capture_overflows = 0U;}if (TIMER_EVENT_CYCLE_END == p_args->event){/* An overflow occurred during capture. This must be accounted for at the application layer. */g_capture_overflows++;}
}
void gpt_capture_example (void)
{fsp_err_t err = FSP_SUCCESS;/* Initializes the module. */err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);/* Handle any errors. This function should be defined by the user. */assert(FSP_SUCCESS == err);/* Enable captures. Captured values arrive in the interrupt. */(void) R_GPT_Enable(&g_timer0_ctrl);/* (Optional) Disable captures. */(void) R_GPT_Disable(&g_timer0_ctrl);
}

3.4 更新周期案例

#define GPT_EXAMPLE_MSEC_PER_SEC           (1000)
#define GPT_EXAMPLE_DESIRED_PERIOD_MSEC    (20)
/* This example shows how to calculate a new period value at runtime. */
void gpt_period_calculation_example (void)
{fsp_err_t err = FSP_SUCCESS;/* Initializes the module. */err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);/* Handle any errors. This function should be defined by the user. */assert(FSP_SUCCESS == err);/* Start the timer. */(void) R_GPT_Start(&g_timer0_ctrl);/* Get the source clock frequency (in Hz). There are 3 ways to do this in FSP:*  - If the PCLKD frequency has not changed since reset, the source clock frequency is*    BSP_STARTUP_PCLKD_HZ >> timer_cfg_t::source_div*  - Use the R_GPT_InfoGet function (it accounts for the divider).*  - Calculate the current PCLKD frequency using R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKD) and right shift*    by timer_cfg_t::source_div.** This example uses the 3rd option (R_FSP_SystemClockHzGet).*/uint32_t pclkd_freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKD) >> g_timer0_cfg.source_div;/* Calculate the desired period based on the current clock. Note that this calculation could overflow if the* desired period is larger than UINT32_MAX / pclkd_freq_hz. A cast to uint64_t is used to prevent this. */uint32_t period_counts =(uint32_t) (((uint64_t) pclkd_freq_hz * GPT_EXAMPLE_DESIRED_PERIOD_MSEC) / GPT_EXAMPLE_MSEC_PER_SEC);/* Set the calculated period. */err = R_GPT_PeriodSet(&g_timer0_ctrl, period_counts);assert(FSP_SUCCESS == err);
}

3.5 更新占空比案例


#define GPT_EXAMPLE_DESIRED_DUTY_CYCLE_PERCENT    (25)
#define GPT_EXAMPLE_MAX_PERCENT                   (100)
/* This example shows how to calculate a new duty cycle value at runtime. */
void gpt_duty_cycle_calculation_example (void)
{fsp_err_t err = FSP_SUCCESS;/* Initializes the module. */err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);/* Handle any errors. This function should be defined by the user. */assert(FSP_SUCCESS == err);/* Start the timer. */(void) R_GPT_Start(&g_timer0_ctrl);/* Get the current period setting. */timer_info_t info;(void) R_GPT_InfoGet(&g_timer0_ctrl, &info);uint32_t current_period_counts = info.period_counts;/* Calculate the desired duty cycle based on the current period. Note that if the period could be larger than* UINT32_MAX / 100, this calculation could overflow. A cast to uint64_t is used to prevent this. The cast is* not required for 16-bit timers. */uint32_t duty_cycle_counts =(uint32_t) (((uint64_t) current_period_counts * GPT_EXAMPLE_DESIRED_DUTY_CYCLE_PERCENT) /GPT_EXAMPLE_MAX_PERCENT);/* Set the calculated duty cycle. */err = R_GPT_DutyCycleSet(&g_timer0_ctrl, duty_cycle_counts, GPT_IO_PIN_GTIOCB);assert(FSP_SUCCESS == err);
}

3.6 单次触发脉冲案例

/* Example callback called when timer overflows. */
void gpt_overflow_callback (timer_callback_args_t * p_args)
{if (TIMER_EVENT_CYCLE_END == p_args->event){/* Use R_GPT_DutyCycleSet() API to set new values for each cycle.* - Use GPT_IO_PIN_ONE_SHOT_LEADING_EDGE to set the leading edge transition match value (GTCCRC or GTCCRE register).* - Use GPT_IO_PIN_ONE_SHOT_TRAILING_EDGE to set the trailing edge transition match value (GTCCRD or GTCCRF register).*/}
}
#define GPT_ONE_SHOT_EXAMPLE_DUTY_CYCLE_GTCCRD_GTCCRF    (0x1000U)
#define GPT_ONE_SHOT_EXAMPLE_DUTY_CYCLE_GTCCRC           (0x800U)
#define GPT_ONE_SHOT_EXAMPLE_DUTY_CYCLE_GTCCRE           (0x100U)
void gpt_one_shot_pulse_mode_example (void)
{fsp_err_t err = FSP_SUCCESS;/* Initializes the module. */err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);/* Handle any errors. This function should be defined by the user. */assert(FSP_SUCCESS == err);/* Set the duty cycle for One-Shot-Pulse mode *//* GPT_IO_PIN_ONE_SHOT_LEADING_EDGE sets the initial value for the GTCCRC register if GTIOCnA is the selected pin for output. */err = R_GPT_DutyCycleSet(&g_timer0_ctrl,GPT_ONE_SHOT_EXAMPLE_DUTY_CYCLE_GTCCRC,GPT_IO_PIN_GTIOCA | GPT_IO_PIN_ONE_SHOT_LEADING_EDGE);assert(FSP_SUCCESS == err);/* GPT_IO_PIN_ONE_SHOT_LEADING_EDGE sets the initial value for the GTCCRE register if GTIOCnB is the selected pin for output. */err = R_GPT_DutyCycleSet(&g_timer0_ctrl,GPT_ONE_SHOT_EXAMPLE_DUTY_CYCLE_GTCCRE,GPT_IO_PIN_GTIOCB | GPT_IO_PIN_ONE_SHOT_LEADING_EDGE);assert(FSP_SUCCESS == err);/* GPT_IO_PIN_ONE_SHOT_TRAILING_EDGE sets the initial value for the GTCCRD register if GTIOCnA is the selected pin for output. */err = R_GPT_DutyCycleSet(&g_timer0_ctrl,GPT_ONE_SHOT_EXAMPLE_DUTY_CYCLE_GTCCRD_GTCCRF,GPT_IO_PIN_GTIOCA | GPT_IO_PIN_ONE_SHOT_TRAILING_EDGE);assert(FSP_SUCCESS == err);/* GPT_IO_PIN_ONE_SHOT_TRAILING_EDGE sets the initial value for the GTCCRF register if GTIOCnB is the selected pin for output.* GPT_BUFFER_FORCE_PUSH pushes set values to temporary registers to prepare for the initial output cycle. This must be done* when setting the duty cycle before starting the timer. */err = R_GPT_DutyCycleSet(&g_timer0_ctrl,GPT_ONE_SHOT_EXAMPLE_DUTY_CYCLE_GTCCRD_GTCCRF,GPT_IO_PIN_GTIOCB | GPT_IO_PIN_ONE_SHOT_TRAILING_EDGE | GPT_BUFFER_FORCE_PUSH);assert(FSP_SUCCESS == err);/* Start the timer. */(void) R_GPT_Start(&g_timer0_ctrl);/* (Optional) Stop the timer. */(void) R_GPT_Stop(&g_timer0_ctrl);
}
GPT Compare Match Set Example
This example demonstrates the configuration and use of compare match with GPT timer./* Example callback called when compare match occurs. */
void gpt_compare_match_callback (timer_callback_args_t * p_args)
{if (TIMER_EVENT_COMPARE_A == p_args->event){/* Add application code to be called periodically here. */}
}
#define GPT_COMPARE_MATCH_EXAMPLE_VALUE    (0x2000U)
void gpt_compare_match_set_example (void)
{fsp_err_t err = FSP_SUCCESS;/* Initializes the module. */err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);/* Handle any errors. This function should be defined by the user. */assert(FSP_SUCCESS == err);/* Set the compare match value (GPT_COMPARE_MATCH_EXAMPLE_VALUE). This value must be less than or equal to period value. */err = R_GPT_CompareMatchSet(&g_timer0_ctrl, GPT_COMPARE_MATCH_EXAMPLE_VALUE, TIMER_COMPARE_MATCH_A);assert(FSP_SUCCESS == err);/* Start the timer. */(void) R_GPT_Start(&g_timer0_ctrl);/* (Optional) Stop the timer. */(void) R_GPT_Stop(&g_timer0_ctrl);
}

4 测试

4.1 代码介绍

编写一个Demo实现4路PWM信号输出,其详细代码如下:

 /*FILE NAME  :  bsp_pwm.cDescription:  pwm interfaceAuthor     :  tangmingfei2013@126.comDate       :  2024/06/03*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include "bsp_pwm.h"
#include "hal_data.h"void GPT_PWM_SetDuty3(uint8_t duty, uint32_t pin);
void GPT_PWM_SetDuty2(uint8_t duty, uint32_t pin);
void GPT_PWM_SetDuty1(uint8_t duty, uint32_t pin);void pwm_init( void )
{// timer 1   GPT_IO_PIN_GTIOCAR_GPT_Open(&g_timer1_ctrl, &g_timer1_cfg);R_GPT_Start(&g_timer1_ctrl);/* Set the calculated duty cycle. */GPT_PWM_SetDuty1(60, GPT_IO_PIN_GTIOCA);// timer 2   GPT_IO_PIN_GTIOCBR_GPT_Open(&g_timer2_ctrl, &g_timer2_cfg);R_GPT_Start(&g_timer2_ctrl);// set duty GPT_PWM_SetDuty2(80, GPT_IO_PIN_GTIOCB); // timer 6   GPT_IO_PIN_GTIOCA & GPT_IO_PIN_GTIOCBR_GPT_Open(&g_timer3_ctrl, &g_timer3_cfg);R_GPT_Start(&g_timer3_ctrl);// set duty GPT_PWM_SetDuty3( 50, GPT_IO_PIN_GTIOCA);// set duty GPT_PWM_SetDuty3( 20, GPT_IO_PIN_GTIOCB);
}void GPT_PWM_SetDuty3(uint8_t duty, uint32_t pin)
{fsp_err_t  err;timer_info_t info;uint32_t current_period_counts;uint32_t duty_cycle_counts;if (duty > 100)duty = 100; R_GPT_InfoGet(&g_timer3_ctrl, &info);current_period_counts = info.period_counts;duty_cycle_counts = (uint32_t)(((uint64_t) current_period_counts * duty) / 100);err = R_GPT_DutyCycleSet(&g_timer3_ctrl, duty_cycle_counts, pin);assert(FSP_SUCCESS == err);
}void GPT_PWM_SetDuty2(uint8_t duty, uint32_t pin)
{fsp_err_t  err;timer_info_t info;uint32_t current_period_counts;uint32_t duty_cycle_counts;if (duty > 100)duty = 100; R_GPT_InfoGet(&g_timer2_ctrl, &info);current_period_counts = info.period_counts;duty_cycle_counts = (uint32_t)(((uint64_t) current_period_counts * duty) / 100);err = R_GPT_DutyCycleSet(&g_timer2_ctrl, duty_cycle_counts, pin);assert(FSP_SUCCESS == err);
}void GPT_PWM_SetDuty1(uint8_t duty, uint32_t pin)
{fsp_err_t  err;timer_info_t info;uint32_t current_period_counts;uint32_t duty_cycle_counts;if (duty > 100)duty = 100; R_GPT_InfoGet(&g_timer1_ctrl, &info);current_period_counts = info.period_counts;duty_cycle_counts = (uint32_t)(((uint64_t) current_period_counts * duty) / 100);err = R_GPT_DutyCycleSet(&g_timer1_ctrl, duty_cycle_counts, pin);assert(FSP_SUCCESS == err);
}/* End of this file */

4.2 验证

编译和下载代码到板卡中,运行结果如下:


http://www.ppmy.cn/embedded/115494.html

相关文章

网络工程师学习笔记——网络互连与互联网(二)

IP地址 是电脑在互联网上进行进行通信的“身份证” 是网络号主机号 网络号代表所处的网段&#xff0c;而主机号则代表电脑 ipv4有232个ip地址大约43亿 其中又分为A、B、C、D、E类地址 A&#xff1a;1.0.0.0~127.255.255.255&#xff08;首位0&#xff09; B&#xff1a;1…

招联金融2025秋招--大量招后台、算法

【投递方式】 直接扫下方二维码&#xff0c;或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus&#xff0c;使用内推码 igcefb 投递 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策划 产品运营…

6.7泊松噪声

基础概念 在OpenCV联合C中给一张图片添加泊松噪声&#xff08;Poisson Noise&#xff09;可以通过生成随机数并在图像的每个像素上加上这些随机数来实现。泊松噪声是一种统计分布服从泊松分布的噪声&#xff0c;通常用于模拟光子计数等场景。 使用泊松噪声的场景 泊松噪声通…

「C++系列」动态内存

【人工智能教程】&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。 点击跳转到网站&#xff1a;【人工智能教程】 文章目录 一、动态内存1. 使用new和delete①分配单个对象②分配对象数组 2. …

Android 车载应用开发指南 - CarService 详解(下)

车载应用正在改变人们的出行体验。从导航到娱乐、从安全到信息服务&#xff0c;车载应用的开发已成为汽车智能化发展的重要组成部分。而对于开发者来说&#xff0c;如何将自己的应用程序无缝集成到车载系统中&#xff0c;利用汽车的硬件和服务能力&#xff0c;是一个极具挑战性…

Rocky Linux 9 中添加或删除某个网卡的静态路由的方法

使用ip命令配置临时路由 添加静态路由 ip route add <目的网络> via <下一跳IP> dev <网卡接口名称>例: 给eth0网卡添加一个到达 192.168.2.0/24 网络&#xff0c;下一跳为 192.168.1.254 的路由 ip route add 192.168.2.0/24 via 192.168.1.254 dev eth0…

STM32 单片机最小系统全解析

STM32 单片机最小系统全解析 本文详细介绍了 STM32 单片机最小系统&#xff0c;包括其各个组成部分及设计要点与注意事项。STM32 最小系统在嵌入式开发中至关重要&#xff0c;由电源、时钟、复位、调试接口和启动电路等组成。 在电源电路方面&#xff0c;采用 3.3V 直流电源供…

医院信息化运维监控:确保医疗系统的稳定与安全

在当今数字化时代&#xff0c;医院的信息化水平直接关系到医疗服务的效率和质量。随着医疗信息化的不断推进&#xff0c;医院对信息化运维监控的需求也日益增强。特别是IT软硬件资源监控和机房动环监控&#xff0c;它们在保障医院信息系统稳定运行中发挥着至关重要的作用。 首先…