e2studio开发RA2E1(9)----定时器GPT配置输入捕获

news2025/2/8 22:34:17

e2studio开发RA2E1.9--定时器GPT配置输入捕获

  • 概述
  • 视频教学
  • 样品申请
  • 硬件准备
  • 参考程序
  • 源码下载
  • 选择计时器
  • 时钟源
  • UART配置
  • UART属性配置
  • 设置e2studio堆栈
  • e2studio的重定向printf设置
  • R_SCI_UART_Open()函数原型
  • 回调函数user_uart_callback ()
  • printf输出重定向到串口
  • 定时器输入捕获配置
  • 占空比与频率计算
  • 回调函数gpt5_callback
  • 主程序
  • 演示

概述

本文将探讨如何在 Renesas RA 系列微控制器上使用 GPT(通用定时器)模块来配置输入捕获功能。输入捕获是定时器的一项重要功能,它允许我们捕获外部信号(如脉冲或波形)的时间戳,广泛应用于频率计数、脉冲宽度测量以及其他需要精确时间记录的应用。

最近在瑞萨RA的课程,需要样片的可以加qun申请:925643491。

在这里插入图片描述

视频教学

https://www.bilibili.com/video/BV1QrP1ejEAZ/

e2studio开发RA2E1(9)----定时器GPT配置输入捕获

样品申请

https://www.wjx.top/vm/rCrkUrz.aspx

硬件准备

首先需要准备一个开发板,这里我准备的是自己绘制的开发板,需要的可以进行申请。
主控为R7FA2E1A72DFL#AA0

在这里插入图片描述

参考程序

https://github.com/CoreMaker-lab/RA2E1

https://gitee.com/CoreMaker/RA2E1

源码下载

选择计时器

RA MCU 有两个定时器外设:通用 PWM 定时器 (GPT) 和异步通用定时器 (AGT)。

在这里插入图片描述

时钟源

GPT 使用 PCLKD(外设时钟D) 作为主时钟源。该时钟可以通过 可配置的分频器 进行调整,最大分频因子为 1024。

在这里插入图片描述

选择 XTAL 12MHz 作为时钟源(Clock Src: XTAL)。PCLKD 时钟的分频器设置为 Div /1,意味着 PCLKD 直接运行在 12MHz。
在这里插入图片描述

UART配置

在这里插入图片描述

点击Stacks->New Stack->Connectivity -> UART(r_sci_uart)。

在这里插入图片描述

UART属性配置

在这里插入图片描述

设置e2studio堆栈

printf函数通常需要设置堆栈大小。这是因为printf函数在运行时需要使用栈空间来存储临时变量和函数调用信息。如果堆栈大小不足,可能会导致程序崩溃或不可预期的行为。
printf函数使用了可变参数列表,它会在调用时使用栈来存储参数,在函数调用结束时再清除参数,这需要足够的栈空间。另外printf也会使用一些临时变量,如果栈空间不足,会导致程序崩溃。
因此,为了避免这类问题,应该根据程序的需求来合理设置堆栈大小。

在这里插入图片描述

e2studio的重定向printf设置

在这里插入图片描述

在嵌入式系统的开发中,尤其是在使用GNU编译器集合(GCC)时,–specs 参数用于指定链接时使用的系统规格(specs)文件。这些规格文件控制了编译器和链接器的行为,尤其是关于系统库和启动代码的链接。–specs=rdimon.specs 和 --specs=nosys.specs 是两种常见的规格文件,它们用于不同的场景。
–specs=rdimon.specs
用途: 这个选项用于链接“Redlib”库,这是为裸机(bare-metal)和半主机(semihosting)环境设计的C库的一个变体。半主机环境是一种特殊的运行模式,允许嵌入式程序通过宿主机(如开发PC)的调试器进行输入输出操作。
应用场景: 当你需要在没有完整操作系统的环境中运行程序,但同时需要使用调试器来处理输入输出(例如打印到宿主机的终端),这个选项非常有用。
特点: 它提供了一些基本的系统调用,通过调试接口与宿主机通信。
–specs=nosys.specs
用途: 这个选项链接了一个非常基本的系统库,这个库不提供任何系统服务的实现。
应用场景: 适用于完全的裸机程序,其中程序不执行任何操作系统调用,比如不进行文件操作或者系统级输入输出。
特点: 这是一个更“裸”的环境,没有任何操作系统支持。使用这个规格文件,程序不期望有操作系统层面的任何支持。
如果你的程序需要与宿主机进行交互(如在开发期间的调试),并且通过调试器进行基本的输入输出操作,则使用 --specs=rdimon.specs。
如果你的程序是完全独立的,不需要任何形式的操作系统服务,包括不进行任何系统级的输入输出,则使用 --specs=nosys.specs。

