查看: 604|回复: 1

【瑞萨RA4系列开发板体验】GPT定时器的基础使用

[复制链接]

116

主题

133

帖子

3768

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3768
发表于 2023-2-8 09:40:25 | 显示全部楼层 |阅读模式
【瑞萨RA4系列开发板体验】GPT定时器的基础使用
作者:HonestQiao


在RA4M2的系统重,提供了三种定时器,从手册之中可以了解:

三种定时器分别是:
  • 普通PWM 32位定时器:GPT32
  • 普通PWM 16位定时器:GPT16
  • 低功耗用用异步定时器:AGT
其中普通GPT比较常用,主要是用于生成PWM波形,从而控制例如无刷电机等外部设备。当然,也可以不进行输出,直接当做定时器使用,在定时回调中,进行我们需要的处理。
从手册上可以了解这些定时器的具体功能规范:


下面,就以点灯的实例,来展示GPT的基础使用。
一、FPS设置
要启用GPT,首先就需要在FPS种进行设置。
关于LED部分的设置,就不重新说了,这个是基础。
GPT设置步骤如下:


上述步骤,就是先添加一个GPT的Stack,然后设置其初始化参数和回调参数:
初始化参数:
  • Name: 名称
  • Channel: 通道
  • Mode: 模式,选择周期性
  • Period: 周期位1
  • Period Unit: 周期的单位位秒
    也就是定时器1秒触发一次

周期单位可以详细设置,具体如下:


在bsp_delay.h中,也有类似的定义:
  1. typedef enum
  2. {
  3.     BSP_DELAY_UNITS_SECONDS      = 1000000, ///< Requested delay amount is in seconds
  4.     BSP_DELAY_UNITS_MILLISECONDS = 1000,    ///< Requested delay amount is in milliseconds
  5.     BSP_DELAY_UNITS_MICROSECONDS = 1        ///< Requested delay amount is in microseconds
  6. } bsp_delay_units_t;
复制代码
回调参数:
  • Callback:回调函数名称,定时器触发时,会调用该函数,在其中进行具体的操作处理
  • Overflow/Crest Interrupts Priority:定时器的中断登记,用10就可以
    其他的先不用管,默认即可。
    设置好,生成代码以后,就转入代码部分的操作了。
    在代码部分,我们需要添加两个调用,一个是GPT初始化,一个是回调函数,具体如下:


  1. static bool status = false;

  2. /* GPT 初始化函数 */
  3. void GPT_Timing_Init(void)
  4. {
  5.     /* 初始化 GPT0 模块 */
  6.     R_GPT_Open(&g_timer_gpt0_ctrl, &g_timer_gpt0_cfg);

  7.     /* 启动 GPT0 定时器 */
  8.     R_GPT_Start(&g_timer_gpt0_ctrl);
  9. }

  10. /* GPT 中断回调函数 */
  11. void gpt0_timing_callback(timer_callback_args_t * p_args)
  12. {
  13.     /* 定时器溢出事件 */
  14.     if (TIMER_EVENT_CYCLE_END == p_args->event)
  15.     {
  16.         /* 翻转 LED1 */
  17.         //每秒翻转一次
  18.         status = ! status;
  19.         if(status) {
  20.             R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_15, BSP_IO_LEVEL_HIGH); // 点亮LED
  21.         } else {
  22.             R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_04_PIN_15, BSP_IO_LEVEL_LOW); // 关闭LED
  23.         }
  24.     }
  25. }
复制代码
在上述代码终,GPT_Timing_Init()负责初始化,因为我们只用了gpt0,所以只需要初始化gpt0即可。
gpt0对应的控制变量,以及回调函数的预定义,在hal_data.h终有定义,具体如下:

  1. extern gpt_instance_ctrl_t g_timer_gpt0_ctrl;
  2. extern const timer_cfg_t g_timer_gpt0_cfg;

  3. #ifndef gpt0_timing_callback
  4. void gpt0_timing_callback(timer_callback_args_t * p_args);
  5. #endif
