脉冲宽度调制 (PWM) 是一种模拟调制技术,其中脉冲的持续时间或宽度随时间而变化。它是一种常用的技术,用于产生具有定义频率和占空比的连续脉冲信号。简而言之,PWM 就是在频率保持不变的情况下改变脉冲的宽度。
使用 PWM 信号,您可以轻松控制伺服电机的速度或 LED 的亮度。由于通用微控制器只能在其输出引脚上提供逻辑 1(高)或逻辑 0(低),因此它们无法提供变化的模拟电压,除非它具有内置的数模转换器 (DAC)或外部连接。在这种情况下,可以对微控制器进行编程以输出具有不同占空比的脉宽调制 (PWM) ,然后可以将其转换为不同的模拟电压。
因此,在本教程中,我们将 LED 与通用 STM8S 微控制器连接,该微控制器使用微控制器生成的 PWM 信号进行控制,我们将使用 STVD 和 Cosmic C 编译器对微控制器进行编程。在此之前,让我们了解一些 PWM 信号的基础知识。
了解 PWM 信号的基础
您可能听说过,PWM 代表脉冲宽度调制。它是一种模拟调制技术,用于大量不同的应用和项目。PWM 信号的图像如下所示。
您在上面看到的图像是具有相同ON 时间和OFF 时间的通用方波。现在,假设方波的总周期为 1 秒,这意味着方波的开启时间和方波的关闭时间也是 500 毫秒。因此,如果我们连接一个 LED 并用这个方波给它加电,LED 将在半个周期内亮起,在半个周期内熄灭。看起来 LED 以一半的亮度发光。
在上图中,您可以看到我们降低了占空比,如果我们考虑相同的 1S 周期,我们的 On-TIme 为 250ms,OFF 时间为 750ms。现在,如果我们连接相同的 LED,我们会观察到 LED 会因为占空比降低而变得更暗。
STM8S PWM 发生器电路:硬件设置和要求
由于我们使用 PWM 控制 LED,因此需要一个 LED 与 STM8S 板连接。由于 STM8S 开发板上有 LED,因此我将使用它进行演示。我们还需要STM8S开发板以及ST-LINK编程器。除此之外,我们需要一个 5V 电源为开发板供电,因为开发板有一个板载 micro USB 电缆,我们将使用它为开发板供电。
基于STM8S微控制器的LED调光器电路图
为了对电路进行编程,我们将ST-Link V2 编程器连接到 STM8S 开发板的 3.3V、SWIM 和接地引脚。STM8 微控制器最有趣的地方在于,它只需要一个SWIM 引脚即可对微控制器进行编程。
正如您在上面的示意图中看到的,测试 LED 连接到开发板上,并连接到板最左侧的端口 1.4
ST Micro STM8S 微控制器上的 PWM 引脚
STM8S 有 20 个引脚,其中 8 个引脚可以配置为 PWM。下图显示了红色方框中标记的 PWM 引脚。这些引脚也是可用于其他功能的 GPIO 引脚。
正如我们在上图中看到的,标记的引脚可以生成 PWM 信号。所以我们将使用板上的其中一个来产生 PWM 信号。但是,启用 PWM 会禁用其他功能,因此我们需要小心选择将哪个引脚配置为 PWM。由于我们正在构建此电路以进行在线演示,因此我们将使用 PIN D4 生成 PWM 信号。
对 STM8s 微控制器进行编程以生成 PWM 信号
如我们在STM8S 微控制器入门教程中讨论的那样,创建一个工作区和新项目。您可以添加所有头文件和源文件,也可以仅添加 gpio、TImer2、config 和 stm8s 文件。打开 main.c 文件并开始编写程序。
确保您已包含如上图所示的头文件。打开 main.c 文件并启动代码。完整的 main.c 代码可以在此页面底部找到,您还可以从那里下载项目文件。代码解释如下,如果您对编码部分感到困惑,也可以参考 SPL 用户手册 或本页底部链接的视频。
在我们开始编码过程之前,您需要包含stm8s_gpio.c、stm8s_TIm2.c ,并且在源文件夹和头文件夹中您需要包含stm8s_gpio.h、stm8s_TIm2。H。您可以从STM8S103F3P6 SPL GitHub Repository获取这些头文件。完成后,我们通过包含所有必需的库开始我们的代码,并定义所有必要的变量。对于这个实验代码,我们只需要将 PWM 值保存在一个变量中,这就是我们包含一个名为pwm_duty 的变量的原因。
#包括“STM8S.h” 有符号的 int pwm_duty = 0;
一旦我们声明了所有的库和变量,我们需要构建我们的延迟函数,因为 cosmic c 编译器不提供任何预定义的延迟函数。我们将使用只需要一个时钟周期的汇编指令NOP 。而且由于微控制器的内核以 2MHz 运行,我们可以很容易地推测延迟。出于这个原因,我们将延迟与两个 for 循环结合起来。这是对 cosmic C 编译器进行延迟的最简单、最准确的方法。
void delay_ms (int ms) //函数定义 { for (int i=0; i<=ms; i++) for (int j=0; j<120; j++) // Nop = Fosc/4 _asm("nop"); //执行无操作 //汇编代码 }
接下来,我们将研究我们的主循环。对于本节,我们需要查看SPL 用户手册。我们通过取消初始化 GPIO 引脚和 Timer2 来启动主函数。如果 GPIO 或 Timer 之前已用于其他应用程序,则应在使用它们之前对其进行初始化。这不是强制性的,但这是一个很好的做法。
GPIO_DeInit(GPIOD); TIM2_DeInit();
接下来,我们必须将引脚声明为输出,借助TIM2_OC1Init()函数设置 Timer2,并在定时器中使用预分频器来实现 4KHz 的 PWM 频率。我们是在TIM2_TimeBaseInit()函数的帮助下完成的。完成后,我们在TIM2_Cmd(ENABLE)函数的帮助下启用定时器。对于这个项目,我们决定在板上使用 PIN D4,这是一个支持 PWM 的 PIN。
GPIO_DeInit(GPIOD); TIM2_DeInit(); GPIO_Init(GPIOD,GPIO_PIN_4,GPIO_MODE_OUT_PP_HIGH_FAST); TIM2_OC1Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 1000, TIM2_OCPOLARITY_HIGH); TIM2_TimeBaseInit(TIM2_PRESCALER_1, 500); TIM2_Cmd(启用);
接下来,我们有我们的无限循环。在无限循环中,我们设置了 for 循环,并启用了捕获和比较语句,这将使我们能够设置 PWM 通道。
而(真){ 对于(pwm_duty = 0;pwm_duty 0;pwm_duty -= 2){ TIM2_SetCompare1(pwm_duty); 延迟毫秒(10); } }
上面的代码负责产生 PWM 信号,因为在第一个 for 循环中 PWM 信号会从高电平变为低电平,而因为下一个 for 循环,PWM 信号会从低电平变为高电平并继续循环。
使用 STM8S 生成 PWM 信号
编译代码并上传到你的STM8S开发板。如果您遇到任何编译错误,请确保您已添加所有头文件和源文件,如前所述。上传代码后,您应该会看到引脚 D4 上连接的 LED 的亮度会发生变化。
#包括“STM8S.h”
有符号的 int pwm_duty = 0;
void delay_ms (int ms) //函数定义
{
for (int i=0; i<=ms; i++)
for (int j=0; j<120; j++) // Nop = Fosc/4
_asm("nop"); //执行无操作 //汇编代码
}
无效主要(无效)
{
GPIO_DeInit(GPIOD);
TIM2_DeInit();
GPIO_Init(GPIOD,GPIO_PIN_4,GPIO_MODE_OUT_PP_HIGH_FAST);
TIM2_OC1Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 1000,
TIM2_OCPOLARITY_HIGH);
TIM2_TimeBaseInit(TIM2_PRESCALER_1, 500);
TIM2_Cmd(启用);
而(真){
for(pwm_duty = 0; pwm_duty < 1000; pwm_duty += 2){ // 循环
TIM2_SetCompare1(pwm_duty); //设置Timer2的捕获比较
延迟毫秒(10);//延迟10ms
}
对于(pwm_duty = 1000;pwm_duty > 0;pwm_duty -= 2){
TIM2_SetCompare1(pwm_duty);
延迟毫秒(10);
}
}
}