本节将会介绍如何使用 HarmonyOS IoT 硬件子系统的脉宽调制(Pulse Width Modulation, PWM)模块的相关 API 控制蜂鸣器发声和 LED 灯的亮度。

本节重点掌握要点

  • 清楚需要用到的头文件及其对应的路径
  • 熟练掌握 与 PWM 模块相关的 API 接口函数的使用
  • 掌握通过 PWM 模块控制蜂鸣器发声
  • 掌握通过PWM 模块控制 LED 灯的亮度

6.1 PWM 简介

        定义:脉冲宽度调制(PWM) 是一种数字信号,最常用于控制电路。该信号在预定义的时间中设置为高(5v或3.3v)和低(0v)。通常,我们将PWM的高电平称为1,低电平为0。

        PWM占空比:在一个周期内PWM信号保持高电平的时间百分比称为占空比。如果信号始终为高电平,则它处于100%占空比,如果它始终处于低电平,则占空比为0%。如图2.4-1所示,T1为高电平时长,T为一个PWM周期,则占空比为 T1/T。

图6-1 PWM波形图

PWM的频率:在1s内完成周期性变化的次数叫做频率,常用f表示,单位为赫兹 Hz。1Hz 代表每秒钟周期震动1次 ,100Hz即100次/秒,再者说音频采样率8000Hz,其实指的是每秒采样的次数为8000次。频率 f 和周期 T 的关系为: f = 1/T 。

我们知道数字信号只有高/低电平两种状态,在连续的一段时间内,让同一个引脚上输出不同状态的高/低电平,可以实现输出方波信号。通过 CPU 控制 GPIO 引脚状态能够实现这种功能,但每次状态变化都需要 CPU 主控控制,会造成 CPU 计算资源的浪费。

芯片的 PWM 模块无须 CPU 主动控制即可输出连续的方波信号。在有 PWM 模块的芯片中, CPU 只需要向 PWM 模块设定方波的一些参数,就可以实现在没有 CPU 控制的情况下,输出一定频率的连续方波信号。另外,PWM模块可以控制输出方波在一个周期内高电平和低电平所占的时间比例,即占空比。

6.2 和 PWM 相关头文件及其对应的路径与 API 接口函数

图6-2 PWM模块相关头文件及其对应的路径、API 接口函数

  • hi_u32 hi_pwm_init(hi_pwm_port port)

功能描述:PWM模块初始化。

参数讲解:该函数只有一个参数。参数1: hi_pwm_port 类型的参数 port,用于指定初始化 PWM 端口号。

函数返回值:成功则返回0,失败则返回-1。

typedef enum {
    HI_PWM_PORT_PWM0 = 0,    
    HI_PWM_PORT_PWM1 = 1,     
    HI_PWM_PORT_PWM2 = 2,     
    HI_PWM_PORT_PWM3 = 3,     
    HI_PWM_PORT_PWM4 = 4,     
    HI_PWM_PORT_PWM5 = 5,     
    HI_PWM_PORT_MAX   
} hi_pwm_port;

说明:Hi3861 芯片总共有5路PWM输出通道,hi_pwm_port 是枚举类型,分别对应5个 PWM端口号。具体对应如下:

HI_PWM_PORT_PWM0,对应 PWM0;

HI_PWM_PORT_PWM1 ,对应 PWM1;

HI_PWM_PORT_PWM2 ,对应 PWM2;

HI_PWM_PORT_PWM3 ,对应 PWM3;

HI_PWM_PORT_PWM4 ,对应 PWM4;

HI_PWM_PORT_PWM5 ,对应 PWM5;

  • hi_u32 hi_pwm_start(hi_pwm_port port, hi_u16 duty, hi_u16 freq)

功能描述:开始输出 PWM 信号。

参数讲解:该函数有3个参数。参数1: hi_pwm_port 类型的参数 port,用于指定 PWM 端口号。和 hi_pwm_init 函数的参数一样。参数2:hi_u16 (unsigned short)类型的参数 duty,PWM占空比计数值,取值范围为:[1, 65535],默认值为750。参数3:hi_u16 (unsigned short)类型的参数 freq,分频倍数,取值范围为:[1, 65535],默认值为1500。

