打印

【CPKCOR-RA8D1B核心板】5、不一样的点灯系列——点呼吸灯

[复制链接]
1569|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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;
    }
}
      效果如下:

  

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:硬件工程师
简介:有着多年硬件开发经验的专业人员,专注于医疗电子领域,热衷于对新鲜事物的探索,喜欢DIY!

268

主题

1607

帖子

8

粉丝