本帖最后由 qintian0303 于 2024-10-13 21:47 编辑
#申请原创# @21小跑堂 @21小跑堂 @21小跑堂
往期回顾
【CPKCOR-RA8D1B核心板】1、板卡基本信息
【CPKCOR-RA8D1B核心板】2、搭建开发环境
【CPKCOR-RA8D1B核心板】3、离不开的点灯——GPIO输出操作
【CPKCOR-RA8D1B核心板】4、另一种闪烁——非阻塞式闪烁
呼吸灯的效果还是很迷人的,那么什么是呼吸灯?又要如何实现呢?
PWM控制LED呼吸灯的原理主要是基于LED灯对电流的瞬时响应以及人眼的视觉暂留效应。具体来说,PWM通过改变LED灯的导通时间(即高电平持续时间)来控制其亮度。当高电平持续时间较短时,LED灯的亮度较低;当高电平持续时间较长时,LED灯的亮度较高。因此,通过连续调节高电平的持续时间,就可以实现对LED灯亮度的连续调节,从而产生呼吸灯效果。人眼在观察快速变化的图像时,具有一种称为“视觉暂留”的生理现象。即当光信号快速闪烁时,人眼并不会立即感知到这种闪烁,而是会将多个短暂的光信号在视觉上进行平均或融合,从而感知到一个平均的亮度水平。结合LED的快速响应和人眼的视觉暂留效应,当PWM信号的占空比(即高电平时间与整个周期时间的比例)发生变化时,虽然LED灯实际上是在不断地开关(即发光和不发光之间快速切换),但人眼感知到的是一个平均的亮度。
所以本章节通过实现呼吸灯的方式体验CPKCOR-RA8D1B核心板的PWM功能,PWM功能属于定时器的高级功能之一。通用 PWM 定时器(GPT,General PWM Timer)是 RA MCU 的其中一种 32/16 位的定时器外设。 在 GPT 当中,可分为 GPT32 和 GPT16,它们最主要的区别是计数器的不同。 GPT32 是 32 位的定时器,包含的计数器是 32 位的,所能计数的范围为:0 ~ 0xFFFF_FFFF; 而 GPT16 是 16 位的定时器,包含的计数器是 16 位的,所能计数的范围为:0 ~ 0xFFFF。
定时器(Timer)最基本的功能就是定时,咱们在上一节已经体验。 如果把定时器与 GPIO 引脚结合起来使用的话可以实现更加丰富的功能, 可以对输入信号进行计数,可以测量输入信号的脉冲宽度,可以输出单个脉冲、PWM 等波形,等等。 通过定时器生成 PWM 波形信号来控制电机状态是工业控制的普遍方法,这方面知识非常值得深入了解。GPT 模块可用于计数事件、测量外部输入信号、作为通用计时器并产生周期性中断、以及输出周期性或 PWM 信号到 特定的引脚。不过控制的不是板载的灯,应为PA01不是PWM的输出通道,无法复用,最终我们选择的是:
PWM 输出需要使用 IO 引脚进行输出,因此需要先在“Pins”配置页中为 GPT 配置引脚, 我们将 GPT4 的 GTIOC4B 信号输出连接到 P301 引脚::
在“Stacks”配置页中加入 GPT 模块:
其属性和AGT相同,主要配置如下:
图中需要更改的配置如下:
Pin Output Support:这一项配置允许输出 PWM 信号到引脚,我们改为使能引脚输出。
Name和 Channel:这两项分别设置 GPT 模块名字为 “g_timer_gpt4” 和选择第 4 个 GPT 定时器(第4个通道)。
Mode:配置 GPT 的工作模式为 锯齿波PWM 输出模式。
Period和 Period Unit:我们将PWM频率设为 22 KHz, 因此“Period”设置为 20,单位“Period Unit”设置为 Kilohertz,即千赫兹(KHz)。
GTIOCB Output Enabled:使能 GTIOCB 输出。
GTIOCB Stop Level:设置定时器停止时 GTIOCB 输出的电平为低电平。
GTIOC6B:选择连接到 P301 引脚,这个软件会自动设置的,我们只要确认了就好。
接下来我们只要其中定时器就可以了:
void GPT4_PWM_SetDuty(uint8_t duty){
timer_info_t info;
uint32_t current_period_counts;
uint32_t duty_cycle_counts;
if (duty > 100)
duty = 100; //限制占空比范围:0~100
/* 获得GPT的信息 */
R_GPT_InfoGet(&g_timer_GPT4_ctrl, &info);
/* 获得计时器一个周期需要的计数次数 */
current_period_counts = info.period_counts;
/* 根据占空比和一个周期的计数次数计算GTCCR寄存器的值 */
duty_cycle_counts = (uint32_t)(((uint64_t) current_period_counts * duty) / 100);
/* 最后调用FSP库函数设置占空比 */
R_GPT_DutyCycleSet(&g_timer_GPT4_ctrl, duty_cycle_counts, GPT_IO_PIN_GTIOCB);
}
R_GPT_Open(&g_timer_GPT4_ctrl, &g_timer_GPT4_cfg);
R_GPT_Start(&g_timer_GPT4_ctrl);
GPT4_PWM_SetDuty(20);
到这里就配置完成了:
上体可以看出P301引脚的输出与咱们的配置参数一致,接下来进行呼吸灯实验的只需要通过AGT定时中不断修改占空比就可以了,硬件上在P301引脚连接一个外部LED的控制引脚,由于没有对应的扩展板,最好是选用JA和JD的扩展引脚,毕竟好连接一点。
为了更好的实现2s一次的呼吸效果,我们将AGT定时改为了10ms,并在中断中进行如下处理:
void g_timer0_Callback(timer_callback_args_t * p_args){
if (TIMER_EVENT_CYCLE_END == p_args->event){
LED.timercnt++;
if(LED.timercnt >= 100){
LED.timercnt = 0;
LED.flag = 1;
LED.cnt++;
}
BreathLED.cnt++;
if(BreathLED.cnt>5 && BreathLED.cnt<=95){
GPT4_PWM_SetDuty(BreathLED.cnt);
}
else if(BreathLED.cnt>105 && BreathLED.cnt<=195){
GPT4_PWM_SetDuty(200-BreathLED.cnt);
}
else if(BreathLED.cnt >= 200)
BreathLED.cnt = 0;
}
}
效果如下:
|