函数返回值:成功则返回0,失败则返回-1。

补充说明:

freq:分频倍数。该参数用于控制输出的 PWM 信号频率,具体输出的频率 Fout 等于时钟源频率 Fclk (160MHz)除以 freq 参数的值,即有以下对应关系:

Fout = Fclk / freq = 160 MHz / freq

duty:PWM 占空比计数值。该参数用于指定占空比,占空比的具体值为 duty 参数和 freq 参数的比例,即有以下对应关系:

占空比 = duty / freq

  • hi_u32 hi_pwm_stop(hi_pwm_port port)

功能描述:停止输出 PWM 信号。

参数讲解:该函数只有一个参数。参数1: hi_pwm_port 类型的参数 port,和 hi_pwm_init 函数的参数一样。

函数返回值:成功则返回0,失败则返回-1。

  • hi_u32 hi_pwm_deinit(hi_pwm_port port)

功能描述:解除 PWM 模块初始化。

参数讲解:该函数只有一个参数。参数1: hi_pwm_port 类型的参数 port,和 hi_pwm_init 函数的参数一样。

函数返回值:成功则返回0,失败则返回-1。

  • hi_u32 hi_pwm_set_clock(hi_pwm_clk_source clk_type)

功能描述:该函数用于设置PWM模块时钟类型,该设置对所有PWM模块均生效。默认为160M时钟。

参数讲解:该函数只有一个参数。参数1: hi_pwm_clk_source clk 类型的参数 clk_type。

函数返回值:成功则返回0,失败则返回-1。

typedef enum {
    PWM_CLK_160M, 
    PWM_CLK_XTAL, 
    PWM_CLK_MAX   
} hi_pwm_clk_source;

说明:hi_pwm_clk_source 是一个枚举数据类型,可取值如下:

PWM_CLK_160M:芯片内部160M 时钟源;

PWM_CLK_XTAL:外部晶体时钟源,24MHz或40MHz ,具体取决于芯片外部使用的晶振频率。

PWM_CLK_MAX:最大值,不可使用

6.3 开发板蜂鸣器原理图说明

        开发板上蜂鸣器部分的相关原理图如图 6-3 所示,在原理图中,蜂鸣器连接在主控芯片的 GPIO13 引脚上。

        蜂鸣器分为有源蜂鸣器和无源蜂鸣器,这里的有源指的不是电源,而是指震荡源。也就是说,有源蜂鸣器内部带震荡源,所以只要一通电就会叫。而无源蜂鸣器内部不带震荡源,如果只用直流信号无法令其鸣叫,必须用 2k-5kHz 的方波信号去驱动它。无源蜂鸣器无正负极,有源蜂鸣器有正负极。本开发板使用的是无源蜂鸣器,因此不分正负极,需要用 2k-5kHz 的方波信号去驱动它,才能令其鸣叫。

图6-3

6.4 通过输出 PWM 方波控制蜂鸣器发声

1. 创建 pwm_example.c 文件

        在 OpenHarmony 工程项目的 src/applications/sample/wifi-iot/app/ 目录下,创建 03_pwm_demo 文件夹,在该文件夹下创建名为 pwm_example.c 文件。文件内容如下:

#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "hi_io.h"
#include "hi_pwm.h"

#define PWM_TEST_GPIO 0
#define INTERVAL_TIME_US 1000000

static void MypwmTask(void *arg)
{
  (void) arg;
  
  IoTGpioInit(PWM_TEST_GPIO);
  IoTGpioSetDir(PWM_TEST_GPIO, IOT_GPIO_DIR_OUT);
  hi_io_set_func(PWM_TEST_GPIO, HI_IO_FUNC_GPIO_0_PWM3_OUT);
  hi_pwm_init(HI_PWM_PORT_PWM3);

  while (1)
  {
    hi_pwm_start(HI_PWM_PORT_PWM3, 20000, 40000);
    usleep(INTERVAL_TIME_US);               //蜂鸣器响一秒钟
    hi_pwm_stop(HI_PWM_PORT_PWM3);          //停止输出 PWM 信号
    usleep(INTERVAL_TIME_US);               //蜂鸣器停止响一秒钟

  }
  
}

