PWM
该示例演示使用 TIM 外设实现输出 PWM 波形的功能,该示例可实现以下功能:
使用 TIM2,实现输出周期为 1s、占空比为 50% 的 PWM 功能,使用 P0_1 作为 PWM 输出。
实现 PWM 互补输出功能,使用 P0_2 作为 PWM_P 输出,使用 P2_2 作为 PWM_N 输出。当设置死区后,PWM_P 和 PWM_N 在输出高电平时会比 PWM 延迟一个死区时长。可配置宏
PWM_DEAD_ZONE_CLOCK_SOURCE_5M
,将死区时钟源切换至 5M。实现 PWM 互补 Bypass 功能,使用 P0_2 作为 PWM_P 输出,使用 P2_2 作为 PWM_N 输出。当通过配置宏
PWM_DEAD_ZONE_BYPASS
设置 Bypass 功能后,PWM_P 和 PWM_N 输出波形完全互补,此时无死区产生。可以通过配置宏
PWM_COMPL_OUTPUT_EM_STOP_TEST
实现 PWM 输出急停功能。
环境需求
该示例支持以下开发套件:
Hardware Platforms |
Board Name |
---|---|
RTL8752H HDK |
RTL8752H EVB |
更多信息请参考 快速入门。
硬件连线
连接 P0_1(PWM 输出),P0_2(PWM_P)和 P2_2(PWM_N)至逻辑分析仪观察波形。
配置选项
该示例可配置的宏如下:
PWM_DEAD_ZONE_CLOCK_SOURCE_5M
:配置该宏可将 PWM 互补波形的输出死区时钟源调整至 5M。PWM_DEAD_ZONE_BYPASS
:配置该宏可调整输出的 PWM 互补波形为完全互补,无死区产生。PWM_COMPL_OUTPUT_EM_STOP_TEST
:配置该宏可实现输出 PWM 急停功能。
编译和下载
该示例的工程路径如下:
Project file: board\evb\io_sample\TIM\PWM\mdk
Project file: board\evb\io_sample\TIM\PWM\gcc
请按照以下步骤操作构建并运行该示例:
打开工程文件。
按照 快速入门 中 编译 APP Image 给出的步骤构建目标文件。
编译成功后,在路径
mdk\bin
或gcc\bin
下会生成 app binapp_MP_xxx.bin
文件。按下 reset 按键,开始运行。
测试验证
通过逻辑分析仪可以看到 P0_1 输出周期为 1s、占空比为 50% 的 PWM 波,P0_2 作为 PWM_P 输出相对于 P0_1 在上升沿延迟死区时间的波形,P2_2 作为 PWM_N 输出与 P0_2 反相的 PWM 波。

PWM 的输出波形
放大上述波形,当未开启宏
PWM_DEAD_ZONE_CLOCK_SOURCE_5M
时,死区长度为 5 ms。当开启宏PWM_DEAD_ZONE_CLOCK_SOURCE_5M
后,死区长度变为 4 us。

PWM 死区波形
当开启宏
PWM_DEAD_ZONE_BYPASS
时,可看到输出的互补 PWM 波形为完全互补,没有死区产生。

PWM Bypass 输出波形
当开启宏
PWM_COMPL_OUTPUT_EM_STOP_TEST
时,可以在输出 PWM 互补波形内看到每隔一段时间就会暂停 PWM 的互补输出。