在这里插入图片描述

R_SCI_UART_Open()函数原型

在这里插入图片描述

故可以用 R_SCI_UART_Open()函数进行配置,开启和初始化UART。

    /* Open the transfer instance with initial configuration. */
    err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
    assert(FSP_SUCCESS == err);

回调函数user_uart_callback ()

当数据发送的时候,可以查看UART_EVENT_TX_COMPLETE来判断是否发送完毕。

在这里插入图片描述

在这里插入图片描述

可以检查检查 “p_args” 结构体中的 “event” 字段的值是否等于 “UART_EVENT_TX_COMPLETE”。如果条件为真,那么 if 语句后面的代码块将会执行。

fsp_err_t err = FSP_SUCCESS;
volatile bool uart_send_complete_flag = false;
void user_uart_callback (uart_callback_args_t * p_args)
{
    if(p_args->event == UART_EVENT_TX_COMPLETE)
    {
        uart_send_complete_flag = true;
    }
}

printf输出重定向到串口

打印最常用的方法是printf,所以要解决的问题是将printf的输出重定向到串口,然后通过串口将数据发送出去。
注意一定要加上头文件#include <stdio.h>

#ifdef __GNUC__                                 //串口重定向
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif


PUTCHAR_PROTOTYPE
{
        err = R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
        if(FSP_SUCCESS != err) __BKPT();
        while(uart_send_complete_flag == false){}
        uart_send_complete_flag = false;
        return ch;
}

int _write(int fd,char *pBuffer,int size)
{
    for(int i=0;i<size;i++)
    {
        __io_putchar(*pBuffer++);
    }
    return size;
}

定时器输入捕获配置

操作 “New Stack > Timers >Timer, General PWM (r_gpt)” 在项目中添加GPT定时器。

在这里插入图片描述

这里设置P102进行捕获PWM。

在这里插入图片描述

● Pin Output Support:设为 Enabled,允许 PWM 信号输出到外部引脚。
● Name:设置为 g_timer5,这是模块的唯一标识符,用于代码中引用此定时器实例。
● Channel:设定为 5,表示该定时器使用通道 5 进行计数和控制。
● Mode:设为 Periodic,表示该定时器工作在周期模式,将在设定周期内重复运行。
● Period:周期值设置为 0x10000,表示定时器的周期为 65536 个时钟周期。根据时钟源频率的不同,实际的周期时间可以转换为相应的实际时间。
● Period Unit:单位选择为 Raw Counts,表示周期单位为原始计数,即计数器溢出的周期。
● Capture B Source:设为 GPT5 CAPTURE COMPARE B,表示捕获源为 GPT5 定时器的比较匹配B事件,用于捕获输入信号的时间戳。
● GTIOCB Rising Edge While GTIOCA Low:表示当 GTIOCA 为低电平时,捕获 GTIOCB 引脚的上升沿事件。
● GTIOCB Rising Edge While GTIOCA High:表示当 GTIOCA 为高电平时,捕获 GTIOCB 引脚的上升沿事件。
● GTIOCB Falling Edge While GTIOCA Low:表示当 GTIOCA 为低电平时,捕获 GTIOCB 引脚的下降沿事件。
● GTIOCB Falling Edge While GTIOCA High:表示当 GTIOCA 为高电平时,捕获 GTIOCB 引脚的下降沿事件。

在这里插入图片描述

● Callback:设置为 gpt5_callback,指定了当定时器触发中断时,调用的回调函数。在此情况下,回调函数 gpt5_callback 将在捕获事件发生时执行。
● Capture/Compare match B Interrupt Priority:设置为 Priority 2,表示启用比较匹配 B 中断,且其优先级为 2。
● GTIOC5B:指定 GTIOC5B 引脚为另一个定时器输入/输出引脚,连接到外部引脚 P102。

在这里插入图片描述

占空比与频率计算

在波形中:
● up1_capture_time 是第一次上升沿的捕获时间。
● down_capture_time 是下降沿的捕获时间。
● up2_capture_time 是第二次上升沿的捕获时间。

在这里插入图片描述

脉冲周期(pulse_period)完整周期为上升沿(up1_capture_time)到第二次上升沿(up2_capture_time)之间的时间差,也就是脉冲的完整周期。

在这里插入图片描述

● 频率计算:我在频率计算中使用了 pulse_period,确保了计算是在第一次和第二次上升沿之间。
● 占空比计算:计算占空比时,使用了从 down_capture_time 到第二次上升沿 up2_capture_time 之间的时间差来计算脉冲宽度。

