使用STVD和Cosmic C编译器对微控制器进行编程

控制/MCU

1882人已加入

描述

  脉冲宽度调制 (PWM) 是一种模拟调制技术,其中脉冲的持续时间或宽度随时间而变化。它是一种常用的技术,用于产生具有定义频率和占空比的连续脉冲信号。简而言之,PWM 就是在频率保持不变的情况下改变脉冲的宽度。

  使用 PWM 信号,您可以轻松控制伺服电机的速度或 LED 的亮度。由于通用微控制器只能在其输出引脚上提供逻辑 1(高)或逻辑 0(低),因此它们无法提供变化的模拟电压,除非它具有内置的数模转换器 (DAC)或外部连接。在这种情况下,可以对微控制器进行编程以输出具有不同占空比的脉宽调制 (PWM) ,然后可以将其转换为不同的模拟电压。

  因此,在本教程中,我们将 LED 与通用 STM8S 微控制器连接,该微控制器使用微控制器生成的 PWM 信号进行控制,我们将使用 STVD 和 Cosmic C 编译器对微控制器进行编程。在此之前,让我们了解一些 PWM 信号的基础知识。

  了解 PWM 信号的基础

  您可能听说过,PWM 代表脉冲宽度调制。它是一种模拟调制技术,用于大量不同的应用和项目。PWM 信号的图像如下所示。

STM8S

  您在上面看到的图像是具有相同ON 时间和OFF 时间的通用方波。现在,假设方波的总周期为 1 秒,这意味着方波的开启时间和方波的关闭时间也是 500 毫秒。因此,如果我们连接一个 LED 并用这个方波给它加电,LED 将在半个周期内亮起,在半个周期内熄灭。看起来 LED 以一半的亮度发光。

STM8S

  在上图中,您可以看到我们降低了占空比,如果我们考虑相同的 1S 周期,我们的 On-Time 为 250ms,OFF 时间为 750ms。现在,如果我们连接相同的 LED,我们会观察到 LED 会因为占空比降低而变得更暗。

  STM8S PWM 发生器电路:硬件设置和要求

STM8S

  由于我们使用 PWM 控制 LED,因此需要一个 LED 与 STM8S 板连接。由于 STM8S 开发板上有 LED,因此我将使用它进行演示。我们还需要STM8S开发板以及ST-LINK编程器。除此之外,我们需要一个 5V 电源为开发板供电,因为开发板有一个板载 micro USB 电缆,我们将使用它为开发板供电。

  基于STM8S微控制器的LED调光器电路图

  为了对电路进行编程,我们将ST-Link V2 编程器连接到 STM8S 开发板的 3.3V、SWIM 和接地引脚。STM8 微控制器最有趣的地方在于,它只需要一个SWIM 引脚即可对微控制器进行编程。

STM8S

  正如您在上面的示意图中看到的,测试 LED 连接到开发板上,并连接到板最左侧的端口 1.4

  ST Micro STM8S 微控制器上的 PWM 引脚

  STM8S 有 20 个引脚,其中 8 个引脚可以配置为 PWM。下图显示了红色方框中标记的 PWM 引脚。这些引脚也是可用于其他功能的 GPIO 引脚。

STM8S

  正如我们在上图中看到的,标记的引脚可以生成 PWM 信号。所以我们将使用板上的其中一个来产生 PWM 信号。但是,启用 PWM 会禁用其他功能,因此我们需要小心选择将哪个引脚配置为 PWM。由于我们正在构建此电路以进行在线演示,因此我们将使用 PIN D4 生成 PWM 信号。

  对 STM8s 微控制器进行编程以生成 PWM 信号

  如我们在STM8S 微控制器入门教程中讨论的那样,创建一个工作区和新项目。您可以添加所有头文件和源文件,也可以仅添加 gpio、timer2、config 和 stm8s 文件。打开 main.c 文件并开始编写程序。

STM8S

  确保您已包含如上图所示的头文件。打开 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 < 1000;pwm_duty += 2){
      TIM2_SetCompare1(pwm_duty);
      延迟毫秒(10);
                        }                      
    对于(pwm_duty = 1000;pwm_duty > 0;pwm_duty -= 2){
      TIM2_SetCompare1(pwm_duty);
      延迟毫秒(10);
    }
  }

 

上面的代码负责产生 PWM 信号,因为在第一个 for 循环中 PWM 信号会从高电平变为低电平,而因为下一个 for 循环,PWM 信号会从低电平变为高电平并继续循环。

  使用 STM8S 生成 PWM 信号

  编译代码并上传到你的STM8S开发板。如果您遇到任何编译错误,请确保您已添加所有头文件和源文件,如前所述。上传代码后,您应该会看到引脚 D4 上连接的 LED 的亮度会发生变化。

STM8S

#包括“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);

}

}

}

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分