【鸿蒙开发】Hi3861学习笔记- PWM

embedded/2025/3/23 18:39:58/

00. 目录

文章目录

    • 00. 目录
    • 01. 概述
    • 02. PWM相关类型
      • 2.1 hi_pwm_clk_source
      • 2.2 hi_pwm_port
    • 03. PWM相关API
      • 3.1 hi_pwm_init
      • 3.2 hi_pwm_deinit
      • 3.3 hi_pwm_start
      • 3.4 hi_pwm_stop
    • 04. 硬件设计
    • 05. 软件设计
    • 06. 实验现象
    • 07. 附录

01. 概述

PWM(Pulse Width Modulation , 脉冲宽度调制) 是一种对模拟信号电平进行数字编码的方法,通过不同频率的脉冲使用方波的占空比用来对一个具体模拟信号的电平进行编码,使输出端得到一系列幅值相等的脉冲,用这些脉冲来代替所需要波形的设备。

在这里插入图片描述

上图是一个简单的 PWM 原理示意图,假定定时器工作模式为向上计数,当计数值小于阈值时,则输出一种电平状态,比如高电平,当计数值大于阈值时则输出相反的电平状态,比如低电平。当计数值达到最大值是,计数器从0开始重新计数,又回到最初的电平状态。高电平持续时间(脉冲宽度)和周期时间的比值就是占空比,范围为0~100%。上图高电平的持续时间刚好是周期时间的一半,所以占空比为50%。

一个比较常用的pwm控制情景就是用来调节灯或者屏幕的亮度,根据占空比的不同,就可以完成亮度的调节。PWM调节亮度并不是持续发光的,而是在不停地点亮、熄灭屏幕。当亮、灭交替够快时,肉眼就会认为一直在亮。在亮、灭的过程中,灭的状态持续时间越长,屏幕给肉眼的观感就是亮度越低。亮的时间越长,灭的时间就相应减少,屏幕就会变亮。

在这里插入图片描述

PWM_21">02. PWM相关类型

2.1 hi_pwm_clk_source

/*** @ingroup iot_pwm** Enumerates the PWM clock sources.CNcomment:PWM时钟源枚举。CNend*/
typedef enum {PWM_CLK_160M, /**< 160M APB clock.CNcomment:160M 工作时钟 CNend */PWM_CLK_XTAL, /**< 24M/40M crystal clock.CNcomment:24M或40M 晶体时钟 CNend */PWM_CLK_MAX   /**< Maximum value, which cannot be used.CNcomment:最大值,不可使用CNend */
} hi_pwm_clk_source;

2.2 hi_pwm_port

/*** @ingroup iot_pwm** Enumerates the PWM ports.CNcomment:PWM端口枚举。CNend*/
typedef enum {HI_PWM_PORT_PWM0 = 0, /**< PWM port0. Register base address: 0x40040000, multiplexed with GPIOX.CNcomment:PWM0端口。寄存器基址:0x40040000,复用GPIOX。CNend */HI_PWM_PORT_PWM1 = 1, /**< PWM port1. Register base address: 0x40040100, multiplexed with GPIOX.CNcomment:PWM1端口。寄存器基址:0x40040100,复用GPIOX。CNend */HI_PWM_PORT_PWM2 = 2, /**< PWM port2. Register base address: 0x40040200, multiplexed with GPIOX.CNcomment:PWM2端口。寄存器基址:0x40040200,复用GPIOX。CNend */HI_PWM_PORT_PWM3 = 3, /**< PWM port3. Register base address: 0x40040300, multiplexed with GPIOX.CNcomment:PWM3端口。寄存器基址:0x40040300,复用GPIOX。CNend */HI_PWM_PORT_PWM4 = 4, /**< PWM port4. Register base address: 0x40040400, multiplexed with GPIOX.CNcomment:PWM4端口。寄存器基址:0x40040400,复用GPIOX。CNend */HI_PWM_PORT_PWM5 = 5, /**< PWM port5. Register base address: 0x40040500, multiplexed with GPIOX.CNcomment:PWM5端口。寄存器基址:0x40040500,复用GPIOX。CNend */HI_PWM_PORT_MAX   /**< Maximum value, which cannot be used.CNcomment:最大值,不可使用CNend */
} hi_pwm_port;