static void PwmExampleEntry(void)
{
  osThreadAttr_t attr = {0};
  attr.name = "MypwmTask";
  attr.stack_size = 4096;
  attr.priority = osPriorityNormal;

  if(osThreadNew((osThreadFunc_t)MypwmTask, NULL, &attr) == NULL)
  {
    printf("[MypwmEntry] create MypwmTask failed! \n");
  }
}

SYS_RUN(PwmExampleEntry);

图6-4 程序编写流程图

程序编写思路如图6-4所示,部分代码说明如下。

hi_pwm_start(HI_PWM_PORT_PWM4, 20000, 40000) 函数开始输出 PWM 信号,其中输出频率 Fout = 160 MHz/40 000 = 4 KHz,符合我们无源蜂鸣器 2k-5kHz 频率范围的要求。占空比 = duty/freq = 20 000/40 000 =1/2 = 50%。输出频率决定了蜂鸣器鸣叫时候音调的高低,占空比决定了蜂鸣器鸣叫时音量的大小。

2. 创建 BUILD.gn 文件,编写应用级编译脚本

        在 OpenHarmony 工程项目的 src/applications/sample/wifi-iot/app/03_pwm_demo 文件夹下,建 BUILD.gn 文件,文件内容如下:

static_library("my_pwm") {
    sources = [
        "pwm_example.c"
    ]

    include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/kal/cmsis",
        "//base/iot_hardware/peripheral/interfaces/kits",
        "//device/hisilicon/hispark_pegasus/sdk_liteos/include",
         
    ]
}
3. 编写模块级编译脚本 BUILD.gn 文件

        修改 OpenHarmony 工程项目的 src/applications/sample/wifi-iot/app 目录下的 BUILD.gn 文件,将其内容修改如下:

import("//build/lite/config/component/lite_component.gni")

lite_component("app") {
    features = [
        #"01_led_demo:my_led",
        #"02_key_demo:my_key",  //将前面两节内容的编译脚本注释掉,只保留本节内容
        "03_pwm_demo:my_pwm",
    ]
}
4. 代码编译和烧录

        按照3.2节介绍的方法进行代码编译,发现编译不通过,出现了错误,具体如图6-5所示。原因是我们没有打开 PWM 配置。我们找到 device/hisilicon/hispark_pegasus/sdk_liteos/build/config/usr_config.mk 文件,可以看到 #CONFIG_PWM_SUPPORT is not set ,如图6-6所示。我们将该语句修改成:CONFIG_PWM_SUPPORT=y,如图6-7所示。修改完成后,再次进行编译,编译成功,如图6-8所示。(备注:使用 DevEco Device Tool 3.1 Release 版本软件不会再出现这个问题,因为该版本软件默认打开了PWM配置,其他低的版本就会出现该问题

        编译成功后,按照3.2节介绍的方法进行代码烧录,在烧录完成后,按下复位按键,可以听到蜂鸣器响一秒钟,然后停一秒钟,如此循环播放。

图6-5 编译错误

图6-6 CONFIG_PWM_SUPPORT is not set

图6-7 CONFIG_PWM_SUPPORT=y

图6-8 编译成功

6.5 通过 PWM 模块在蜂鸣器上播放音乐

        蜂鸣器上播放音乐的原理就是让蜂鸣器发出不同频率的声音以及在该频率下持续的时长。通过前面的学习,我们知道通过修改函数 hi_pwm_start(hi_pwm_port port, hi_u16 duty, hi_u16 freq) 分频倍数就能够实现让 PWM 模块输出不同频率的方波,从而播放出不同频率的声音通过延时函数 usleep 保持 PWM 开启的时长,从而达到某个频率方波输出的时长。这样就能够实现音乐的播放了。

        音乐主要的因素就是简谱和节奏,简谱就是我们曲谱的音符,而音符又是什么呢?其实音符就是频率,音乐曲谱中的do re mi fa so la si (简谱 1 2 3 4 5 6 7)对应的就是不同的频率,因此我们只需要把这些音符和频率对应起来就可以了。节奏就是我们曲谱每个音符持续的时长,我们称之为曲谱时值,这个和我们的延时函数 usleep 相对应。

