当前位置: 首页 > news >正文

第18章_瑞萨MCU零基础入门系列教程之GPT

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id=728461040949

配套资料获取:https://renesas-docs.100ask.net

瑞萨MCU零基础入门系列教程汇总: https://blog.csdn.net/qq_35181236/article/details/132779862


第18章 GPT

本章目标

  • 了解RA6M5处理器的GPT外设;
  • 学会使用RASC配置GPT实现基本定时和PWM输出;

18.1 GPT简介

通用PWM定时器(GPT,Genera- PWM Timer)是RA MCU的一种32/16位的定时器外设。在GPT当中,可分为GPT32和GPT16,它们最主要的区别是计数器的位数不同。GPT32是32位的定时器,能计数的范围为:0~0xFFFF_FFFF; 而GPT16是16位的定时器,能计数的范围为:0~0xFFFF。

GPT模块可用于计数事件、测量外部输入信号、作为通用计时器并产生周期性中断、以及输出周期性PWM信号到GTIO引脚。GPT也可用于输出单个脉冲,但是注意这是通过软件来实现的,GPT硬件本身不支持输出单个脉冲(One-Shot)功能。当使用单个脉冲(One-Shot)模式时,必须要开启中断,在脉冲周期结束后在ISR中断服务函数中停止计时器。

RA MCU的GPT包括但不限于如下这些特征:

  • 32位GPT有4个输入/输出通道;16位GPT有6个输入输出通道;
  • 每个GPT的计数器支持向上计数、向下计数或者向上向下同时计数;
  • 每个通道的时钟源都可以单独配置选择;
  • 每个通道有2个引脚可用来输入输出;
  • 每个通道有2个输出比较寄存器或者输入捕获寄存器;
  • 每个通道的输出比较寄存器或输入捕获寄存器都有4个缓存寄存器;
  • 在PWM模式下支持设置死区时间;
  • 计数器的开始、停止、清除等动作可以由最多8个ELC事件响应,也可以由最多4个外部触发器相应;
  • 支持生成控制无刷直流电机的PWM波;

RA MCU的GPT支持下表的这些功能:·

image1

image2

RA MCU的GPT引脚及其功能用途如下表:

image3

最后来看下GPT的系统框图:

![](
http://photos.100ask.net/renesas-docs/DShanMCU_RA6M5/object_oriented_module_programming_method_in_ARM_embedded_system/chapter-18/image4.png" alt="image4)

  1. 计数器

GTCNT是GPT定时器模块内部的计数器,实际上,计数器是实现定时器外设的各种功能的基础。 因此,了解计数器的规格和功能非常重要。

对于RA6M5,共有10个GPT定时器(GPT09),而GPT又分为GPT32和GPT16。GPT32有4个(GPT03),计数器为32bit,在上图中用GPT320GPT323来表示;而GPT16有6个(GPT49),计数器为16bit,在上图中用GPT164~GPT169来表示。

GPT的计数器支持递增计数,递减计数和递增/递减计数(即递增与递减计数轮流进行)。

  1. 时钟源

GPT定时器的时钟输入可以选择内部的PCLKD分频后输入,或者选择通过GTETRGn引脚输入外部时钟。这两类中只能选择一个,若选择外部时钟输入则定时器不能对内部时钟输入进行计数。

  • PCLKD / n(n = 1/2/4/8/16/32/64/256/1024)
  • GTETRGA,GTETRGB,GTETRGC,GTETRGD(通过POEG)

注:PCLKD / 1表示的是不分频。

  1. 周期设置

GTPR周期设置寄存器,是一个可读写的寄存器,用户可通过该寄存器设置计数器GTCNT的最大计数值,计数超过该值就会溢出,因此该值决定了计数器的计数周期。GTPR的有效位与GTCNT(16位或32位)相同。如果GTPR的有效大小为16位,则用户读取其高16位始终为0,并且对其高16位的写入作会被忽略。

GTPBR 周期设置缓冲寄存器,同样也是一个可读写的寄存器,用作GTPR的缓冲寄存器,GPT计数器每计数溢出一次,就会将GTPBR的值写入GTPR。GTPBR的有效大小也与GTCNT(16位或32位)相同。如果GTPBR的有效大小为16位,则用户读取其高16位始终为0,并且对其高16位的写入作会被忽略。

  1. 控制寄存器

本书是面向对象的编程思想,不会基于寄存器直面底层硬件编程,且GPT的控制寄存器很多,本书不对GPT的寄存器做一一讲解。

  1. 比较输出和输入捕获控制寄存器

这部分包含一个比较器和6个GTCCRx寄存器(x = A,B,C,D,E,F)。这6个GTCCRx寄存器的功能并不完全相同:

  • GTCCRA和GTCCRB是用于输出比较和输入捕捉的寄存器。
  • GTCCRC和GTCCRE可用作比较匹配寄存器,也可以分别作为GTCCRA和GTCCRB的缓冲寄存器(构成GTCCRA和GTCCRB的单缓冲寄存器)。
  • GTCCRD和GTCCRF可用作比较匹配寄存器,也可以分别作为GTCCRC和GTCCRE的缓冲寄存器(构成GTCCRA和GTCCRB的双缓冲寄存器:即GTCCRC和GTCCRD作为GTCCRA的双缓冲,GTCCRE和 GTCCRF作为GTCCRB的双缓冲)。

比如,在普通的PWM输出模式下,比较器将计数器GTCNT与GTCCRA和GTCCRB进行比较,若匹配(比较结果相等),则根据GTIOR(Genera- PWM Timer I/O Contro- Register)寄存器的GTIOA[4:0]和GTIOB[4:0]的配置来切换GTIOCA和GTIOCB的输出电平。可以将GTIOCA和GTIOCB切换为低电平、高电平、或者反转电平。

  1. 中断源

图中显示的是GPT0的中断请求信号,中断请求信号用于产生中断、或者通过ELC链接到其他模块。

GPT提供以下中断源:

  • GTCCR输入捕捉/比较匹配
  • GTCNT计数器上溢(超出GTPR设置的值)/下溢
  • 周期计数功能完成

每个中断源都有自己的状态标志。当一个中断源信号产生时,相关的状态标志会被硬件自动设置为1。状态标志可以通过写入0来清除。需要注意的是,如果标志设置和标志清除同时发生,标志清除优先于标志设置。

  1. GPT输入引脚

GTIOCnA和GTIOCnB是GPT的IO输入输出引脚,用于信号输出和输入捕获。它们还配备了噪声滤波器(Noise Filter),噪声滤波器以采样时钟对输入信号进行采样,并去除长度小于3个采样周期的脉冲。用户可设置是否启用噪声滤波器。

  1. ELC输入事件

GPT可以执行以下操作以响应最多8个来自ELC的事件信号输入:

  • 开始计数,停止计数,清除计数
  • 递增计数,递减计数
  • 进行一次输入捕获
  1. 输出相位切换控制

输出相位切换(GPT_OPS)功能通过输出相位切换控制寄存器(OPSCR)进行控制,用于实现轻松控制无刷直流电机运行的功能。

需要注意的是:GPT_OPS功能在RA6M5中只有一个,并不是每个GPT定时器都对应有一个,也就是说通过该功能只能轻松控制一个直流无刷电机。

18.2 GPT模块的使用

在RASC中使用GPT模块根据应用场景分为两类:基本定时、有输入/输出需求。如果仅仅用作基本定时,那么只需要在RASC的“Stacks”中添加GPT模块即可;如果有输入输出需求的,例如输出PWM到某个引脚或者对某个波形进行捕获比较,那就需要去FSP的“Pins”中配置该引脚,然后再去“Stacks”中添加配置GPT模块。

18.2.1 配置GPT模块

如果需要输出波形到某个引脚或者捕获比较某个引脚,建议先去RASC的“Pins”配置引脚。

  1. 配置GPT引脚

在“Pins”中的“Peripherals”中找到“Timers:GPT”,根据硬件设计选择GPT通道和引脚,比如要使用PWM实现一个呼吸灯,LED的原理图如下图所示:

使用到的引脚是P400,此引脚支持的GPT复用通道在RA6M5数据手册中查看:

可以看到P400支持的GPT复用通道是GTIOC6A,也就是GPT通道6的A组引脚,那么就可以配置Pins了,如下图所示:

  1. 添加GPT Stack

在FSP的“Stacks”中点击“New Stack”找到“Timers”,选择其中的“Timer,General PWM(r_gpt)”添加GPT模块,如下图所示:

接着根据使用场景配置GPT的Stack模块。GPT的Stack有3个大类需要配置:

  • Common:通用配置,适配该外设所有的stack模块。对于GPT而言,通用配置需要设置的参数是:

    • Parameter Checking:参数校验,在FSP库函数中判断参数是否合法,使用断言方式判断,默认不使能。
    • Pin Output Support:GPT输出引脚是否使能,支持两种模式:使能和根据模块外部特征配置使能。默认使用“根据模块外部特征配置使能”,目的是不同的模块使用不同的配置实现定制化。
    • Write Protect Enable:写保护,默认不使能。
    • Clock Source:时钟源,GPT默认选择PCLKD。
  • Module g_timer Timer,General PWM(r_gpt):模块定制化配置,是本节配置的重点。

  • Pins:引脚选择,如果有输入输出需求,会自动连接到前文配置的引脚。如果是多通道,需要选择配置。

  1. 配置GPT Module

GPT的通道定制化Module配置有以下5类参数需要配置:

  • General:常规配置

  • OutPut:输出配置

此项是配置GPT输出功能的参数,例如占空比、引脚初始状态、空闲状态等,参数比较多,不一一列举,主要内容如下图所示:

后文会配置此处的参数生成PWM来实现呼吸灯效果,那时会详细介绍这些参数。

  • Input:输入配置

此项是配置GPT的输入捕获功能,需要配置触发捕获向上计数的源、触发向下计数的源、开始捕获触发源、停止捕获触发源等,详细内容见下图:

这些触发源都需要根据硬件设计选择。

  • Interrupts:中断配置

此项配置GPT的中断回调函数和中断优先级,比如溢出中断优先级、输入捕获优先级等,如下图所示:

  • Extra Features:外部特征配置

GPT的外部特征配置是指配置GPT输出引脚的使能、GPT计数的触发源、死区时间的设置等,如下图所示:

当GPT的使用更加精细,比如会和ADC搭配使用,需要生成复杂的PWM、三角PWM时,就需要对外部特征进行更加精细的,定制化的配置。

18.2.2 配置信息解读

使用RASC将GPT的stack模块配置好之后点击“Generate Project Content”生成工程,会在工程的pin_data.c中生成模块的引脚信息,在hal_data.c中生成模块的配置信息。

  1. GPT的引脚信息

假设需要使用GPT往P400引脚输出PWM控制LED,使用RASC配置GPT的通道且指定引脚后,生成的工程中的pin_data.c中的g_bsp_pin_cfg_data[]数组就会添加该引脚的配置信息,代码如下:

const ioport_pin_cfg_t g_bsp_pin_cfg_data[] = {......(省略内容){.pin = BSP_IO_PORT_04_PIN_00,.pin_cfg = ((uint32_t) IOPORT_CFG_PERIPHERAL_PIN | (uint32_t) IOPORT_PERIPHERAL_GPT1)},
};
  1. GPT的模块配置信息

GPT模块的配置信息在hal_data.c中以timer_cfg_t类型的结构体变量表示,代码如下:

const timer_cfg_t g_timer6_cfg =
{.mode                = TIMER_MODE_PERIODIC,/* Actual period: 0.001 seconds. Actual duty: 50%. */ .period_counts = (uint32_t) 0x186a0, .duty_cycle_counts = 0xc350, .source_div = (timer_source_div_t)0,.channel             = 6,.p_callback          = gpt_timer6_callback,/** If NULL then do not add & */
#if defined(NULL).p_context           = NULL,
#else.p_context           = &NULL,
#endif.p_extend            = &g_timer6_extend,.cycle_end_ipl       = (10),
#if defined(VECTOR_NUMBER_GPT2_COUNTER_OVERFLOW).cycle_end_irq       = VECTOR_NUMBER_GPT2_COUNTER_OVERFLOW,
#else.cycle_end_irq       = FSP_INVALID_VECTOR,
#endif
};
  • 第03行:mode表示GPT的类型,此处是周期型;
  • 第05~06行:表示输出PWM的周期和占空比;
  • 第08行:表示使用的GPT的通道;
  • 第09行:表示GPT的中断回调函数;

在程序中使用GPT的open函数打开GPT设备的时,就会使用这些配置信息初始化GPT。

18.2.3 中断回调函数

使用RASC配置生成工程后,配置的中断回调函数会在hal_data.h中声明,代码如下:

#ifndef gpt_timer6_callback
void gpt_timer6_callback(timer_callback_args_t * p_args);
#endif

用户需要在自己的程序中实现这个中断回调函数,例如:

void gpt_timer6_callback(timer_callback_args_t *p_args)
{/* TODO: add your own code here */
}

用户可以根据中断回调函数的参数timer_callback_args_t的成员进行定制处理,这个结构体的原型长这样:

typedef struct st_timer_callback_args
{/** Placeholder for user data.  Set in @ref timer_api_t::open function in @ref timer_cfg_t. */void const  * p_context;timer_event_t event;               ///< The event can be used to identify what caused the callback./** Most recent capture, only valid if event is TIMER_EVENT_CAPTURE_A or TIMER_EVENT_CAPTURE_B. */uint32_t capture;
} timer_callback_args_t;

最常用的就是其中的定时器事件成员timer_event_t,它支持的事件如下:

/** Events that can trigger a callback function */
typedef enum e_timer_event
{TIMER_EVENT_CYCLE_END, ///< Requested timer delay has expired or timer has wrapped aroundTIMER_EVENT_CREST = TIMER_EVENT_CYCLE_END, ///< Timer crest event (counter is at a maximum, triangle-wave PWM only)TIMER_EVENT_CAPTURE_A,                    ///< A capture has occurred on signal ATIMER_EVENT_CAPTURE_B,                    ///< A capture has occurred on signal BTIMER_EVENT_TROUGH,      ///< Timer trough event (counter is 0, triangle-wave PWM only
} timer_event_t;

比如用户可以判断事件是否为TIMER_EVENT_CYCLE_END,它表示计数到指定周期了才进入的中断:

if(p_args->event == TIMER_EVENT_CYCLE_END)
{
}

18.2.4 API接口及其用法

GPT模块供用户使用的API在r_timer_api.h中定义:

typedef struct st_timer_api
{fsp_err_t (* open)(timer_ctrl_t * const p_ctrl, timer_cfg_t const * const p_cfg);fsp_err_t (* start)(timer_ctrl_t * const p_ctrl);fsp_err_t (* stop)(timer_ctrl_t * const p_ctrl);fsp_err_t (* reset)(timer_ctrl_t * const p_ctrl);fsp_err_t (* enable)(timer_ctrl_t * const p_ctrl);fsp_err_t (* disable)(timer_ctrl_t * const p_ctrl);fsp_err_t (* periodSet)(timer_ctrl_t * const p_ctrl, uint32_t const period);fsp_err_t (* dutyCycleSet)(timer_ctrl_t * const p_ctrl, uint32_t const duty_cycle_counts, uint32_t const pin);fsp_err_t (* infoGet)(timer_ctrl_t * const p_ctrl, timer_info_t * const p_info);fsp_err_t (* statusGet)(timer_ctrl_t * const p_ctrl, timer_status_t * const p_status);fsp_err_t (* callbackSet)(timer_ctrl_t * const p_api_ctrl, void (* p_callback)(timer_callback_args_t *),void const * const p_context, timer_callback_args_t * const p_callback_memory);fsp_err_t (* close)(timer_ctrl_t * const p_ctrl);
} timer_api_t;

接下来看下这些API的用法。

  1. 打开GPT设备
fsp_err_t (* open)(timer_ctrl_t * const p_ctrl, timer_cfg_t const * const p_cfg);
  • p_ctrl:timer_ctrl_t结构体指针参数,本质是一个void类型的参数,指向st_gpt_instance_ctrl类型变量;
  • p_cfg:timer_cfg_t结构体指针参数,在程序中会指向在hal_data.c中定义的g_timer6_cfg静态全局变量;

用户在程序中可以参考如下代码使用此函数:

fsp_err_t err = g_timer6.p_api->open(g_timer0.p_ctrl, g_timer6.p_cfg);
if(FSP_SUCCESS != err)printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);
  1. 开启/停止GPT计数
  • GPT开始计数