PWMAPI_69">03. PWM相关API

3.1 hi_pwm_init

/**
* @ingroup iot_pwm
* @brief  Initializes the PWM module.CNcomment:PWM初始化。CNend
*
* @par   描述:
*            Initializes the PWM module.CNcomment:PWM初始化。CNend
* @attention
*        @li Before using the PWM function, ensure that the GPIO multiplexing relationship has been configured.
CNcomment:使用PWM功能前需要确认已配置GPIO复用关系。CNend
*        @li For details, see Hi3861 V100 API Development Guide.
CNcomment:具体配置方法请参见<Hi3861V100 API开发指南>Demo介绍小节相关说明。CNend
*        @li For details about the multiplexed GPIO, see the Hi3861 V100 Data Sheet.
CNcomment:具体复用的GPIO请参见<Hi3861 芯片 硬件用户指南>。CNend
*        @li Before using the PWM function, initialize the PWM.CNcomment:使用PWM功能前需要先初始化。CNend
*
* @param  port [IN]  type #hi_pwm_port PWM port number.CNcomment:PWM端口号。CNend
*
* @retval #HI_ERR_SUCCESS Success.
* @retval #Other          Failure. For details, see hi_errno.h.
* @par 依赖:
*            @li hi_pwm.h: Describes the APIs of the PWM module.CNcomment:文件用于描述PWM对外接口。CNend
* @see hi_pwm_deinit | hi_pwm_start | hi_pwm_stop。
*/
hi_u32 hi_pwm_init(hi_pwm_port port)
功能:初始化指定 PWM 端口
参数:port:指定的 PWM 端口。前面介绍芯片 GPIO 功能时,每个管脚都有对应的功能,在使用 PWM 时,需选择具有 PWM 功能的 IO 即可。
返回值:0 成功,1 失败        

3.2 hi_pwm_deinit

/**
* @ingroup iot_pwm
* @brief  Deinitializes the PWM module.CNcomment:PWM去初始化。CNend
*
* @par   描述:
*            Deinitializes the PWM module.CNcomment:PWM去初始化。CNend
*
* @attention Deinitialize the PWM module when the function iss not used.
CNcomment:不使用PWM功能时去初始化。CNend
*
* @param  port [IN]  type #hi_pwm_port PWM port number.CNcomment:PWM端口号。CNend
*
* @retval #HI_ERR_SUCCESS Success.
* @retval #Other          Failure. For details, see hi_errno.h.
* @par 依赖:
*            @li hi_pwm.h: Describes the APIs of the PWM module.CNcomment:文件用于描述PWM对外接口。CNend
* @see hi_pwm_init。
*/
hi_u32 hi_pwm_deinit(hi_pwm_port port)
功能:不使用 PWM 功能时去初始化
参数:port:指定的 PWM 端口。
返回值:0 成功,1 失败

3.3 hi_pwm_start

/**
* @ingroup iot_pwm
* @brief  Outputs the PWM signal according to the configured parameter.
*         PWM signal duty cycle = duty/freq Frequency = Clock source frequency/freq.
CNcomment:按配置的参数输出PWM信号。PWM信号占空比=duty/freq。频率=时钟源频率/freq。CNend
*
* @par   描述:
*            Starts the PWM signal output.CNcomment:启动PWM信号输出。CNend
*
* @attention This API cannot be called in an interrupt.CNcomment:不支持在中断中调用。CNend
*
* @param  port [IN] type #hi_pwm_port PWM port number.CNcomment:PWM端口号。CNend
* @param  duty [IN] type #hi_u16 PWM duty cycle count. Value range: [1, 65535]. The default value is 750.
CNcomment:PWM占空比计数值。取值范围为:[1, 65535]。默认值为750。CNend
* @param  freq [IN] type #hi_u16 Frequency division multiple. Value range: [1, 65535]. The default value is 1500.
CNcomment:分频倍数。取值范围为:[1, 65535]。默认值为1500。CNend
*
* @retval #HI_ERR_SUCCESS Success.
* @retval #Other          Failure. For details, see hi_errno.h.
* @par 依赖:
*            @li hi_pwm.h: Describes the APIs of the PWM module.CNcomment:文件用于描述PWM对外接口。CNend
* @see  hi_pwm_init | hi_pwm_stop。
*/
hi_u32 hi_pwm_start(hi_pwm_port port, hi_u16 duty, hi_u16 freq)
功能:启动 PWM 信号输出,不支持在中断中调用参数:port:指定的 PWM 端口。duty:PWM 占空比,范围 1-65535,默认值为 750。freq:分频系数,范围 1-65535,默认为 1500PWM 频率默认为 160MHz。
返回值:0 成功,1 失败