表6-1 音符、频率及分频倍数关系对应表

时钟源频率

160 MHz

音符

do 1

re 2

mi 3

fa 4

so 5

la 6

si 7

频率 Hz

4185.9

4698.7

5273.9

5587.6

6271.8

7039.8

7901.6

分频倍数

38223

34052

30338

28635

25511

22728

20249

1. 创建 pwm_music_example.c 文件

        在 OpenHarmony 工程项目的 src/applications/sample/wifi-iot/app/ 03_pwm_demo 目录下,创建名为 pwm_music_example.c 文件。文件内容如下:

#include <stdio.h>
#include <unistd.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "hi_io.h"
#include "hi_pwm.h"


#define PWM_TEST_GPIO 0
#define INTERVAL_TIME_US 1000000

//音符对应的分频倍数
static const hi_u16 tuneFreqs[] = {0, 38223, 34052, 30338, 28635, 25511, 22728, 20249};

//曲谱音符,《两只老虎》简谱
static const hi_u8  scoreNotes[] = {
  1, 2, 3, 1,    1, 2, 3, 1,    3, 4, 5,  3, 4, 5,    5, 6, 5, 4, 3, 1,  
  5, 6, 5, 4, 3, 1,  1, 5, 1,  1, 5, 1
};

//曲谱时值,根据简谱记普方法转写
static const hi_u8 scoreDurations[] = {
  4, 4, 4, 4,    4, 4, 4, 4,    4, 4, 8,   4, 4, 8,   3, 1, 3, 1, 4, 4,   
  3, 1, 3, 1, 4, 4,  4, 4, 8,   4, 4, 8
};


static void MypwmTask(void *arg)
{
  (void) arg;
  
  IoTGpioInit(PWM_TEST_GPIO);
  IoTGpioSetDir(PWM_TEST_GPIO, IOT_GPIO_DIR_OUT);
  hi_io_set_func(PWM_TEST_GPIO, HI_IO_FUNC_GPIO_0_PWM3_OUT);
  hi_pwm_init(HI_PWM_PORT_PWM3);

  for (size_t i = 0; i < sizeof(scoreNotes)/sizeof(scoreNotes[0]); i++)
  {
    hi_u32 tune = scoreNotes[i];  //音符
    hi_u16 freqDivisor = tuneFreqs[tune];  //获取音符对应的分频系数,从而能得到频率
    hi_u32 tuneInterval = scoreDurations[i]*(125*1000);  //计算曲谱时值
    printf("%d %d %d \r\n", tune, freqDivisor, tuneInterval);
    hi_pwm_start(HI_PWM_PORT_PWM3, freqDivisor/2, freqDivisor);
    usleep(tuneInterval);
    hi_pwm_stop(HI_PWM_PORT_PWM3);
  }
  
}

static void PwmExampleEntry(void)
{
  osThreadAttr_t attr = {0};
  attr.name = "MypwmTask";
  attr.stack_size = 4096;
  attr.priority = osPriorityNormal;

  if(osThreadNew((osThreadFunc_t)MypwmTask, NULL, &attr) == NULL)
  {
    printf("[MypwmEntry] create MypwmTask failed! \n");
  }
}

SYS_RUN(PwmExampleEntry);

上述部分代码说明如下。

1、分别定义三个数组 tuneFreqs[] 、scoreNotes[]、scoreDurations[] 来存储分频倍数 freq、曲谱音符和曲谱时长。分频倍数 freq (对应上述代码中的变量 freqDivisor ) 和曲谱音符的对应关系为:

freq = tuneFreqs [ scoreNotes [ i ] ]

2、tune = scoreNotes[i] 将简谱中的音符赋值给变量 tune,该变量对应的值为 1-7,分别和 tuneFreqs 元素位置频率一 一 对应。音符 1(也就是音符 do)的频率是 4185.9 Hz,分频倍数是38223,对应的是数组 tuneFreqs 下标为1的元素 tuneFreqs[1] = 38223。音符2(也就是音符 re)的频率是 4698.7 Hz,分频倍数是34052,对应的是数组 tuneFreqs 下标为2的元素 tuneFreqs[2] = 34052,其他音符以此类推。