fsp_err_t (* start)(timer_ctrl_t * const p_ctrl);
  • GPT停止计数
fsp_err_t (* stop)(timer_ctrl_t * const p_ctrl);

必须要在GPT打开状态下使用这两个函数,用户可以参考如下代码在自己的程序中使用这两个函数:

err = g_timer6.p_api->start(g_timer6.p_ctrl);
if(FSP_SUCCESS != err)printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);err = g_timer6.p_api->stop(g_timer6.p_ctrl);
if(FSP_SUCCESS != err)printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);
  1. 重置GPT计数值
fsp_err_t (* reset)(timer_ctrl_t * const p_ctrl);

如果GPT是向上计数,使用此函数会将计数器的值重置为0;如果是向下计数,使用此函数会将计数器的值重置为设定的周期值。

  1. 使能/失能GPT的输入捕获
  • 使能GPT输入捕获
fsp_err_t (* enable)(timer_ctrl_t * const p_ctrl);
  • 失能GPT输入捕获
    fsp_err_t (* disable)(timer_ctrl_t * const p_ctrl);

如果用户使用了GPT的输入捕获功能的话,在需要对引脚的信号进行捕获时需要使能捕获功能;如果想要停止捕获则调用disable。

  1. 设置GPT的计数周期值
    fsp_err_t (* periodSet)(timer_ctrl_t * const p_ctrl, uint32_t const period);

