parent
c5933a652c
commit
84daab189d
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
Binary file not shown.
After Width: | Height: | Size: 79 KiB |
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
|
@ -159,3 +159,30 @@
|
|||
3. 修改通道号为 0,与 DAC0 对应
|
||||
|
||||
![img](picture/dac_config2.png)
|
||||
|
||||
|
||||
## 通用 PWM 定时器(GPT)
|
||||
|
||||
GPT 定时器在该芯片中可作为通用定时器,也可以用于产生 PWM 信号。在将其用于产生 PWM 信号时,GPT 定时器提供了 gpt0 - gpt9 总共 10 个通道,每个通道可以设定两个输出端口。当前版本的 PWM 驱动将每个通道都看做一个单独的 PWM 设备,每个设备都只有一个通道。用户可以选择开启一个通道的任意一个输出端口,或将两个端口均开启,但在同时开启两个端口的情况下,它们输出的波形将完全一致。
|
||||
|
||||
1. 添加 GPT 设备
|
||||
|
||||
![img](./picture/add_gpt1.png)
|
||||
|
||||
2. 配置通道
|
||||
|
||||
![img](./picture/add_gpt2.png)
|
||||
|
||||
对 GPT 较为关键的配置如图所示,具体解释如下:
|
||||
|
||||
1. 将 ```Common``` -> ```Pin Output Support``` 设置为 Enable ,以开启 PWM 波形的输出。
|
||||
2. 指定 GPT 通道,并根据通道数指定 GPT 的名称,例如此处指定 GPT 通道 3 ,所以 GPT 的名称必须为 ```g_timer3```。并且将定时器模式设置为 PWM ,并指定每个 PWM 周期的计数值。
|
||||
3. 设定 PWM 通道默认输出的占空比,这里为 50% 。
|
||||
4. 设定 GPT 通道下两个输出端口的使能状态。
|
||||
5. 此处设置 GPT 通道下两个输出端口各自对应的引脚。
|
||||
|
||||
3. 配置输出引脚
|
||||
|
||||
![img](./picture/add_gpt3.png)
|
||||
|
||||
在完成上一步对 GPT 定时器的设置后,根据图示找到对应 GPT 通道输出引脚设置的界面(这里是 GPT3),将图中标号 **1** 处设置为 ```GTIOCA or GTIOCB``` ,并根据需要在图中标号 **2** 处设置 GPT 通道下两个输出端口各自对应的输出引脚。
|
|
@ -17,6 +17,15 @@ menu "Hardware Drivers Config"
|
|||
select RT_USING_PIN
|
||||
default y
|
||||
|
||||
config BSP_USING_ONCHIP_FLASH
|
||||
bool "Enable Onchip FLASH"
|
||||
default n
|
||||
|
||||
config BSP_USING_WDT
|
||||
bool "Enable Watchdog Timer"
|
||||
select RT_USING_WDT
|
||||
default n
|
||||
|
||||
menuconfig BSP_USING_UART
|
||||
bool "Enable UART"
|
||||
default y
|
||||
|
@ -73,11 +82,6 @@ menu "Hardware Drivers Config"
|
|||
endif
|
||||
endif
|
||||
|
||||
config BSP_USING_WDT
|
||||
bool "Enable Watchdog Timer"
|
||||
select RT_USING_WDT
|
||||
default n
|
||||
|
||||
menuconfig BSP_USING_ONCHIP_RTC
|
||||
bool "Enable RTC"
|
||||
select RT_USING_RTC
|
||||
|
@ -141,9 +145,52 @@ menu "Hardware Drivers Config"
|
|||
default n
|
||||
endif
|
||||
|
||||
config BSP_USING_ONCHIP_FLASH
|
||||
bool "Enable Onchip FLASH"
|
||||
menuconfig BSP_USING_PWM
|
||||
bool "Enable PWM"
|
||||
default n
|
||||
select RT_USING_PWM
|
||||
if BSP_USING_PWM
|
||||
config BSP_USING_PWM0
|
||||
bool "Enable GPT0 (32-Bits) output PWM"
|
||||
default n
|
||||
|
||||
config BSP_USING_PWM1
|
||||
bool "Enable GPT1 (32-Bits) output PWM"
|
||||
default n
|
||||
|
||||
config BSP_USING_PWM2
|
||||
bool "Enable GPT2 (32-Bits) output PWM"
|
||||
default n
|
||||
|
||||
config BSP_USING_PWM3
|
||||
bool "Enable GPT3 (32-Bits) output PWM"
|
||||
default n
|
||||
|
||||
config BSP_USING_PWM4
|
||||
bool "Enable GPT4 (16-Bits) output PWM"
|
||||
default n
|
||||
|
||||
config BSP_USING_PWM5
|
||||
bool "Enable GPT5 (16-Bits) output PWM"
|
||||
default n
|
||||
|
||||
config BSP_USING_PWM6
|
||||
bool "Enable GPT6 (16-Bits) output PWM"
|
||||
default n
|
||||
|
||||
config BSP_USING_PWM7
|
||||
bool "Enable GPT7 (16-Bits) output PWM"
|
||||
default n
|
||||
|
||||
config BSP_USING_PWM8
|
||||
bool "Enable GPT8 (16-Bits) output PWM"
|
||||
default n
|
||||
|
||||
config BSP_USING_PWM9
|
||||
bool "Enable GPT9 (16-Bits) output PWM"
|
||||
default n
|
||||
endif
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Board extended module Drivers"
|
||||
|
|
|
@ -9,14 +9,14 @@ src = Split("""
|
|||
drv_common.c
|
||||
""")
|
||||
|
||||
if GetDepend(['BSP_USING_SERIAL']):
|
||||
if GetDepend(['BSP_USING_UART']):
|
||||
if GetDepend(['RT_USING_SERIAL_V2']):
|
||||
src += ['drv_usart_v2.c']
|
||||
else:
|
||||
print("\nThe current project does not support serial-v1\n")
|
||||
Return('group')
|
||||
|
||||
if GetDepend(['BSP_USING_PIN']):
|
||||
if GetDepend(['BSP_USING_GPIO']):
|
||||
src += ['drv_gpio.c']
|
||||
|
||||
if GetDepend(['BSP_USING_WDT']):
|
||||
|
@ -41,6 +41,9 @@ if GetDepend(['BSP_USING_DAC']):
|
|||
if GetDepend(['BSP_USING_ONCHIP_FLASH']):
|
||||
src += ['drv_flash.c']
|
||||
|
||||
if GetDepend(['BSP_USING_PWM']):
|
||||
src += ['drv_pwm.c']
|
||||
|
||||
path = [cwd]
|
||||
path += [cwd + '/config']
|
||||
|
||||
|
|
|
@ -21,14 +21,18 @@ extern "C" {
|
|||
#ifdef SOC_SERIES_R7FA6M4AF
|
||||
#include "ra6m4/uart_config.h"
|
||||
|
||||
#ifdef RT_USING_ADC
|
||||
#ifdef BSP_USING_ADC
|
||||
#include "ra6m4/adc_config.h"
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_DAC
|
||||
#ifdef BSP_USING_DAC
|
||||
#include "ra6m4/dac_config.h"
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_PWM
|
||||
#include "ra6m4/pwm_config.h"
|
||||
#endif
|
||||
|
||||
#endif/* SOC_SERIES_R7FA6M4AF */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-10-26 KevinXu first version
|
||||
*/
|
||||
#ifndef __PWM_CONFIG_H__
|
||||
#define __PWM_CONFIG_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <drv_config.h>
|
||||
#include "hal_data.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
#ifdef BSP_USING_PWM0
|
||||
BSP_PWM0_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM1
|
||||
BSP_PWM1_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM2
|
||||
BSP_PWM2_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM3
|
||||
BSP_PWM3_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM4
|
||||
BSP_PWM4_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM5
|
||||
BSP_PWM5_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM6
|
||||
BSP_PWM6_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM7
|
||||
BSP_PWM7_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM8
|
||||
BSP_PWM8_INDEX,
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM9
|
||||
BSP_PWM9_INDEX,
|
||||
#endif
|
||||
BSP_PWMS_NUM
|
||||
};
|
||||
|
||||
#define PWM_DRV_INITIALIZER(num) \
|
||||
{ \
|
||||
.name = "pwm"#num , \
|
||||
.g_cfg = &g_timer##num##_cfg, \
|
||||
.g_ctrl = &g_timer##num##_ctrl, \
|
||||
.g_timer = &g_timer##num, \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PWM_CONFIG_H__ */
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-10-25 KevinXu first version
|
||||
*/
|
||||
|
||||
#include "drv_pwm.h"
|
||||
|
||||
#ifdef RT_USING_PWM
|
||||
|
||||
/* Declare the control function first */
|
||||
static rt_err_t drv_pwm_control(struct rt_device_pwm *, int, void *);
|
||||
static struct rt_pwm_ops drv_ops =
|
||||
{
|
||||
drv_pwm_control
|
||||
};
|
||||
|
||||
static struct ra_pwm ra6m4_pwm_obj[BSP_PWMS_NUM] =
|
||||
{
|
||||
#ifdef BSP_USING_PWM0
|
||||
[BSP_PWM0_INDEX] = PWM_DRV_INITIALIZER(0),
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM1
|
||||
[BSP_PWM1_INDEX] = PWM_DRV_INITIALIZER(1),
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM2
|
||||
[BSP_PWM2_INDEX] = PWM_DRV_INITIALIZER(2),
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM3
|
||||
[BSP_PWM3_INDEX] = PWM_DRV_INITIALIZER(3),
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM4
|
||||
[BSP_PWM4_INDEX] = PWM_DRV_INITIALIZER(4),
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM5
|
||||
[BSP_PWM5_INDEX] = PWM_DRV_INITIALIZER(5),
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM6
|
||||
[BSP_PWM6_INDEX] = PWM_DRV_INITIALIZER(6),
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM7
|
||||
[BSP_PWM7_INDEX] = PWM_DRV_INITIALIZER(7),
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM8
|
||||
[BSP_PWM8_INDEX] = PWM_DRV_INITIALIZER(8),
|
||||
#endif
|
||||
#ifdef BSP_USING_PWM9
|
||||
[BSP_PWM9_INDEX] = PWM_DRV_INITIALIZER(9),
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/* Convert the raw PWM period counts into ns */
|
||||
static rt_uint32_t _convert_counts_ns(uint32_t source_div, uint32_t raw)
|
||||
{
|
||||
uint32_t pclkd_freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKD) >> source_div;
|
||||
uint32_t ns = (uint32_t)(((uint64_t)raw * 1000000000ULL) / pclkd_freq_hz);
|
||||
return ns;
|
||||
}
|
||||
|
||||
/* Convert ns into raw PWM period counts */
|
||||
static rt_uint32_t _convert_ns_counts(uint32_t source_div, uint32_t raw)
|
||||
{
|
||||
uint32_t pclkd_freq_hz = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_PCLKD) >> source_div;
|
||||
uint32_t counts = (uint32_t)(((uint64_t)raw * (uint64_t)pclkd_freq_hz) / 1000000000ULL);
|
||||
return counts;
|
||||
}
|
||||
|
||||
|
||||
/* PWM_CMD_ENABLE or PWM_CMD_DISABLE */
|
||||
static rt_err_t drv_pwm_enable(struct ra_pwm *device,
|
||||
struct rt_pwm_configuration *configuration,
|
||||
rt_bool_t enable)
|
||||
{
|
||||
fsp_err_t err = FSP_SUCCESS;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
err = R_GPT_Start(device->g_ctrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = R_GPT_Stop(device->g_ctrl);
|
||||
}
|
||||
|
||||
return (err == FSP_SUCCESS) ? RT_EOK : -RT_ERROR;
|
||||
}
|
||||
|
||||
/* PWM_CMD_GET */
|
||||
static rt_err_t drv_pwm_get(struct ra_pwm *device,
|
||||
struct rt_pwm_configuration *configuration)
|
||||
{
|
||||
timer_info_t info;
|
||||
if (R_GPT_InfoGet(device->g_ctrl, &info) != FSP_SUCCESS)
|
||||
return -RT_ERROR;
|
||||
|
||||
configuration->pulse =
|
||||
_convert_counts_ns(device->g_cfg->source_div, device->g_cfg->duty_cycle_counts);
|
||||
configuration->period =
|
||||
_convert_counts_ns(device->g_cfg->source_div, info.period_counts);
|
||||
configuration->channel = device->g_cfg->channel;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/* PWM_CMD_SET */
|
||||
static rt_err_t drv_pwm_set(struct ra_pwm *device,
|
||||
struct rt_pwm_configuration *conf)
|
||||
{
|
||||
uint32_t counts;
|
||||
fsp_err_t fsp_erra;
|
||||
fsp_err_t fsp_errb;
|
||||
rt_err_t rt_err;
|
||||
uint32_t pulse;
|
||||
uint32_t period;
|
||||
struct rt_pwm_configuration orig_conf;
|
||||
|
||||
rt_err = drv_pwm_get(device, &orig_conf);
|
||||
if (rt_err != RT_EOK)
|
||||
{
|
||||
return rt_err;
|
||||
}
|
||||
|
||||
/* Pulse cannot last longer than period. */
|
||||
period = conf->period;
|
||||
pulse = (period >= conf->pulse) ? conf->pulse : period;
|
||||
|
||||
/* Not to set period again if it's not changed. */
|
||||
if (period != orig_conf.period)
|
||||
{
|
||||
counts = _convert_ns_counts(device->g_cfg->source_div, period);
|
||||
fsp_erra = R_GPT_PeriodSet(device->g_ctrl, counts);
|
||||
if (fsp_erra != FSP_SUCCESS)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Two pins of a channel will not be separated. */
|
||||
counts = _convert_ns_counts(device->g_cfg->source_div, pulse);
|
||||
fsp_erra = R_GPT_DutyCycleSet(device->g_ctrl, counts, GPT_IO_PIN_GTIOCA);
|
||||
fsp_errb = R_GPT_DutyCycleSet(device->g_ctrl, counts, GPT_IO_PIN_GTIOCB);
|
||||
if (fsp_erra != FSP_SUCCESS || fsp_errb != FSP_SUCCESS)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement of control method in struct rt_pwm_ops.
|
||||
*/
|
||||
static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
|
||||
{
|
||||
struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
|
||||
struct ra_pwm *pwm_device = (struct ra_pwm *)device->parent.user_data;
|
||||
|
||||
/**
|
||||
* There's actually only one GPT timer with 10 channels. In this case, the
|
||||
* timer is separated into 10 PWM devices, so each device has only one
|
||||
* channel.
|
||||
*/
|
||||
if (configuration->channel != 0)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case PWM_CMD_ENABLE:
|
||||
return drv_pwm_enable(pwm_device, configuration, RT_TRUE);
|
||||
case PWM_CMD_DISABLE:
|
||||
return drv_pwm_enable(pwm_device, configuration, RT_FALSE);
|
||||
case PWM_CMD_GET:
|
||||
return drv_pwm_get(pwm_device, configuration);
|
||||
case PWM_CMD_SET:
|
||||
return drv_pwm_set(pwm_device, configuration);
|
||||
default:
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is to register the PWM device
|
||||
*
|
||||
* Note that the PWM driver only supports one fixed pin.
|
||||
*/
|
||||
int rt_hw_pwm_init(void)
|
||||
{
|
||||
rt_err_t ret = RT_EOK;
|
||||
rt_err_t rt_err = RT_EOK;
|
||||
fsp_err_t fsp_err = FSP_SUCCESS;
|
||||
|
||||
for (int i = 0; i < BSP_PWMS_NUM; i++)
|
||||
{
|
||||
fsp_err = R_GPT_Open(ra6m4_pwm_obj[i].g_ctrl,
|
||||
ra6m4_pwm_obj[i].g_cfg);
|
||||
|
||||
rt_err = rt_device_pwm_register(&ra6m4_pwm_obj[i].pwm_device,
|
||||
ra6m4_pwm_obj[i].name,
|
||||
&drv_ops,
|
||||
&ra6m4_pwm_obj[i]);
|
||||
|
||||
if (fsp_err != FSP_SUCCESS || rt_err != RT_EOK)
|
||||
{
|
||||
ret = -RT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
INIT_BOARD_EXPORT(rt_hw_pwm_init);
|
||||
#endif /* RT_USING_PWM */
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-10-25 KevinXu first version
|
||||
*/
|
||||
|
||||
#ifndef __DRV_PWM_H__
|
||||
#define __DRV_PWM_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
#include <rthw.h>
|
||||
#include <drv_common.h>
|
||||
#include <drv_config.h>
|
||||
#include <hal_data.h>
|
||||
|
||||
/* PWM device object structure */
|
||||
struct ra_pwm
|
||||
{
|
||||
struct rt_device_pwm pwm_device;
|
||||
gpt_instance_ctrl_t *g_ctrl;
|
||||
timer_instance_t const *const g_timer;
|
||||
timer_cfg_t const *const g_cfg;
|
||||
char *name;
|
||||
};
|
||||
|
||||
/* Get ra6m4 pwm device object from the general pwm device object */
|
||||
#define _GET_RA6M4_PWM_OBJ(ptr) rt_container_of(ptr, struct ra_pwm, pwm_device)
|
||||
|
||||
#endif /* __DRV_PWM_H__ */
|
Loading…
Reference in New Issue