3、freqDivisor = tuneFreqs[tune] 获取音符对应的分频系数,从而能得到频率。

4、tuneInterval = scoreDurations[i]*(125*1000) 计算曲谱时值,即 usleep 要延时的时长。

5、hi_pwm_start(HI_PWM_PORT_PWM4, freqDivisor/2, freqDivisor) 开始PWM 方波输出,分频倍数=freqDivisor,占空比 = (freqDivisor/2)/ freqDivisor = 1/2 = 50%。

2. 编写应用级编译脚本BUILD.gn 文件

        在 OpenHarmony 工程项目的 src/applications/sample/wifi-iot/app/03_pwm_demo 文件夹下,修改原来的 BUILD.gn 文件,将 sources 里面的 pwm_example.c 替换成 pwm_music_example.c ,修改后的内容如下:

static_library("my_pwm") {
    sources = [
        #"pwm_example.c",
        "pwm_music_example.c"
    ]

    include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/kal/cmsis",
        "//base/iot_hardware/peripheral/interfaces/kits",
        "//device/hisilicon/hispark_pegasus/sdk_liteos/include",
         
    ]
}
3. 编写模块级编译脚本 BUILD.gn 文件

        OpenHarmony 工程项目的 src/applications/sample/wifi-iot/app 目录下的 BUILD.gn 文件内容不变,和前面的一样,具体内容如下:

import("//build/lite/config/component/lite_component.gni")

lite_component("app") {
    features = [
        #"01_led_demo:my_led",
        #"02_key_demo:my_key",
        "03_pwm_demo:my_pwm",
    ]
}
4. 代码编译和烧录

        按照3.2节介绍的方法进行代码编译和烧录,在烧录完成后,按下复位按键,蜂鸣器就播放出《两只老虎》的音乐了。

6.6 通过 PWM 模块控制蜂鸣器的音量

        在前面我们讲过,hi_pwm_start(hi_pwm_port port, hi_u16 duty, hi_u16 freq) 函数输出频率决定了蜂鸣器鸣叫时候音调的高低,占空比决定了蜂鸣器鸣叫时音量的大小。在 freq 不变的情况下,改变 duty 参数的值可以输出不同占空比的方波信号,使用不同占空比的方波信号,可以控制蜂鸣器的音量。

1. 创建 pwm_vol_example.c 文件

        在 OpenHarmony 工程项目的 src/applications/sample/wifi-iot/app/ 03_pwm_demo 目录下,创建名为 pwm_vol_example.c 文件。文件内容如下:

#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "hi_io.h"
#include "hi_pwm.h"

#define PWM_TEST_GPIO 0
#define INTERVAL_TIME_US 1000000

static void MypwmTask(void *arg)
{
  (void) arg;
  
  IoTGpioInit(PWM_TEST_GPIO);
  IoTGpioSetDir(PWM_TEST_GPIO, IOT_GPIO_DIR_OUT);
  hi_io_set_func(PWM_TEST_GPIO, HI_IO_FUNC_GPIO_0_PWM3_OUT);
  hi_pwm_init(HI_PWM_PORT_PWM3);

  while (1)
  {
    const int numLevels = 100;
    for (size_t i = 1; i < numLevels; i++)
    {
      hi_pwm_start(HI_PWM_PORT_PWM3, 40000*i/numLevels, 40000);
      usleep(INTERVAL_TIME_US);
      hi_pwm_stop(HI_PWM_PORT_PWM3);
      usleep(INTERVAL_TIME_US);
    }
    
  }
  
}

static void PwmExampleEntry(void)
{
  osThreadAttr_t attr = {0};
  attr.name = "MypwmTask";
  attr.stack_size = 4096;
  attr.priority = osPriorityNormal;

  if(osThreadNew((osThreadFunc_t)MypwmTask, NULL, &attr) == NULL)
  {
    printf("[MypwmEntry] create MypwmTask failed! \n");
  }
}

SYS_RUN(PwmExampleEntry);

上述部分代码说明如下。

