开发环境:
IDE:MounRiver Studio
MCU:CH585
1 PWM输出的工作原理
脉冲宽度调制(PWM),是英文“Pulse Width Modulation” 的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。
CH585的定时器都可以用来产生 PWM 输出。系统还提供了 8 路 8 位 PWM 输出(PWM4~PWM11)或6 路 16 位 PWM 输出(PWM4~PWM9),占空比可调,PWM 周期固定可选 8 种周期
2 PWM输出实现
2.1 定时器实现PWM
2.1.1 代码分析
本章要实现通过CH585实现PWM方波的输出,这里就需要将相应的GPIO设置为输出。定时器的引脚配置如下表所示。
Table ‑ 定时器 x

GPIO的引脚映射如下表所示。
Table ‑ GPIO功能引脚映射

这里以TMR3为例介绍通过库函数来配置该功能的步骤。
首先要提到的是,PWM 相关的函数设置在库函数文件ch58x_timx.h 和ch58x_timx.c文件中。
1) 配置PB22为复用输出,用于PWM输出。
GPIOB_ResetBits(GPIO_Pin_22); // 配置PWM口 PB22
GPIOB_ModeCfg(GPIO_Pin_22, GPIO_ModeOut_PP_5mA);
2) 初始化 TMR3。
TMR3_PWMInit(High_Level, PWM_Times_1);
清空控制寄存器,设置PWM输出模式。有效重复次数为1次。
3) 设置 TMR3的 PWM 的周期和占空比。
笔者这里配置周期为100us,占空比为50%。
TMR3_PWMCycleCfg(g_10us * 10); // 周期 100us 最大67108864
TMR3_PWMActDataWidth(g_10us/2 * 10); // 占空比 50%, 修改占空比必须暂时关闭定时器
4) 使能 TMR3。
最后需要使能PWM输出,启动TMR3
TMR3_PWMEnable();
TMR3_Enable();
最后看下主函数代码:
#include "CH58x_common.h"
#define g_10us (FREQ_SYS/100000)
int main()
{
HSECFG_Capacitance(HSECap_18p);
SetSysClock(CLK_SOURCE_HSE_PLL_62_4MHz);
GPIOA_ResetBits(GPIO_Pin_9);
GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA);
TMR0_PWMInit(High_Level, PWM_Times_1);
TMR0_PWMCycleCfg(g_10us * 10);
TMR0_PWMActDataWidth(g_10us/4 * 10);
TMR0_PWMEnable();
TMR0_Enable();
GPIOA_ResetBits(GPIO_Pin_10);
GPIOA_ModeCfg(GPIO_Pin_10, GPIO_ModeOut_PP_5mA);
TMR1_PWMInit(High_Level, PWM_Times_1);
TMR1_PWMCycleCfg(g_10us * 10);
TMR1_PWMActDataWidth(g_10us/3 * 10);
TMR1_PWMEnable();
TMR1_Enable();
GPIOA_ResetBits(GPIO_Pin_11);
GPIOA_ModeCfg(GPIO_Pin_11, GPIO_ModeOut_PP_5mA);
TMR2_PWMInit(High_Level, PWM_Times_1);
TMR2_PWMCycleCfg(g_10us * 10);
TMR2_PWMActDataWidth(g_10us/2 * 10);
TMR2_PWMEnable();
TMR2_Enable();
GPIOB_ResetBits(GPIO_Pin_22);
GPIOB_ModeCfg(GPIO_Pin_22, GPIO_ModeOut_PP_5mA);
TMR3_PWMInit(High_Level, PWM_Times_1);
TMR3_PWMCycleCfg(g_10us * 10);
TMR3_PWMActDataWidth(g_10us/4 * 10 * 3);
TMR3_PWMEnable();
TMR3_Enable();
while(1)
{
}
}
是不是很简单。
2.1.2 PWM周期、占空比分析
根据前面的参数配置,我们可以算出PWM的输出周期:
PWM频率 = 系统时钟频率 / PWM周期值
例如:
- 系统时钟:60MHz
- PWM周期值:10000
- PWM频率 = 60,000,000 / 10,000 = 6kHz
占空比 = (比较值 / PWM周期值) × 100%
例如:
- 周期值:10000
- 比较值:3000
- 占空比 = 30%
2.1.3 PWM输出的实验现象
在前面我们输出了的PWM0(PA9)、PWM1(PA10)、PWM2(PA11)、PWM3(PB22)不同占空比的 PWM 信号。接下来就看看PWM的输出,PWM 信号可以通过示波器看到。下面笔者就是用逻辑分析仪查看波形。
首先笔者使用的逻辑分析仪是Kingst LA5016,当然啦,其他的也可以,关于逻辑分析仪的相关使用笔者这里就不介绍了,可以查看官方资料。
首先将(PA9)、(PA10)、(PA11)、(PB22)分别接到逻辑分析仪的CH0 – CH3,然后下载程序到板子中,打开Kingst VIS,然后进行采样。