复制代码
在hal_data.c中,有关于g_timer_gpt0_ctrl和g_timer_gpt0_cfg的具体定义:
  1. const timer_cfg_t g_timer_gpt0_cfg =
  2. {
  3.     .mode                = TIMER_MODE_PERIODIC,
  4.     /* Actual period: 1 seconds. Actual duty: 50%. */
  5.     .period_counts = (uint32_t) 0x5f5e100,
  6.     .duty_cycle_counts = 0x2faf080,
  7.     .source_div = (timer_source_div_t)0,
  8.     .channel             = 0,
  9.     .p_callback          = gpt0_timing_callback,
  10.     /** If NULL then do not add & */
  11. #if defined(NULL)
  12.     .p_context           = NULL,
  13. #else
  14.     .p_context           = &NULL,
  15. #endif
  16.     .p_extend            = &g_timer_gpt0_extend,
  17.     .cycle_end_ipl       = (10),
  18. #if defined(VECTOR_NUMBER_GPT0_COUNTER_OVERFLOW)
  19.     .cycle_end_irq       = VECTOR_NUMBER_GPT0_COUNTER_OVERFLOW,
  20. #else
  21.     .cycle_end_irq       = FSP_INVALID_VECTOR,
  22. #endif
  23. };
  24. /* Instance structure to use this module. */
  25. const timer_instance_t g_timer_gpt0 =
  26. {
  27.     .p_ctrl        = &g_timer_gpt0_ctrl,
  28.     .p_cfg         = &g_timer_gpt0_cfg,
  29.     .p_api         = &g_timer_on_gpt
  30. };
复制代码
在前面代码终,还添加了一个status变量,用于表示LED的状态,true则电量LED1,false则熄灭LED1。其中,BSP_IO_PORT_04_PIN_15对应LED1的引脚。
然后,在hal_entry()终调用初始化,就能够启动定时器了,具体如下:

  1. void hal_entry(void)
  2. {
  3.     /* TODO: add your own code here */
  4.     fsp_err_t err;                                       //
  5.     err = R_IOPORT_Open(&g_ioport_ctrl, &g_bsp_pin_cfg); // 初始化引脚
  6.     assert(FSP_SUCCESS == err);                          // 判断是否初始化成功

  7.     GPT_Timing_Init();  // GPT 初始化
  8.     while(1)
  9.     {        R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS);
  10.     }


  11. #if BSP_TZ_SECURE_BUILD
  12.     /* Enter non-secure code */
  13.     R_BSP_NonSecureEnter();
  14. #endif
  15. }
复制代码
使用GPT_Timing_Init()进行初始化后,定时器就会启动,并按照预定的周期,调用gpt0_timing_callback()。
代码终的R_BSP_SoftwareDelay()表示演示,以免while(1)疯狂运行。
编写好代码之后,编译下载到开发板上,就可以看到LED1,每秒闪烁一次了。
在前面的gpt cfg定义中,有两个很重要,但设置为1秒的时候,对应的值为:

  1. /* Actual period: 1 seconds. Actual duty: 50%. */
  2. .period_counts = (uint32_t) 0x5f5e100,
  3. .duty_cycle_counts = 0x2faf080,
复制代码
当设置为100毫秒的时候,对应的值为:
  1. /* Actual period: 0.1 seconds. Actual duty: 50%. */
  2. .period_counts = (uint32_t) 0x989680,
  3. .duty_cycle_counts = 0x4c4b40,
复制代码
在上述配置中,period_counts表示定时器一个周期的计数次数,达到计数次数,则调用一次回调函数。
duty_cycle_counts表示占空比的技术次数,上述两个值,都为period_counts的一半,所以如果是PWM输出,则其对应的占空比为50%。
如果使用0.1seconds的配置,然后编译烧录,就可以看到LED快速闪烁了。
如果将1秒的period_counts除以0.1秒的period_counts,可以得到倍差值:0x5f5e100/0x989680 = 0xa,也就是10倍。
明白了这一点,那我们想要及时修改定时器的定时周期测试的时候,就不用再去FSP中操作了。等调整了定时器,达到实际需要了,再到FSP中进行一次设置,使得配置能够写入到xml配置文件中。



回复

使用道具 举报

3

主题

195

帖子

1191

积分

金牌会员

Rank: 6Rank: 6

积分
1191
发表于 2023-3-14 10:56:55 | 显示全部楼层

不错,学习一下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

用户排行榜

RA助手

主题: 116帖子:133精华:0

RA_Lance

主题: 92帖子:132精华:9

lugl

主题: 38帖子:126精华:0

xujiwei263

主题: 16帖子:73精华:0

books咦

主题: 11帖子:11精华:2

Juggernaut

主题: 9帖子:95精华:0
快速回复 返回顶部 返回列表