hi_pwm_start(HI_PWM_PORT_PWM4, 40000*i/numLevels, 40000) 函数 freq 参数为 40000,duty 参数为 40000*i/numLevels,i 从 1 取值到 numLevels,因此,PWM 模块的输出频率:

Fout = 160 MHz / 40 000 = 4 kHz

占空比为:

占空比 = duty / freq = (40000*i/numLevels)/ 40000 = i / numLevels

占空比从 1% 逐渐增大到 99%,因此音量也是逐渐增大。

2. 编写应用级编译脚本BUILD.gn 文件

        在 OpenHarmony 工程项目的 src/applications/sample/wifi-iot/app/03_pwm_demo 文件夹下,修改原来的 BUILD.gn 文件,将 sources 里面的 pwm_music_example.c 替换成 pwm_vol_example.c ,修改后的内容如下:

static_library("my_pwm") {
    sources = [
        #"pwm_example.c",
        #"pwm_music_example.c",
        "pwm_vol_example.c",
    ]

    include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/kal/cmsis",
        "//base/iot_hardware/peripheral/interfaces/kits",
        "//device/hisilicon/hispark_pegasus/sdk_liteos/include",
         
    ]
}
3. 编写模块级编译脚本 BUILD.gn 文件

        OpenHarmony 工程项目的 src/applications/sample/wifi-iot/app 目录下的 BUILD.gn 文件内容不变,和前面的一样,具体内容如下:

import("//build/lite/config/component/lite_component.gni")

lite_component("app") {
    features = [
        #"01_led_demo:my_led",
        #"02_key_demo:my_key",
        "03_pwm_demo:my_pwm",
    ]
}
4. 代码编译和烧录

        按照3.2节介绍的方法进行代码编译和烧录,在烧录完成后,按下复位按键,可以听到蜂鸣器响一秒钟,然后停一秒钟,如此循环播放,且音量逐渐从小变大。

6.7 通过 PWM 模块控制三色 LED 灯的亮度

        LED2 为开发板搭载的共阳极三色 LED 灯,其型号为 MHP5050RGBDT,RED/GREEN/BLUE 分别和主控芯片 Hi3861 的 GPIO01/GPIO10/GPIO02 引脚连接。三色 LED 灯使用三个 MMBT3904 三极管驱动,RED/GREEN/BLUE 任一引脚高电平,对应该路颜色的 LED 灯点亮,低电平对应该路 LED 灯熄灭。GPIO01/GPIO10/GPIO02 分别对应 PWM4/PWM1/PWM2, GPIO01 连接 RED 红色 LED 灯,GPIO10 连接 GREEN 绿色 LED 灯,GPIO02 连接 BLUE 蓝色 LED 灯,其原理图如下所示。我们通过 PWM 模块来输出不同占空比的高电平,从而使三色 LED 灯的颜色越来越亮,且红绿蓝三种颜色轮流点亮。

图6-9 三色LED灯原理图

1. 创建 pwm_rgb_example.c 文件

        在 OpenHarmony 工程项目的 src/applications/sample/wifi-iot/app/ 03_pwm_demo 目录下,创建名为 pwm_rgb_example.c 文件。文件内容如下:

#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "hi_io.h"
#include "hi_pwm.h"

#define PWM_RED_GPIO 1
#define PWM_GREEN_GPIO 10
#define PWM_BLUE_GPIO 2
#define INTERVAL_TIME_US 1000000