说明

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

Fout = Fclk / freq = 160 MHz / freq

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

占空比 = duty / freq

3.4 hi_pwm_stop

/**
* @ingroup iot_pwm
* @brief  Stops the PWM signal output.CNcomment:停止PWM信号输出。CNend
*
* @par   描述:
*          Stops the PWM signal output.CNcomment: 停止PWM信号输出。CNend
*
* @attention This API cannot be called in an interrupt.CNcomment:不支持在中断中调用。CNend
*
* @param  port [IN] type #hi_pwm_port PWM port number.CNcomment:PWM端口号。CNend
*
* @retval #HI_ERR_SUCCESS Success.
* @retval #Other          Failure. For details, see hi_errno.h.
* @par 依赖:
*            @li hi_pwm.h: Describes the APIs of the PWM module.CNcomment:文件用于描述PWM对外接口。CNend
* @see  hi_pwm_init | hi_pwm_start。
*/
hi_u32 hi_pwm_stop(hi_pwm_port port)
功能:停止 PWM 信号输出,不支持在中断中调用参数:port:指定的 PWM 端口。
返回值:0 成功,1 失败        

04. 硬件设计

在这里插入图片描述

从网络标号可知,LED 与芯片的 IO2 管脚连接,当该引脚输出高电平时,LED点亮,输出低电平时,LED 熄灭。

05. 软件设计

bsp_pwm.h

#ifndef __BSP_PWM_H__#define __BSP_PWM_H__#include <unistd.h>
#include "cmsis_os2.h"#include "hi_io.h"
#include "hi_gpio.h"//pwm初始化
void pwm_init(void);//设置pwm占空比
void pwm_set_duty1(uint16_t duty);#endif /*__BSP_PWM_H__*/ 

bsp_pwm.c