如果要改变定时器的计数周期,可以调用此函数,在下一次重新计数开始生效。

  1. 设置GPT输出PWM的占空比
fsp_err_t (* dutyCycleSet)(timer_ctrl_t * const p_ctrl, uint32_t const duty_cycle_counts, uint32_t const pin);

在PWM驱动应用中,可以使用此函数来修改占空比。用户可以参考如下代码来使用这个函数:

fsp_err_t err = g_timer6.p_api->dutyCycleSet(g_timer6.p_ctrl, gPulse, GPT_IO_PIN_GTIOCA);
if(FSP_SUCCESS != err)
printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);

此函数最后一个参数是指GPT的输出通道,而不是指IO引脚。

  1. 关闭GPT设备
fsp_err_t (* close)(timer_ctrl_t * const p_ctrl);

18.3 GPT的基本定时功能

本节实验会使用到串口打印以及滴答定时器,请将前文的drv_uart.c/.h和hal_systick.c/.h移植到本次实验中。

18.3.1 设计目的

实现一个基于硬件定时器的延时函数,最小延时时间为1us。同时利用滴答定时器辅助验证,通过串口打印调试结果。

18.3.2 GPT模块配置

本次实验只用到了GPT的基本定时计数功能,没有使用到比较输出或捕获输出,因而仅添加了stack模块,没有配置Pins。GPT Stack模块的Module配置如下图所示:

虽然配置的时候选择的周期和单位是1us,但是在实际使用中可以改变这个值,所以Period和Period Unit在配置时其实可以选任意值。

另外,基于本次实验的目的,本书将定时器设置为one-shot模式,每次延时只需要计数器完成一次周期计数溢出。

18.3.3 驱动程序

  1. 初始化
void GPTDrvInit(void)
{fsp_err_t err = g_timer0.p_api->open(g_timer0.p_ctrl, g_timer0.p_cfg);if(FSP_SUCCESS != err)printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);
}