static void MypwmTask(void *arg)
{
  (void) arg;
  
  IoTGpioInit(PWM_RED_GPIO);
  IoTGpioInit(PWM_GREEN_GPIO);
  IoTGpioInit(PWM_BLUE_GPIO);
  IoTGpioSetDir(PWM_RED_GPIO, IOT_GPIO_DIR_OUT);
  IoTGpioSetDir(PWM_GREEN_GPIO, IOT_GPIO_DIR_OUT);
  IoTGpioSetDir(PWM_BLUE_GPIO, IOT_GPIO_DIR_OUT);
  hi_io_set_func(PWM_RED_GPIO, HI_IO_FUNC_GPIO_1_PWM4_OUT);
  hi_io_set_func(PWM_GREEN_GPIO, HI_IO_FUNC_GPIO_10_PWM1_OUT);
  hi_io_set_func(PWM_BLUE_GPIO, HI_IO_FUNC_GPIO_2_PWM2_OUT);


  hi_pwm_init(HI_PWM_PORT_PWM4);
  hi_pwm_init(HI_PWM_PORT_PWM1);
  hi_pwm_init(HI_PWM_PORT_PWM2);

  while (1)
  {
    const int numLevels = 10;
    for (size_t i = 1; i <= numLevels; i++)
    {
      hi_pwm_start(HI_PWM_PORT_PWM4, 40000*i/numLevels, 40000);
      usleep(INTERVAL_TIME_US);
    }
    hi_pwm_stop(HI_PWM_PORT_PWM4);
    usleep(INTERVAL_TIME_US);

    for (size_t i = 1; i <= numLevels; i++)
    {
      hi_pwm_start(HI_PWM_PORT_PWM1, 40000*i/numLevels, 40000);
      usleep(INTERVAL_TIME_US);
    }
    hi_pwm_stop(HI_PWM_PORT_PWM1);
    usleep(INTERVAL_TIME_US);

    for (size_t i = 1; i <= numLevels; i++)
    {
      hi_pwm_start(HI_PWM_PORT_PWM2, 40000*i/numLevels, 40000);
      usleep(INTERVAL_TIME_US);
    }
    hi_pwm_stop(HI_PWM_PORT_PWM2);
    usleep(INTERVAL_TIME_US);  
  }
  
}

static void PwmExampleEntry(void)
{
  osThreadAttr_t attr = {0};
  attr.name = "MypwmTask";
  attr.stack_size = 4096;
  attr.priority = osPriorityNormal;

  if(osThreadNew((osThreadFunc_t)MypwmTask, NULL, &attr) == NULL)
  {
    printf("[MypwmEntry] create MypwmTask failed! \n");
  }
}

SYS_RUN(PwmExampleEntry);
2. 编写应用级编译脚本BUILD.gn 文件

        在 OpenHarmony 工程项目的 src/applications/sample/wifi-iot/app/03_pwm_demo 文件夹下,修改原来的 BUILD.gn 文件,将 sources 里面的 pwm_vol_example.c 替换成 pwm_rgb_example.c ,修改后的内容如下:


static_library("my_pwm") {
    sources = [
        #"pwm_example.c",
        #"pwm_music_example.c",
        #"pwm_vol_example.c",
        "pwm_rgb_example.c",
    ]

    include_dirs = [
        "//utils/native/lite/include",
        "//kernel/liteos_m/kal/cmsis",
        "//base/iot_hardware/peripheral/interfaces/kits",
        "//device/hisilicon/hispark_pegasus/sdk_liteos/include",
         
    ]
}
3. 编写模块级编译脚本 BUILD.gn 文件

        OpenHarmony 工程项目的 src/applications/sample/wifi-iot/app 目录下的 BUILD.gn 文件内容不变,和前面的一样,具体内容如下:

import("//build/lite/config/component/lite_component.gni")

lite_component("app") {
    features = [
        #"01_led_demo:my_led",
        #"02_key_demo:my_key",
        "03_pwm_demo:my_pwm",
    ]
}
4. 代码编译和烧录

        按照3.2节介绍的方法进行代码编译和烧录,在烧录完成后,按下复位按键,可以看到三色 LED 灯交替显示红绿蓝三种颜色,且每种颜色由暗到亮逐渐显示。

版权所有 © 2023 东莞龙元智能科技有限公司

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

附:本文档相关配套资料

1、配套开发板龙元智能 LY-01 淘宝链接:https://item.taobao.com/item.htm?abbucket=20&id=792601994657&spm=a230r.7195193.1997079397.6.638a4fd8mRWYWP

2、配套视频教程 bilibili 链接:【鸿蒙3.1设备开发教程】龙元智能 HarmonyOS 3.1 鸿蒙设备开发实战教程_哔哩哔哩_bilibili

3、配套程序代码:在官方淘宝店购买开发板后,找客服获取整套教程配套程序代码。

官方淘宝店
官方bilibili 配套视频
官方微信公众号

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