PWM 急停输出波形
代码介绍
该章节分为以下几个部分:
源码路径
工程路径:
sdk\board\evb\io_sample\TIM\PWM
源码路径:
sdk\src\sample\io_sample\TIM\PWM
该工程的工程文件代码结构如下:
└── Project: pwm
└── secure_only_app
└── include
├── app_define.h
└── rom_uuid.h
├── cmsis includes CMSIS header files and startup files
├── overlay_mgr.c
├── system_rtl876x.c
└── startup_rtl876x.s
├── lib includes all binary symbol files that user application is built on
├── rtl8752h_sdk.lib
├── gap_utils.lib
└── ROM.lib
├── peripheral includes all peripheral drivers and module code used by the application
├── rtl876x_rcc.c
├── rtl876x_pinmux.c
├── rtl876x_nvic.c
└── rtl876x_tim.c
├── profile
└── app includes the ble_peripheral user application implementation
└── main.c
初始化
当 EVB 复位启动时,执行 main
函数,执行以下流程:
int main(void)
{
extern uint32_t random_seed_value;
srand(random_seed_value);
pwm_demo();
...
}
在 pwm_demo
中,包含 PAD/PINMUX 设置和 TIM 外设的初始化。
void pwm_demo(void)
{
/* Configure PAD and pinmux firstly! */
board_pwm_init();
/* Initialize TIM peripheral */
driver_pwm_init();
}
board_pwm_init
为 PAD/PINMUX 设置,包含如下流程:
配置 PAD:设置引脚,PINMUX 模式,PowerOn,无内部上拉,输出高。
配置 PINMUX:分别配置引脚为 TIM_PWM2,PWM2_P 和 PWM2_N 功能。
#define PWM_OUT_PIN_PINMUX TIM_PWM2 #define PWM_OUT_P_PIN_PINMUX PWM2_P #define PWM_OUT_N_PIN_PINMUX PWM2_N void board_pwm_init(void) { Pad_Config(PWM_OUT_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(PWM_OUT_P_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(PWM_OUT_N_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pinmux_Config(PWM_OUT_PIN, PWM_OUT_PIN_PINMUX); Pinmux_Config(PWM_OUT_P_PIN, PWM_OUT_P_PIN_PINMUX); Pinmux_Config(PWM_OUT_N_PIN, PWM_OUT_N_PIN_PINMUX); }
driver_pwm_init
为 TIM 外设的初始化,包含如下流程:
使能 RCC 时钟。
配置 TIM 为用户自定义模式。
打开 TIM 的 PWM 输出功能,配置输出周期及占空比。
配置 PWM 急停功能时,互补引脚输出电平。
使能 PWM 死区功能,设置死区大小。
若开启宏
PWM_DEAD_ZONE_CLOCK_SOURCE_5M
,执行RCC_ClockSrc5MCmd()
开启 5M 时钟,执行TIM_PWMChangeDZClockSrc()
切换死区的时钟源。若开启宏
PWM_DEAD_ZONE_BYPASS
,执行TIM_PWMDZBypassCmd()
开启 bypass 功能。使能 TIM2,开始输出 PWM 波形。
void driver_pwm_init(void) { RCC_PeriphClockCmd(APBPeriph_TIMER, APBPeriph_TIMER_CLOCK, ENABLE); #if PWM_DEAD_ZONE_CLOCK_SOURCE_5M RCC_ClockSrc5MCmd(); #endif TIM_TimeBaseInitTypeDef TIM_InitStruct; TIM_StructInit(&TIM_InitStruct); TIM_InitStruct.TIM_Mode = TIM_Mode_UserDefine; TIM_InitStruct.TIM_PWM_En = PWM_ENABLE; TIM_InitStruct.TIM_PWM_High_Count = PWM_HIGH_COUNT; TIM_InitStruct.TIM_PWM_Low_Count = PWM_LOW_COUNT; TIM_InitStruct.PWM_Stop_State_P = PWM_STOP_AT_HIGH; TIM_InitStruct.PWM_Stop_State_N = PWM_STOP_AT_LOW; TIM_InitStruct.PWMDeadZone_En = DEADZONE_ENABLE; //enable to use pwn p/n output TIM_InitStruct.PWM_Deazone_Size = PWM_DEAD_ZONE_SIZE; TIM_TimeBaseInit(TIM2, &TIM_InitStruct); #if PWM_DEAD_ZONE_CLOCK_SOURCE_5M TIM_PWMChangeDZClockSrc((PWM_TypeDef *)(&TIMER_PWM2_CR), ENABLE); #endif TIM_Cmd(TIM2, ENABLE); #if PWM_DEAD_ZONE_BYPASS TIM_PWMDZBypassCmd((PWM_TypeDef *)(&TIMER_PWM2_CR), ENABLE); #endif }
功能实现
初始化阶段完成后,可在逻辑分析仪内观察到 PWM 输出波形。
若开启宏 PWM_COMPL_OUTPUT_EM_STOP_TEST
,在主函数内,执行 TIM_PWMComplOutputEMCmd()
,循环开启和关闭 PWM 输出急停功能。
int main(void)
{
...
while (1)
{
#if PWM_COMPL_OUTPUT_EM_STOP_TEST
platform_delay_ms(2000);
//PWM complementary output emergency stop.
TIM_PWMComplOutputEMCmd(PWM2, ENABLE);
platform_delay_ms(2000);
//Resume PWM complementary output.
TIM_PWMComplOutputEMCmd(PWM2, DISABLE);
#else
#endif
}
}