初始化函数比较简单,仅仅只是调用GPT的open函数打开设备。

  1. 中断回调函数和溢出等待函数
static void GPTDrvWaitOverflow(void);
static volatile bool gGPTOverflow = false;
/* Callback function */
void gpt_timer0_callback(timer_callback_args_t *p_args)
{/* TODO: add your own code here */if(p_args->event == TIMER_EVENT_CYCLE_END)gGPTOverflow = true;
}static void GPTDrvWaitOverflow(void)
{while(!gGPTOverflow);gGPTOverflow = false;
}
  • 第02行:定义一个bool类型的标志位来表示定时器计数是否溢出,在中断回调函数中它被赋值为true,在等待函数中它被赋值为false;
  • 第07行:判断的定时器中断事件是周期结束事件,表示一次周期性的计数完成触发的中断;
  1. 微秒延时函数
void GPTDrvUDelay(unsigned int time)
{fsp_err_t err = g_timer0.p_api->periodSet(g_timer0.p_ctrl, time*100);if(FSP_SUCCESS != err)printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);err = g_timer0.p_api->reset(g_timer0.p_ctrl);if(FSP_SUCCESS != err)printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);err = g_timer0.p_api->start(g_timer0.p_ctrl);if(FSP_SUCCESS != err)printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);GPTDrvWaitOverflow();
}
  • 第03行:根据参数和定时器的时钟频率计算周期值,定时器的时钟频率是100MHz,要计数达到1us的时间就需要以100MHz的频率计数100下。因而要实现以n微秒,就需要给定时器设置n*100个计数周期值。
  • 第07行:复位计数器的计数值,本次选择的是向上计数,复位后计数器的计数值会归零;
  • 第11行:开启定时器计数,因为本次使用的是one-shot模式,当定时器计数time*100次后会自动停止;

18.3.4 测试程序

void GPTAppTest(void)
{SystickInit();UARTDrvInit();GPTDrvInit();{uint32_t lastTick = HAL_GetTick();GPTDrvUDelay(1000000);    // delay 1msuint32_t curTick = HAL_GetTick();printf("Last    Tick: %d\r\n", (int)lastTick);printf("Current Tick: %d\r\n", (int)curTick);printf("Passed  Tick: %d\r\n", (int)(curTick - lastTick));}
}
  • 第08行:获取us延时函数调用前的滴答定时器时刻;
  • 第09行:延时1000,000us也就是1s,因为使用的是滴答定时器辅助验证,延时函数需要大于1ms;
  • 第10行:获取us延时函数调用后的滴答定时器时刻;
  • 第13行:打印出两次时刻的差值计算us延时函数的实际耗时;

18.3.5 测试结果

可以看到滴答定时器走过的tick数为1000,也就是耗时1s,和实验预期一致。

18.4 PWM实现呼吸灯

本节实验会使用到串口打印以及滴答定时器,请将前文的drv_uart.c/.h和hal_systick.c/.h移植到本次实验中。

18.4.1 设计目的

使用GPT输出PWM,通过调节PWM的占空比来改变LED的亮度,通过设计合理的周期值来达到适宜的呼吸灯效果。

18.4.2 硬件连接

LED的原理图如下图所示:

在前文已经分析过P400可以复用做GPT通道6的输出IO。

18.4.3 GPT模块配置

在FSP中对GPT6模块的配置如下图所示:

  1. 通道:6
  2. 模式:周期型,周期值:1kHz
  3. 初始占空比:50%
  4. 中断回调函数:gpt_timer6_callback

18.4.4 驱动程序

  1. 初始化

本次实验的初始化程序如下:

void GptPWMDrvInit(void)
{fsp_err_t err = g_timer6.p_api->open(g_timer6.p_ctrl, g_timer6.p_cfg);if(FSP_SUCCESS != err)printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);err = g_timer6.p_api->infoGet(g_timer6.p_ctrl, &gTimerInfo);if(FSP_SUCCESS != err)printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);gPeriod = gTimerInfo.period_counts;gStep = gPeriod/1500;err = g_timer6.p_api->start(g_timer6.p_ctrl);if(FSP_SUCCESS != err)printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);
}
  • 第03行:使用open函数初始化GPT6的配置;
  • 第07行:获取GPT6的初始配置,最重要的是获取到周期数值;
  • 第11行:根据周期数值和预期的呼吸灯效果,设计为逐渐加强和逐渐减弱的时间都为1.5s;
  • 第13行:开启定时器计数;
  1. 中断回调函数

    本次实验以1kHz频率触发溢出中断,每次中断都要修改PWM的占空比来达到LED亮度的增强和减弱,代码如下:

void gpt_timer6_callback(timer_callback_args_t *p_args)
{/* TODO: add your own code here */if(p_args->event == TIMER_EVENT_CYCLE_END){if(gDir)gPulse -= gStep;elsegPulse += gStep;if(gPulse <= 0)gDir = false;else if(gPulse >= gPeriod)gDir = true;fsp_err_t err = g_timer6.p_api->dutyCycleSet(g_timer6.p_ctrl, gPulse, GPT_IO_PIN_GTIOCA);if(FSP_SUCCESS != err)printf("Function:%s\tLine:%d\r\n", __FUNCTION__, __LINE__);}
}
  • 第04行:判断触发中断的是否是周期性计数溢出触发的;
  • 第06~13行:根据占空比的数值决定本次是处于亮度增强期还是减弱期,如果是增强期则增加占空比,否则减小占空比;
  • 第14行:调用函数修改PWM的占空比;

18.4.5 测试结果

本次实验需要在实际硬件上验证。在本书配套的开发板上运行此程序可以发现LED以大约1.5s的时间从暗状态逐渐增强到最亮,然后又花1.5s的时间逐渐减弱到暗状态。


本章完

相关文章:

第18章_瑞萨MCU零基础入门系列教程之GPT

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…...

openssl websockets

1. HTTPS通信的C实现 - 知乎 GitHub - Bwar/Nebula: Nebula is a powerful framwork for building highly concurrent, distributed, and resilient message-driven applications for C....

Vue 组件的单元测试

1、基本的示例 单元测试是软件开发非常基础的一部分。单元测试会封闭执行最小化单元的代码&#xff0c;使得添加新功能和追踪问题更容易。Vue 的单文件组件使得为组件撰写隔离的单元测试这件事更加直接。它会让你更有信心地开发新特性而不破坏现有的实现&#xff0c;并帮助其他…...

海底两万里的思维导图,轻松了解整体的内容

《海底两万里》是一部经典的科幻小说。小说以其丰富的想象力和对海底世界的描绘而闻名于世。今天我们就用思维导图的分支介绍这个作品到底讲了什么。&#xff08;思维导图示例&#xff1a;迅捷画板&#xff09; 《海底两万里》是“凡尔纳三部曲”中的第二部&#xff08;其它两部…...

ZABBIX 6.4官方安装文档

一、官网地址 Zabbix&#xff1a;企业级开源监控解决方案 二、下载 1.选择您Zabbix服务器的平台 2. Install and configure Zabbix for your platform a. Install Zabbix repository # rpm -Uvh https://repo.zabbix.com/zabbix/6.4/rhel/8/x86_64/zabbix-release-6.4-1.el8…...

本地MQTT服务器搭建(EMQX)

一、下载EMQX 下载地址&#xff1a;EMQ (emqx.com) 打开官网后&#xff0c;选择右边的免费试用按钮 然后单击EMQX Enterprise标签&#xff0c;然后选择下面的EMQX开源版&#xff0c;选择开源版的系统平台为Windows&#xff0c;单击免费下载。 在新页面下单击立即下载 二、安装…...

Docker启动pandora并指定ACCESS TOKEN

把chatGPT_ACCESS_TOKEN改成你的ACCESS_TOKEN 《chatGPT ACCESS TOKEN获取地址&#xff08;需要魔法&#xff09;》 docker run -d -m 512m -p 88:88 --privilegedtrue -e PANDORA_SERVER0.0.0.0:88 -e PANDORA_ACCESS_TOKENchatGPT_ACCESS_TOKEN --name pandora pengzhile/pa…...

Python + Jmeter 实现自动化性能压测

Step01: Python脚本开发 文件路径&#xff1a;D://wl//testproject//Fone-grpc//project1//test_client.py Python 脚本作用&#xff1a; 通过 grpc 调用底层 c 的接口&#xff0c;做数据库的数据插入与查询操作&#xff0c;然后将返回的结果进行拼接与输出。 2.代码里面将…...

【Linux进行时】进程状态

进程状态&#xff1a; ❓假设我们在上课&#xff0c;在B站上上课&#xff0c;请问我们的B站是不是一直运行呢&#xff1f;&#x1f4a1;不是的&#xff01; ❓假设我们同时打开了B站和PDF阅读器时&#xff0c;是怎么运行的呢&#xff1f; &#x1f4a1;每一个进程在CPU跑一会&a…...

HarmonyOS开发环境搭建

一 鸿蒙简介&#xff1a; 1.1 HarmonyOS是华为自研的一款分布式操作系统&#xff0c;兼容Android&#xff0c;但又区别Android&#xff0c;不仅仅定位于手机系统。更侧重于万物物联和智能终端&#xff0c;目前已更新到4.0版本。 1.2 HarmonyOS软件编程语言是ArkTS&#xff0c…...

友思特新闻|友思特与IDS深化战略合作伙伴关系

尊敬的客户和合作伙伴&#xff0c; 我们非常高兴地宣布&#xff0c;友思特已经与国际领先的机器视觉解决方案提供商 IDS 深化了我们的合作关系。 作为 IDS 的长期合作伙伴&#xff0c;友思特一直致力于为国内客户提供最先进的机器视觉技术和解决方案。 自从友思特与 IDS 合作…...

ARM Linux DIY(十三)Qt5 移植

