您现在的位置是:首页 >技术杂谈 >【致敬未来的攻城狮计划】— 连续打卡第十八天:FSP固件库开发GPT — PWM输出波形 — LED呼吸灯网站首页技术杂谈
【致敬未来的攻城狮计划】— 连续打卡第十八天:FSP固件库开发GPT — PWM输出波形 — LED呼吸灯
系列文章目录
1.连续打卡第一天:提前对CPK_RA2E1是瑞萨RA系列开发板的初体验,了解一下
5.Keil配置使用(使用 RASC 生成 Keil 工程)
6.Keil配置使用(使用 RASC 生成 Keil 工程)
8.问题解决、学习RA寄存器、用寄存器的方式点亮第一个LED灯。
15.FSP固件库外部中断处理编程(外部中断检测按键控制LED闪烁)
文章目录
前言
继前一篇文章 17.FSP固件库开发GPT — PWM通用定时器 定时2s LED 闪烁 我们具体讲解了定时如何使用,如何定时定多长时间,什么计算,FSP库如何开发,不过只是做了一个开发的讲解,并没有探讨到更深沉的地方,写文章的效果一个是想让大家扫盲,对RA2E1进行一个整体的理解扫盲,更深沉的理解将会在后续具体的项目运营中讲述,
上次的文章讲的是 PWM作为定时器使用,这次我们讲一下PWM作为输出使用,输出波形,但是由于身边没有示波器,所以这次没有视频效果。
具体的大家也可以关注 我的公众号:嵌入式up(提供我自己写的例程 和 技术支持探讨)
一、PWM是什么?
下面这么文章也讲解到了PWM是什么。大家可以移步前往。
17. FSP固件库开发GPT — PWM通用定时器 定时2s LED 闪烁
学过单片机的大家伙,对pwm这个肯定不陌生,所以这里不再赘述,大家也可以翻阅上篇文章,上篇文章详细介绍到了。
二、FSP固件库开发(PWM输出波形 — LED呼吸灯)
1.新建工程
硬件图:
2.FSP配置
如果常 P501 报红色 是因为 引脚之前被配置好了 需要取消之前的配置
这样就可以了。
按顺序依次选择,生成PWM模块。双击属性,最大化配置框。依次配置General,Output,Pins。实现1秒一个周期,占空比50%,在P501输出。
点击此按钮可查询新建的端口可以使用的所有函数:
Pin Output Support:这一项配置允许输出 PWM 信号到引脚,我们改为使能引脚输出。
Name 和 Channel:这两项分别设置 GPT 模块名字为 “g_timer_gpt5” 和选择第 5 个 GPT 定时器(第6个通道)。
Mode:配置 GPT 的工作模式为 PWM 输出模式。
Period 和 Period Unit:我们将PWM频率设为 20 KHz, 因此“Period”设置为 20,单位“Period Unit”设置为 Kilohertz,即千赫兹(KHz)。
GTIOCB Output Enabled:使能 GTIOCB 输出。
GTIOCB Stop Level:设置定时器停止时 GTIOCB 输出的电平为低电平。
GTIOC6B:选择连接到 P600 引脚,这个软件会自动设置的,我们只要确认了就好。
3.代码
#include "hal_data.h"
#include "r_gpt.h"
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER
typedef enum
{
SYS_DELAY_UNITS_SECONDS = 200000000, ///< Requested delay amount is in seconds
SYS_DELAY_UNITS_MILLISECONDS = 200000, ///< Requested delay amount is in milliseconds
SYS_DELAY_UNITS_MICROSECONDS = 200 ///< Requested delay amount is in microseconds
} sys_delay_units_t;
/* 定义变量 */
uint32_t IT_Period;
uint32_t IT_nums;
/**
* @brief 延时程序
* @param delay: 延时的单位时间
* @param unit: 延时的单位
* @retval 无
*/
void SysTick_Delay(uint32_t delay, sys_delay_units_t unit)
{
uint32_t SumTime = delay * unit; //计算总延时时间(单位为时钟节拍数)
IT_nums = SumTime/IT_Period;
while (IT_nums != 0);
}
/**
* @brief SysTick的中断服务函数
* @param 无
* @retval 无
*/
extern void SysTick_Handler(void); //需要先extern声明一下避免编译器警告
void SysTick_Handler(void)
{
IT_nums++;
if (IT_nums == 2000)
{
IT_nums = 0;
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_05_PIN_01, BSP_IO_LEVEL_HIGH); //LED1亮
}
else
{
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_05_PIN_01, BSP_IO_LEVEL_LOW); //LED1亮
}
}
/**
* @brief 启动系统滴答计时器 SysTick
* @param IT_frequency: 滴答计时器每秒的中断次数
* @retval 无
*/
void SysTick_Init(uint32_t IT_frequency)
{
/* SystemCoreClock在这里默认为200M
* SystemCoreClock / 1000 1ms中断一次
* SystemCoreClock / 100000 10us中断一次
* SystemCoreClock / 1000000 1us中断一次
*/
IT_Period = SystemCoreClock / IT_frequency;
uint32_t err = SysTick_Config (IT_Period);
assert(err==0); //capture error
}
/** 自定义函数:设置PWM占空比
@param duty 占空比范围:0~100 %
*/
void GPT_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_gpt5_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_gpt5_ctrl, duty_cycle_counts, GPT_IO_PIN_GTIOCB);
}
void GPT_PWM_Init(void)
{
/* 初始化 GPT 模块 */
R_GPT_Open(&g_timer_gpt5_ctrl, &g_timer_gpt5_cfg);
/* 启动 GPT 定时器 */
R_GPT_Start(&g_timer_gpt5_ctrl);
}
void breathing_LED(void)
{
uint8_t duty = 0;
uint8_t step = 5;
GPT_PWM_Init();
while(1)
{
if(duty == 100)
step = 0;
else if(duty == 0)
step = 10;
duty += step;
GPT_PWM_SetDuty(duty);
R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MICROSECONDS);
}
}
/*******************************************************************************************************************//**
* main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used. This function
* is called by main() when no RTOS is used.
**********************************************************************************************************************/
void hal_entry(void) //相当于主函数 函数最终执行的地方
{
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_05_PIN_02, BSP_IO_LEVEL_LOW); //LED1亮
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_05_PIN_01, BSP_IO_LEVEL_LOW); //LED1亮
R_BSP_PinAccessEnable (); //启用对PFS寄存器的访问,因为后面写IO口都用BSP内联函数
fsp_err_t err = FSP_SUCCESS;
uint8_t ndt = 30;
uint8_t step = 10;
/* PWM On*/
/* 初始化 GPT 模块 */
err = R_GPT_Open(&g_timer_gpt5_ctrl, &g_timer_gpt5_cfg);
assert(err == FSP_SUCCESS);
R_GPT_Start(&g_timer_gpt5_ctrl);
R_BSP_SoftwareDelay(20, BSP_DELAY_UNITS_MILLISECONDS);
err = R_GPT_PeriodSet(&g_timer_gpt5_ctrl,2000);
assert(err == FSP_SUCCESS);
R_BSP_SoftwareDelay(20, BSP_DELAY_UNITS_MILLISECONDS);
/* 最后调用FSP库函数设置占空比 */
R_GPT_DutyCycleSet(&g_timer_gpt5_ctrl, 20*(100-ndt), GPT_IO_PIN_GTIOCB);
assert(err == FSP_SUCCESS);
R_BSP_SoftwareDelay(20, BSP_DELAY_UNITS_MILLISECONDS);
err = R_GPT_Reset(&g_timer_gpt5_ctrl);
assert(err == FSP_SUCCESS);
R_BSP_SoftwareDelay(20, BSP_DELAY_UNITS_MILLISECONDS);
while(1){
R_BSP_SoftwareDelay(200, BSP_DELAY_UNITS_MILLISECONDS);
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_05_PIN_01, BSP_IO_LEVEL_HIGH);
R_BSP_SoftwareDelay(200, BSP_DELAY_UNITS_MILLISECONDS);
R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_05_PIN_01, BSP_IO_LEVEL_LOW);
err = R_GPT_DutyCycleSet(&g_timer_gpt5_ctrl, 20*(100-ndt), GPT_IO_PIN_GTIOCB);
assert(err == FSP_SUCCESS);
R_BSP_SoftwareDelay(20, BSP_DELAY_UNITS_MILLISECONDS);
ndt += step;
if(ndt >= 100 || ndt <= 0)
step = -step;
// R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_05_PIN_02, BSP_IO_LEVEL_HIGH);
// R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS);
// R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_05_PIN_02, BSP_IO_LEVEL_LOW);
// R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS);
}
视频效果:
RA2E1开发板 呼吸灯成就
总结
pwm呼吸灯成就达成,继续努力!