#include <unistd.h>
#include "bsp_pwm.h"#include "bsp_led.h"
#include "hi_pwm.h"//pwm初始化
void pwm_init(void)
{//1. GPIO初始化hi_gpio_init();//3. 设置GPIO为PWM功能hi_io_set_func(LED_PIN, HI_IO_FUNC_GPIO_2_PWM2_OUT);//4. 设置GPIO为输出hi_gpio_set_dir(LED_PIN, HI_GPIO_DIR_OUT);//PWM初始化hi_pwm_init(HI_PWM_PORT_PWM2);}//设置pwm占空比
void pwm_set_duty1(uint16_t duty)
{hi_pwm_start(HI_PWM_PORT_PWM2, duty, 4000);
}

template.c


#include <stdio.h>
#include <unistd.h>#include "ohos_init.h"
#include "cmsis_os2.h"#include "hi_io.h"
#include "hi_gpio.h"#include "bsp_pwm.h"#define TASK_STACK_SIZE 1024//任务1ID
osThreadId_t task1_id;
osThreadId_t task2_id;//线程回调入口函数
void task1 (void *argument)
{int16_t i = 0;//PWM初始化pwm_init();while(1){for (i = 0; i <= 2000; i++){printf("i = %d\n", i);pwm_set_duty1(i);usleep(1000);}for (i = 2000; i >= 0; i--){printf("i = %d\n", i);pwm_set_duty1(i);usleep(1000);}}}/*** @description: 初始化并创建任务* @param {*}* @return {*}*/
static void template_demo(void)
{  osThreadAttr_t attr;attr.name = "task1"; //任务名称attr.attr_bits = osThreadDetached; //分离状态attr.cb_mem = NULL;attr.cb_size = 0;attr.stack_mem = NULL;attr.stack_size = TASK_STACK_SIZE;attr.priority = osPriorityNormal;//创建任务1task1_id = osThreadNew(task1, NULL, &attr);if (NULL != task1_id){printf("任务1创建OK task1_id = %d\n", task1_id);}}
SYS_RUN(template_demo);

06. 实验现象

实验现象:LED 指示灯亮度变化,由暗变亮,再由亮变暗的循环过程。

07. 附录


http://www.ppmy.cn/embedded/174590.html

相关文章

利用Python爬虫获取Shopee(虾皮)商品详情:实战指南

在跨境电商领域&#xff0c;Shopee&#xff08;虾皮&#xff09;作为东南亚及台湾地区领先的电商平台&#xff0c;拥有海量的商品信息。无论是进行市场调研、数据分析&#xff0c;还是寻找热门商品&#xff0c;获取Shopee商品详情都是一项极具价值的任务。然而&#xff0c;手动…

科技查新和查收查引有什么区别?

信息的准确性与新颖性是科研领域的重要指标&#xff0c;它们不仅能够确保研究质量、锁定研究目标&#xff0c;还能推动科技创新。在科研过程中&#xff0c;科技查新与查收查引作为两种关键的信息咨询服务&#xff0c;发挥着不可替代的作用。尽管两者紧密相关&#xff0c;但在目…

【商城实战(44)】商城实战避坑指南:从问题排查到经验升华

【商城实战】专栏重磅来袭&#xff01;这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建&#xff0c;运用 uniapp、Element Plus、SpringBoot 搭建商城框架&#xff0c;到用户、商品、订单等核心模块开发&#xff0c;再到性能优化、安全加固、多端适配&#xf…

为什么TCP需要三次握手?一次不行吗?

文章目录 1. 三次握手的过程2. 为什么需要三次握手&#xff1f;3. 握手过程中每一步的具体作用4. 简单比喻5. 为什么是三次握手&#xff0c;而不是两次或四次&#xff1f;6. 三次握手中的序列号有什么作用&#xff1f;7. 总结 1. 三次握手的过程 三次握手是建立 TCP 连接的过程…

微信小程序:用户拒绝小程序获取当前位置后的处理办法

【1】问题描述&#xff1a; 小程序在调用 wx.getLocation() 获取用地理位置时&#xff0c;如果用户选择拒绝授权&#xff0c;代码会直接抛出错误。如果再次调用 wx.getLocation() 时&#xff0c;就不会在弹窗询问用户是否允许授权。导致用户想要重新允许获取地理位置时&#x…

WPF 中的 GridSplitter 详解

1. 什么是 GridSplitter&#xff1f; GridSplitter 是 WPF 提供的一个控件&#xff0c;用于调整 Grid 布局的行或列的大小。它可以让用户在运行时拖动分隔线&#xff0c;以改变相邻的行或列的大小&#xff0c;而不需要修改 XAML 代码。 2. GridSplitter 的基本用法 &#xff…

maven使用install将jar包编译到本地仓库管理

要install的jar包 mvn install:install-file -DgroupIdcn.qiufeng -DartifactIdDJGenHsmAPI -Dversion3.1.0d -Dpackagingjar -DfileDJGenHsmAPI-3.1.0d.jar 重点是版本号必须使用编译后的版本号 发布成功后

gitlab将本地项目提交到远程dev分支

获取Git路径 首先从远程获取到git路径&#xff0c;将给的git地址进行克隆到本地文件&#xff1b; git clone http:************.git 按照git地址的文件路径将本地项目&#xff0c;拷贝到目标文件中 在该路径中&#xff0c;初始化命令&#xff1b; # 初始化项目 git init #…