前言 板子带有屏幕&#xff0c;那当然要设计一下 GUI&#xff0c;对 Qt5 比较熟悉&#xff0c;那就移植它吧。 移植 Qt5 buildroot 使能 Qt5&#xff0c;这里我们只开启核心功能 gui module --> widgets module 编译 $ make ODIY_V3S/ qt5base编译报错&#xff1a;找不…...

二,手机硬件参数介绍和校验算法

系列文章目录 第一章 安卓aosp源码编译环境搭建 第二章 手机硬件参数介绍和校验算法 第三章 修改安卓aosp代码更改硬件参数 第四章 编译定制rom并刷机实现硬改(一) 第五章 编译定制rom并刷机实现硬改(二) 第六章 不root不magisk不xposed lsposed frida原生修改定位 第七章 安卓…...

ubunutu20/18/22 编译android 5相关的问题汇总-千里马framework开源代码平板编译过程

hi&#xff0c;粉丝朋友们&#xff1a; 闲鱼50块钱淘到了一个开源平板&#xff0c;注意这个平板是有源码的&#xff0c;可以进行相关的编译修改。哈哈哈&#xff0c;马哥这边就体验了一下50块钱平板是否可以拿来做framework呢&#xff1f; 哈哈&#xff0c;说好就开干了&#x…...

tauri vue vite

准备 rust 根据 https://www.rust-lang.org/tools/install&#xff0c;安装 rust 执行 cargo --version 检查安装是否完成nodejs 安装 nodejstauri cargo install create-tauri-app --lockedcargo create-tauri-app 选择&#xff1a; ✔ Project name tauri-app ✔ Choose wh…...

名词解析与经验分享(前端)

目录 1.什么是sass产品 2.下面我想说说事件循环 3. cmd窗口的一些快捷键 4. 组件与插件的区别 5. vue项目嵌入app后调用app方法 6.点击编辑按钮直接回到顶部&#xff0c;输入框光标闪动聚焦 7.短轮询与长轮询 短轮询 长轮询 8.前端moment库 9.移动端-触底刷新实现核心…...

【前端】js下载url文件

不打开新窗口进行下载 function download(res) { var elemIF document.createElement("iframe"); elemIF.src res; elemIF.style.display "none"; document.body.appendChild(elemIF); } window.open(url, _blank); a标签 const ele …...

什么是 BSD 协议?

BSD开源协议是一个给于使用者很大自由的协议。可以自由的使用&#xff0c;修改源代码&#xff0c;也可以将修改后的代码作为开源或者专有软件再发布。当你发布使用了BSD协议的代码&#xff0c;或者以BSD协议代码为基础做二次开发自己的产品时&#xff0c;需要满足三个条件&…...

【网络教程】揭秘Windows SSH服务端免密登录:告别繁琐,享受安全连接

文章目录 开启Windows下的SSH服务端图形界面安装手动下载安装Windows如何查看系统用户名Windows如何查看本机IP开启免密登录Window生成秘钥Linux下生成秘钥配置公钥视频讲解开启Windows下的SSH服务端 这篇文章演示的环境是Windows11Windows的SSH服务端默认情况下是没有安装的,…...

使用键盘控制Franka机械臂运动

功能说明 使用键盘按键&#xff0c;可以控制franka机械臂7个关节角&#xff0c;已在真机上验证。 代码 主要使用的是官方包内的 franka_example_controllers 1、修改 include下的 joint_position_example_controller.h, 改为如下&#xff1a; // Copyright (c) 2017 Frank…...

力扣第45天----第392题、第115题

# 力扣第45天----第392题、第115题 文章目录 一、第392题--判断子序列二、第115题--不同的子序列 一、第392题–判断子序列 ​ 挺简单的&#xff0c;思路跟以前的都差不多。 class Solution { public:bool isSubsequence(string s, string t) {vector<vector<int>&g…...

扔掉你的开发板,跟我玩Mcore-全志h616

本文转载自WhyCan Forum(哇酷开发者社区)&#xff1a; https://whycan.com/t_10024.html 作者leefei 这是一个1.69寸触摸小电视。使用全志H616芯片&#xff0c;板上硬件有mpu6050陀螺仪&#xff0c;USB转ttl调试串口&#xff0c;一个USB接口&#xff0c;WIFI&蓝牙&#x…...

【Linux】网络篇:UDP、TCP 网络接口及使用

文章目录 socket 及 相关补充0. netstat - - 查询当前服务器上网络服务器1. 端口号&#xff08;port&#xff09;2. 网络字节序3. sockaddr 结构体 一、socket 常见 APIUDP0. IP 地址转化 函数1. socket 函数&#xff1a;创建 socket 文件描述符 (TCP/UDP, 客户端 服务器)2. b…...

卡尔曼滤波(Kalman Filter)原理浅析-数学理论推导-2

目录 前言数学理论推导卡尔曼增益超详细数学推导结语参考 前言 最近项目需求涉及到目标跟踪部分&#xff0c;准备从 DeepSORT 多目标跟踪算法入手。DeepSORT 中涉及的内容有点多&#xff0c;以前也就对其进行了简单的了解&#xff0c;但是真正去做发现总是存在这样或者那样的困…...