我们就可以看到不同通道的实际周期,占空比等信息。从上图可以看到,实际测量的频率和占空比和理论是相符的。
2.2 PWM模块输出PWM
除了使用定时器产生的PWM,系统还提供了 8 路 8 位 PWM 输出(PWM4~PWM11)或6 路 16 位 PWM 输出(PWM4~PWM9)。
PWM 模块配置PWM的流程如下。
(1)、设置寄存器 R8_PWM_CLOCK_DIV,配置 PWM 的基准时钟频率;
(2)、设置 PWM 输出极性配置寄存器 R8_PWM_POLAR,配置对应 PWMx 的输出极性;
(3)、设置 PWM 配置控制寄存器 R8_PWM_CONFIG,设置 PWM 的模式、数据位宽、周期;
(4)、设置 PWM 输出使能寄存器 R8_PWM_OUT_EN,开启对应的 PWMx 输出使能;
(5)、根据需要的占空比计算出数据,写入对应的数据保持寄存器 R8_PWMx_DATA;
(6)、设置 PWM4-PWM11 中所需的 PWM 引脚方向为输出,可选地,设置相应 I/O 的驱动能力;
(7)、根据需要更新 R8_PWMx_DATA 中的数据,更新输出占空比。
2.2.1 代码实现
首先要提到的是,PWM模块相关的函数设置在库函数文件CH58x_pwm.h 和CH58x_pwm.c文件中。
1) 配置PB12为复用输出,用于PWM输出。
GPIOB_ModeCfg(GPIO_Pin_12, GPIO_ModeOut_PP_5mA);
2) 配置PWM模块的时钟和周期
PWMX_CLKCfg(4);
PWMX_16bit_CycleCfg(60000-1);
3) 配置PWM模块的占空比
PWMX_16bit_ACTOUT(CH_PWM4, 30000, Low_Level, ENABLE); // 50%占空比
最后配置PWM模块占空比即可。
主函数代码如下。
#include "CH58x_common.h"
#define g_10us (FREQ_SYS/100000)
int main()
{
HSECFG_Capacitance(HSECap_18p);
SetSysClock(CLK_SOURCE_HSE_PLL_62_4MHz);
GPIOA_ModeCfg(GPIO_Pin_12, GPIO_ModeOut_PP_5mA);
GPIOA_ModeCfg(GPIO_Pin_13, GPIO_ModeOut_PP_5mA);
GPIOB_ModeCfg(GPIO_Pin_0, GPIO_ModeOut_PP_5mA);
GPIOB_ModeCfg(GPIO_Pin_4, GPIO_ModeOut_PP_5mA);
GPIOB_ModeCfg(GPIO_Pin_6, GPIO_ModeOut_PP_5mA);
GPIOB_ModeCfg(GPIO_Pin_7, GPIO_ModeOut_PP_5mA);
PWMX_CLKCfg(4);
PWMX_16bit_CycleCfg(60000-1);
PWMX_16bit_ACTOUT(CH_PWM4, 30000, Low_Level, ENABLE);
PWMX_16bit_ACTOUT(CH_PWM5, 15000, Low_Level, ENABLE);
PWMX_16bit_ACTOUT(CH_PWM6, 45000, Low_Level, ENABLE);
PWMX_16bit_ACTOUT(CH_PWM7, 30000, High_Level, ENABLE);
PWMX_16bit_ACTOUT(CH_PWM8, 15000, High_Level, ENABLE);
PWMX_16bit_ACTOUT(CH_PWM9, 45000, High_Level, ENABLE);
while(1)
{
}
}
2.2.2 PWM输出的实验现象
在前面我们输出了的PWM4(PA12)、PWM5(PA13)、PWM6(PB0)、PWM7(PB4) 、PWM8(PB6) 、PWM9(PB7)不同占空比的 PWM 信号。接下来就看看PWM的输出,PWM 信号可以通过示波器看到。下面笔者就是用逻辑分析仪查看波形。
首先笔者使用的逻辑分析仪是Kingst LA5016,当然啦,其他的也可以,关于逻辑分析仪的相关使用笔者这里就不介绍了,可以查看官方资料。
首先将PWM4(PA12)、PWM5(PA13)、PWM6(PB0)、PWM7(PB4) 、PWM8(PB6) 、PWM9(PB7)分别接到逻辑分析仪的CH0 – CH5,然后下载程序到板子中,打开Kingst VIS,然后进行采样。

我们就可以看到不同通道的实际周期,占空比等信息。从上图可以看到,实际测量的频率和占空比和理论是相符的。