在这里插入图片描述

回调函数gpt5_callback

  1. 上升沿捕获:
    ○ 在上升沿捕获时,更新第一次和第二次上升沿的捕获时间。
    ○ 计算 脉冲周期:即第二次上升沿与第一次上升沿之间的时间差。
    ○ 计算 频率:通过时钟频率除以脉冲周期。
    ○ 计算 占空比:通过计算从上升沿到下降沿的脉冲宽度,然后用脉冲宽度除以脉冲周期来计算占空比。
  2. 下降沿捕获:
    ○ 在下降沿捕获时,更新下降沿的捕获时间。

需要注意的是,代码中计算占空比时,用 (100.0f - (pulse_width*100 / (double)pulse_period)) 来计算正占空比。

volatile uint32_t up1_capture_time = 0;     // 用于存储第一次上升沿捕获的时间
volatile uint32_t down_capture_time = 0;     // 用于存储第一次上升沿捕获的时间
volatile uint32_t up2_capture_time = 0;     // 用于存储第二次上升沿捕获的时间
volatile uint32_t pulse_width = 0;          // 用于存储脉冲宽度
volatile uint32_t pulse_period = 0;         // 用于存储脉冲周期
volatile double duty_cycle = 0;           // 用于存储正占空比
volatile double frequency = 0;            // 用于存储频率

void gpt5_callback(timer_callback_args_t *p_args)
{
    /* TODO: add your own code here */
    if ((TIMER_EVENT_CAPTURE_B == p_args->event))  // 捕获事件
    {
        bsp_io_level_t p_port_value_port_102;
        // 读取端口电平状态,如果是低电平则发生的是下降沿,高电平则是上升沿
        R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_02, &p_port_value_port_102);

        // 获取当前定时器的时钟频率和周期
        timer_info_t info;
        (void) R_GPT_InfoGet(&g_timer5_ctrl, &info);
        uint64_t clock_frequency = info.clock_frequency; // 定时器时钟频率
        uint32_t current_period_counts = info.period_counts; // 定时器周期

        uint32_t current_time = p_args->capture; // 获取当前捕获时间(计数值)

        if (p_port_value_port_102 == BSP_IO_LEVEL_HIGH) // 上升沿
        {
            // 记录第一次和第二次上升沿的时间戳
            up1_capture_time=up2_capture_time;
            up2_capture_time=current_time;

            // 计算脉冲周期:从第一次到第二次上升沿的时间差
            if(up2_capture_time>=up1_capture_time)
                pulse_period = (up2_capture_time-up1_capture_time);
            else
                pulse_period = (current_period_counts -up1_capture_time) + up2_capture_time;
            // 计算频率:频率 = 时钟频率 / 脉冲周期
            frequency  =(double) (clock_frequency/pulse_period);

            // 计算脉冲宽度:从下降沿到第二次上升沿的时间差
            if(up2_capture_time>=down_capture_time)
                pulse_width=up2_capture_time-down_capture_time;
            else
                pulse_width=(current_period_counts -down_capture_time) + up2_capture_time;
            // 计算占空比:占空比 = 脉冲宽度 / 脉冲周期
            duty_cycle = 100.0f-(pulse_width*100 / (double)pulse_period);

        }
        else // 下降沿
        {
            // 更新下降沿的捕获时间
            down_capture_time=current_time;
        }

    }
}

主程序

void hal_entry(void)
{
    /* TODO: add your own code here */
    fsp_err_t err = FSP_SUCCESS;
    /* Initializes the module. */
    err = R_GPT_Open(&g_timer8_ctrl, &g_timer8_cfg);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);
    /* Start the timer. */
    (void) R_GPT_Start(&g_timer8_ctrl);
    R_BSP_SoftwareDelay (20, BSP_DELAY_UNITS_MILLISECONDS);

    err = R_GPT_PeriodSet(&g_timer8_ctrl, 12000);//频率
   assert(FSP_SUCCESS == err);
   R_BSP_SoftwareDelay (20, BSP_DELAY_UNITS_MILLISECONDS);//不加延时可能会设置不成功

   err = R_GPT_DutyCycleSet(&g_timer8_ctrl, 3000, GPT_IO_PIN_GTIOCA);// 设置占空比
   assert(FSP_SUCCESS == err);
   err = R_GPT_DutyCycleSet(&g_timer8_ctrl, 9000, GPT_IO_PIN_GTIOCB);// 设置占空比
   assert(FSP_SUCCESS == err);
   R_BSP_SoftwareDelay (20, BSP_DELAY_UNITS_MILLISECONDS);