SQL 性能优化总结

文章目录 一、性能优化策略二、索引创建规则三、查询优化总结 一、性能优化策略 1. SQL 语句中 IN 包含的值不应过多 MySQL 将 IN中的常量全部存储在一个排好序的数组里面&#xff0c;但是如果数值较多&#xff0c;产生的消耗也是比较大的。所以对于连续的数值&#xff0c;能用…...

MYSQL事务隔离级别分析

MYSQL事务隔离级别分析 不可重复读和幻读的区别&#xff1f; 不可重复读和幻读的区别&#xff1f; 先理解几个概念 不可重复读 一个事务中&#xff0c;后续查询结果得到不同的数据&#xff0c;可被重复读隔离级别解决幻影 出现在查询结果集中但不出现在较早查询的结果集中的行幻…...

学习javaEE初阶的第一堂课

学习金字塔 java发展简史 Java最初诞生的时候是用来写前端的!! 199x年 199x年,互联网还处在比较早期的阶段,当时主流的编程语言是 C/C, 有个大佬要搞个"智能面包机",觉得用C来做太难了 于是就基于C搞了个简单点的语言,Java 就诞生了~~ 遗憾的是项目流产了,没做成…...

请问一下就是业务概念模型和业务逻辑模型有啥关系

请问一下就是业务概念模型和业务逻辑模型有啥关系&#xff1f; 业务概念模型和业务逻辑模型是业务建模的两个关键组成部分&#xff0c;两者密切相关但又有所不同。 1.业务概念模型&#xff1a;这是对业务术语、定义和关系的一种抽象表示。它是从业务专家那里获得的知识&#…...

3.2 Android eBPF程序类型

写在前面 为什么要先了解eBPF程序类型? 从帮助函数中,我们可能基于内核的eBPF开放API,对eBPF的能力有一个比较细致的认识,但是这并不能让我们从全局,或者更概括的认识eBPF。eBPF程序类型能够更宏观的告诉我们,eBPF能做哪些事情(除网络相关)。 一,eBPF程序类型 内核…...

多目标优化算法:基于非支配排序的小龙虾优化算法(NSCOA)MATLAB

一、小龙虾优化算法COA 小龙虾优化算法&#xff08;Crayfsh optimization algorithm&#xff0c;COA&#xff09;由Jia Heming 等人于2023年提出&#xff0c;该算法模拟小龙虾的避暑、竞争和觅食行为&#xff0c;具有搜索速度快&#xff0c;搜索能力强&#xff0c;能够有效平衡…...

wordpress分享到/网络营销的特点

Redis是一个不错的缓存数据库&#xff0c;读取数据速度效率都很不错。今天大家共同研究下redis的用法。结合网上的资料和自己的摸索&#xff0c;先来看下安装与配置把。 咱们主要看在WINDOWS上怎样使用REDIS数据库。 下载地址&#xff1a;https://github.com/dmajkic/redis/dow…...

新西兰做网站代购/湖南中高风险地区

题目描述 兄弟俩骑车郊游&#xff0c;弟弟先出发&#xff0c;每分钟X米&#xff0c;M分钟后&#xff0c;哥哥带一条狗出发。以每分钟Y米的速度去追弟弟&#xff0c;而狗则以每分钟Z米的速度向弟弟跑去&#xff0c;追上弟弟后又立即返回&#xff0c;直到哥哥追上弟弟时&#xff…...

连云港做网站优化/排行榜123网

一、将数据库中的Date格式的数据&#xff0c;或者指定日期的字符串格式化为想要的样式DATE_FORMAT (date, format)能根据格式串format 格式化日期或日期和时间值date&#xff0c;返回结果字符串。可用DATE_FORMAT( ) 来格式化DATE 或DATETIME 值&#xff0c;以便得到所希望的格…...

潍坊网站建设联系方式/aso优化吧

最近在研究 Yii 的权限控制功能&#xff0c;尽管Yii 自身提供了一个简单的权限管理&#xff0c;但是很多时候&#xff0c;我们还是需要对其做一点扩展。 在这里&#xff0c;我向大家推荐一个不错的扩展&#xff1a;SRBAC。 在Yii的官方网站的extension模块下&#xff0c;你可以…...

做app推广上哪些网站吗/2345浏览器网站进入

1001&#xff1a;枚举保留题目的集合&#xff0c;然后模拟&#xff08;二进制状态压缩 暴力所选的问题k 0~1<<m-1。再把n个人的状态进行按位&&#xff09; 1002&#xff1a;直接在输入的时候扫一遍就行了&#xff0c;顺便用前缀和统计出每个字母的出现次数 &#xff…...

绵阳企业品牌网站建设/武汉百度推广代运营

你发现了吗&#xff1f;抖音开始关注老年化群体了&#xff0c;征集60岁以上的老人共同参与新项目的制作。的确&#xff0c;在互联网的产品日益增多的今天&#xff0c;应该考虑不同年龄层的使用体验。而电子邮箱作为具有30年经验的产品&#xff0c;第一批的60后、70后使用者如今…...