900a187f4c49a761e930f9a0155472dc
PWM模块介绍
参考<<Renesas RA2L1 Group User’s Manual: Hardware>>的章节<<320. General PWM Timer (GPT)>>
特征
- 4通道GPT32,6通道GPT16
- 计数器可递增,递减(锯齿波),先递增后递减(三角波)
- 可作为通用定时器《也可以用于控制无刷电机。
- 每个通道时钟独立配置
- 配个通道两个输入或者输出引脚,对应两个输入捕获或者输出比较寄存器
- 两个捕获比较寄存器对应有4个缓冲寄存器,可在波顶点和波谷进行切换,用于产生不对称波形
- 每个通道独立设置周期,可在上下溢出产生中断
- PWM死区产生
- 同步启动、停止和清除任意通道的计数器
- 计数开始、计数停止、计数清除计数、上计数、下计数或输入捕获操作可以响应4各ELC
- 根据两个输入引脚的状态,进行计数开始、计数停止、计数清除、上计数、下计数或输入捕获操作
- 计数启动、计数停止、计数清除、上计数、下计数或输入捕获操作可以响应两个外部触发输入
- 输出引脚之间检测到短路,可以自动禁用输出功能
- 可产生用于控制无刷直流电机的PWM波形
- 比较匹配A和D事件,溢出/下流事件,以及输入的UVW边缘事件可以输出到ELC
- 启用用于输入捕获和输入UVW的噪声滤波器
- 总线时钟: PCLKB,核心时钟: PCLKD
框图
相关引脚
寄存器
GTWP:写保护寄存器
GTSTR:软件启动计数器
GTSTP:软件停止计数器
GTCLR:软件清除计数器
GTSSR:配置计数启动源,引脚状态或者软件GTSTR
GTPSR:配置计数停止源,引脚状态或者软件GTSTP
GTCSR:配置计数清除源,引脚状态或者软件GTCLR
GTUPSR:计数器上计数源选择
GTDNSR:计数器下计数源选择
GTICASR:输入捕获源选择A
GTICBSR:输入捕获源选择B
GTCR:定时器模式,分频,启动配置
GTUDDTYC:计数方向,占空比设置
GTIOR:引脚相关配置
GTINTAD:中断配置
GTST:状态寄存器
GTBER:buffer使能
GTCNT:计数器
GTPR:周期设置
GTPBR:周期buffer
GTDTCR:死区控制
GTDVU:死区时间
OPSCR:输出相位控制
操作过程
- 使能模块时钟MSTPCRD.MSTPD5 b5 MSTPCRD.MSTPD6 b6 设置为0分别对应使能GPT32n和 GPT164
- 引脚配置
控制P501 产生呼吸灯效果,相应的引脚功能配置为GPT
对应GTP2
- PWM相关寄存器配置
直接基于寄存器进行操作
\ra_cfg\fsp_cfg\bsp\bsp_mcu_family_cfg.h中定义了
#define BSP_MCU_GROUP_RA2L1 (1)
\ra\fsp\src\bsp\cmsis\Device\RENESAS\Include\renesas.h中
#elif BSP_MCU_GROUP_RA2L1
#include "R7FA2L1AB.h"
包含了 #include "R7FA2L1AB.h"
该头文件定义了各外设寄存器基地址
PWM寄存器组结构体是R_GPT
#define R_GPT0 ((R_GPT0_Type *) R_GPT0_BASE)
所以直接寄存器操作包含renesas.h即可。
代码如下
void pwm_init(void)
{
rt_kprintf("PCLKD:%d\r\n",BSP_STARTUP_PCLKD_HZ);
R_MSTP->MSTPCRD_b.MSTPD5 = 0;
R_PMISC->PWPR_b.B0WI = 0;
R_PMISC->PWPR_b.PFSWE = 1;
R_PFS->PORT[5].PIN[1].PmnPFS_b.ASEL = 0;
R_PFS->PORT[5].PIN[1].PmnPFS_b.PSEL = 3;
R_PFS->PORT[5].PIN[1].PmnPFS_b.PCR = 1;
R_PFS->PORT[5].PIN[1].PmnPFS_b.PMR = 1;
R_PFS->PORT[5].PIN[1].PmnPFS_b.PDR = 1;
R_PMISC->PWPR_b.PFSWE = 0;
R_PMISC->PWPR_b.B0WI = 1;
R_GPT2->GTWP_b.PRKEY = 0xA5;
R_GPT2->GTWP_b.WP = 0;
R_GPT2->GTSSR_b.CSTRT = 1;
R_GPT2->GTPSR_b.CSTOP = 1;
R_GPT2->GTCSR_b.CCLR = 1;
R_GPT2->GTSTP_b.CSTOP2 = 1; //stop
//R_GPT2->GTSTR_b.CSTRT2 = 1;
R_GPT2->GTCLR_b.CCLR2 = 1;
//R_GPT2->GTUPSR_b.
//R_GPT2->GTDNSRR_b.
//GTICASR
//GTICBSR
R_GPT2->GTCR_b.CST = 1;
R_GPT2->GTCR_b.MD=0; //Saw-wave PWM mode (single buffer or double buffer possible)
/*PCLKD 48MHz
0 0 0: PCLKD/1
0 0 1: PCLKD/4
0 1 0: PCLKD/16
0 1 1: PCLKD/64
1 0 0: PCLKD/256
1 0 1: PCLKD/1024
*/
R_GPT2->GTCR_b.TPCS = 0;
R_GPT2->GTUDDTYC_b.UD = 1; //UPOBDTY[1:0]
R_GPT2->GTUDDTYC_b.OBDTY = 0; //GTIOCnB pin duty depends on the compare match
R_GPT2->GTIOR_b.GTIOB=0x0F;
R_GPT2->GTIOR_b.OBDFLT=0;
R_GPT2->GTIOR_b.OBHLD=0;
R_GPT2->GTIOR_b.OBE=1;
R_GPT2->GTCNT=0;
R_GPT2->GTCCR[1]=1000;
R_GPT2->GTPR=2000;
R_GPT2->GTWP_b.WP = 1;
R_GPT2->GTWP_b.PRKEY = 0x00;
}
void pwm_set(uint32_t duty,uint32_t period)
{
R_GPT2->GTWP_b.PRKEY = 0xA5;
R_GPT2->GTWP_b.WP = 0;
R_GPT2->GTSTP_b.CSTOP2 = 1; //stop
R_GPT2->GTCLR_b.CCLR2 = 1; //clear
R_GPT2->GTCCR[1]=duty;
R_GPT2->GTPR=period;
R_GPT2->GTSTR_b.CSTRT2 = 1; //start
R_GPT2->GTWP_b.WP = 1;
R_GPT2->GTWP_b.PRKEY = 0x00;
}
测试
void hal_entry(void)
{
rt_kprintf("\nHello RT-Thread!\n");
pwm_init();
while (1)
{
static uint32_t duty=0;
for(int i=0;i<100;i++)
{
pwm_set(duty,4800);
rt_thread_mdelay(10);
duty += 4800/100;
}
for(int i=0;i<100;i++)
{
pwm_set(duty,4800);
rt_thread_mdelay(10);
duty -= 4800/100;
}
}
}
总结
本文介绍了RA2L1的GPT模块,并以一个呼吸灯为实例,直接基于寄存器操作实现,这有助于理解模块。
实际该芯片的PWM是非常强大的,比如可以支持3相无刷电机的控制,本文只是以一个最简单的例子,作为引子,目的是讲解如何根据芯片手册,
一步一步实现模块的驱动,当然更复杂的应用场景也就可以按照实际实现。