//   err = R_GPT_Close(&g_timer8_ctrl);
//   assert(FSP_SUCCESS == err);
//   R_BSP_SoftwareDelay (20, BSP_DELAY_UNITS_MILLISECONDS);

   /* Open the transfer instance with initial configuration. */
   err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
   assert(FSP_SUCCESS == err);

   printf("hello\n");

   /* Initializes the module. */
   err = R_GPT_Open(&g_timer5_ctrl, &g_timer5_cfg);
   /* Handle any errors. This function should be defined by the user. */
   assert(FSP_SUCCESS == err);
   /* Start the timer. */
   (void) R_GPT_Start(&g_timer5_ctrl);

   (void) R_GPT_Enable(&g_timer5_ctrl);
   R_BSP_SoftwareDelay (20, BSP_DELAY_UNITS_MILLISECONDS);

   while(1)
   {
       printf("frequency=%.2f,duty cycle=%.2f\n",frequency,duty_cycle);
       duty_cycle = 0;  // 重置占空比
       frequency = 0;   // 重置频率
       R_BSP_SoftwareDelay (200, BSP_DELAY_UNITS_MILLISECONDS);

   }


#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

演示

分别接入P101和P100。

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

开源安全一站式构建!开启企业开源治理新篇章

在如今信息技术日新月异、飞速发展的数字化时代&#xff0c;开源技术如同一股强劲的东风&#xff0c;为企业创新注入了源源不断的活力&#xff0c;然而&#xff0c;正如一枚硬币有正反两面&#xff0c;开源技术的广泛应用亦伴随着不容忽视的挑战。安全风险如影随形&#xff0c;…

Node.js 与 npm 版本兼容性问题详解:如何避免版本冲突

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

鸿蒙开发中 SaveButton 按钮 保存按钮点击后权限授权失败。

原因分析 查看官方文档的解释 在 控制台中 过滤这个字段 过滤关键字"SecurityComponentCheckFail"可以获取具体原因。 得到 产生的原因 是 因为层叠的原因 savebutton 组件必须的 在屏幕的最高层 不能有任何的覆盖和遮挡 通过这样书写就解决了 // 下面是安…

胜任力冰山模型:深入探索职业能力的多维结构

目录 1、序言 2、什么是胜任力&#xff1f; 3、任职资格和胜任力的区别 4、胜任力冰山模型&#xff1a;职场能力的多维展现 4.1、冰山水面上的部分 4.2、冰山水面下的部分 4.3、深层的个人特质与价值观 5、如何平衡任职资格与胜任能力 6、结语 1、序言 在快速发展的I…

C#面试常考随笔12:游戏开发中常用的设计模式【C#面试题(中级篇)补充】

C#面试题&#xff08;中级篇&#xff09;&#xff0c;详细讲解&#xff0c;帮助你深刻理解&#xff0c;拒绝背话术&#xff01;-CSDN博客 简单工厂模式 优点&#xff1a; 根据条件有工厂类直接创建具体的产品 客户端无需知道具体的对象名字&#xff0c;可以通过配置文件创建…

将Deepseek接入pycharm 进行AI编程

目录 专栏导读1、进入Deepseek开放平台创建 API key 2、调用 API代码 3、成功4、补充说明多轮对话 总结 专栏导读 &#x1f338; 欢迎来到Python办公自动化专栏—Python处理办公问题&#xff0c;解放您的双手 &#x1f3f3;️‍&#x1f308; 博客主页&#xff1a;请点击——…

《论文阅读》GPT-3是否会产生移情对话?一种新的情境示例选择方法和用于生成同理心对话的自动评估度量 ICCL 2022

《论文阅读》GPT-3是否会产生移情对话?一种新的情境示例选择方法和用于生成同理心对话的自动评估度量 ICCL 2022 前言贡献PromptIn-context learningSITSMEMOSITSM新的自动指标实验前言 亲身阅读感受分享,细节画图解释,再也不用担心看不懂论文啦~ 无抄袭,无复制,纯手工敲…

javaEE初阶————多线程初阶(3)

大家新年快乐呀&#xff0c;今天是第三期啦&#xff0c;大家前几期的内容掌握的怎么样啦&#xff1f; 1&#xff0c;线程死锁 1.1 构成死锁的场景 a&#xff09;一个线程一把锁 这个在java中是不会发生的&#xff0c;因为我们之前讲的可重入机制&#xff0c;在其他语言中可…

【Flink快速入门-1.Flink 简介与环境配置】

Flink 简介与环境配置 实验介绍 在学习一门新的技术之前&#xff0c;我们首先要了解它的历史渊源&#xff0c;也就是说它为什么会出现&#xff0c;它能够解决什么业务痛点。所以本节我们的学习目的是了解 Flink 的背景&#xff0c;并运行第一个 Flink 程序&#xff0c;对它有…

WPF基础 | 初探 WPF:理解其核心架构与开发环境搭建

WPF基础 | 初探 WPF&#xff1a;理解其核心架构与开发环境搭建 一、前言二、WPF 核心架构2.1 核心组件2.2 布局系统2.3 数据绑定机制2.4 事件处理机制 三、WPF 开发环境搭建3.1 安装 Visual Studio3.2 创建第一个 WPF 应用程序 结束语优质源码分享 WPF基础 | 初探 WPF&#xff…

JVM 四虚拟机栈

虚拟机栈出现的背景 由于跨平台性的设计&#xff0c;Java的指令都是根据栈来设计的。不同平台CPU架构不同&#xff0c;所以不能设计为基于寄存器的。优点是跨平台&#xff0c;指令集小&#xff0c;编译器容易实现&#xff0c;缺点是性能下降&#xff0c;实现同样的功能需要更多…

深入理解小波变换:信号处理的强大工具

引言 在科学与工程领域&#xff0c;信号处理一直是关键环节&#xff0c;傅里叶变换与小波变换作为重要的分析工具&#xff0c;在其中发挥着重要作用。本文将深入探讨小波变换&#xff0c;阐述其原理、优势以及与傅里叶变换的对比&#xff0c;并通过具体案例展示其应用价值。 一…

【大数据技术】搭建完全分布式高可用大数据集群(Kafka)

搭建完全分布式高可用大数据集群(Kafka) kafka_2.13-3.9.0.tgz注:请在阅读本篇文章前,将以上资源下载下来。 写在前面 本文主要介绍搭建完全分布式高可用集群 Kafka 的详细步骤。 注意: 统一约定将软件安装包存放于虚拟机的/software目录下,软件安装至/opt目录下。 安…

关于ESP-IDF 5.4 中添加第三方组件esp32-camera找不到文件,编译错误解决办法(花了一天时间解决)

最近需要使用ESP32-S3-CAM 的OV2640摄像头采集图像&#xff0c;为了加速开发进度&#xff0c;于是选择了esp32-camera组件&#xff0c;该组件不是官方组件&#xff0c;需要自己git clone。但在为项目添加esp32-camera组件时&#xff0c;一直编译错误&#xff0c;找不到头文件&a…

Android LifecycleOwner 闪退,java 继承、多态特性!

1. 闪退 同意隐私政策后&#xff0c;启动进入游戏 Activity 闪退 getLifecycle NullPointerException 空指针异常 FATAL EXCEPTION: main Process: com.primer.aa.gg, PID: 15722 java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.primer.aa.…

[LeetCode]day16 242.有效的字母异位词

242. 有效的字母异位词 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的 字母异位词 示例 1: 输入: s "anagram", t "nagaram" 输出: true示例 2: 输入: s "rat"…

基于SpringBoot养老院平台系统功能实现五

一、前言介绍&#xff1a; 1.1 项目摘要 随着全球人口老龄化的不断加剧&#xff0c;养老服务需求日益增长。特别是在中国&#xff0c;随着经济的快速发展和人民生活水平的提高&#xff0c;老年人口数量不断增加&#xff0c;对养老服务的质量和效率提出了更高的要求。传统的养…

【3分钟极速部署】在本地快速部署deepseek

第一步&#xff0c;找到网站&#xff0c;下载&#xff1a; 首先找到Ollama &#xff0c; 根据自己的电脑下载对应的版本 。 我个人用的是Windows 我就先尝试用Windows版本了 &#xff0c;文件不是很大&#xff0c;下载也比较的快 第二部就是安装了 &#xff1a; 安装完成后提示…

Linux ftrace 内核跟踪入门

文章目录 ftrace介绍开启ftraceftrace使用ftrace跟踪指定内核函数ftrace跟踪指定pid ftrace原理ftrace与stracetrace-cmd 工具KernelShark参考 ftrace介绍 Ftrace is an internal tracer designed to help out developers and designers of systems to find what is going on i…

[Day 16]螺旋遍历二维数组

今天我们看一下力扣上的这个题目&#xff1a;146.螺旋遍历二维数组 题目描述&#xff1a; 给定一个二维数组 array&#xff0c;请返回「螺旋遍历」该数组的结果。 螺旋遍历&#xff1a;从左上角开始&#xff0c;按照 向右、向下、向左、向上 的顺序 依次 提取元素&#xff0c…