【星闪】Hi2821 | PWM脉宽调制模块 + 呼吸灯例程

1. 简介

        PWM(Pulse Width Modulation),全称脉宽调制,通过对一系列脉冲的宽度进行调制,等效出所需波形。即对模拟信号电平进行数字编码,通过调节频率、占空比的变化来调节信号的变化。

        一个 PWM 周期内由一段高电平和一段低电平区间组成,通过调整高低电平的时间,即占空比,可以等效输出不同的电压。

        比如,周期为 100ms,高电平时间为 50ms,低电平时间为 50ms,即占空比为 50%,VCC 假设为 5V,那么等效输出的电压为 1.15V。

2. 硬件特性

        Hi2821 一共有 12 路 PWM 输出通道;支持PWM分组,一个组可以分配多个通道,同一个通道不能同时位于不同的组里。

3. 例程

3.1 Kconfig

        SDK 是默认打开 PWM 的编译的,配置项不多,基本上也不需要配置。唯一可能要配置的是最后一个“Using PWM PRELOAD”,它的作用是可以预配置一系列占空比,这样 PWM 输出完一个周期后,驱动会自动加载下一个周期的配置。

3.2 代码

#include "soc_osal.h"
#include "app_init.h"
#include "pwm.h"
#include "hal_pwm.h"
#include "pinctrl.h"#include <string.h>
#include <stdint.h>#define PWM_GROUP_ID 0static uint8_t pwm_chn = 0;
static pwm_config_t pwm_cfg = {1000,0,0,100,false
};static errcode_t pwm_callback(uint8_t channel)
{static uint8_t dir = 0;if (dir) {pwm_cfg.low_time++;pwm_cfg.high_time--;} else {pwm_cfg.low_time--;pwm_cfg.high_time++;}/* 更新占空比 */hal_pwm_funcs_t *func = hal_pwm_get_funcs();func->set_time(PWM_SET_LOW_TIME, (pwm_channel_t)channel, pwm_cfg.low_time);func->set_time(PWM_SET_HIGH_TIME, (pwm_channel_t)channel, pwm_cfg.high_time);func->set_action(PWM_GROUP_ID, PWM_ACTION_START);osal_printk("duty cycle, high: %u, low: %u\r\n", pwm_cfg.high_time, pwm_cfg.low_time);if (pwm_cfg.low_time == 0) {dir = 1;} else if (pwm_cfg.low_time == 1000) {dir = 0;}return 0;
}void app_main(void *unused)
{(void)(unused);int ret = 0;/* 初始化管脚 */uapi_pin_set_mode(31, HAL_PIO_PWM0);/* 初始化PWM */uapi_pwm_deinit();uapi_pwm_init();ret = uapi_pwm_open(pwm_chn, &pwm_cfg);if (ret) {osal_printk("PWM init failed, err: %X");return;}uapi_pwm_register_interrupt(pwm_chn, pwm_callback);osal_printk("\r\nPWM freq: %d Hz\r\n", uapi_pwm_get_frequency(pwm_chn));uapi_pwm_set_group(PWM_GROUP_ID, &pwm_chn, 1);uapi_pwm_start_group(PWM_GROUP_ID);
}

1. 初始化管脚

        我使用的是开发板上自带的 LED 灯,对应 31 号管脚,只需要调用 uapi_pin_set_mode 函数配置复用到对应的 PWM 通道即可。

2. 初始化 PWM

        先调用 uapi_pwm_init 初始化驱动;接着调用 uapi_pwm_open 配置通道运行参数,参数一为通道号,参数二为运行参数,定义如下:

typedef struct pwm_config {uint32_t low_time;               /*!< @if Eng PWM working clock cycle count low level part,PWM work frequency @ref uapi_pwm_get_frequency().If the PWM operating cycle is Tus,the actual low-level time = low_time * Tus.@else   PWM工作时钟周期计数个数低电平部分,频率参考 @ref uapi_pwm_get_frequency()。如果PWM工作周期为Tus, 实际低电平时间 = low_time * Tus @endif */uint32_t high_time;              /*!< @if Eng PWM working clock cycle count high level part,PWM work frequency @ref uapi_pwm_get_frequency().If the PWM operating cycle is Tus,the actual high-level time = high_time * Tus.@else   PWM工作时钟周期计数个数高电平部分,频率参考 @ref uapi_pwm_get_frequency()。如果PWM工作周期为Tus, 实际高电平时间 = high_time * Tus @endif */uint32_t offset_time;            /*!< @if Eng PWM offset time.@else   PWM相位。  @endif */uint16_t cycles;                 /*!< @if Eng PWM cycles, range:0~32767 (15bit).@else   PWM重复周期,范围:0~32767 (15bit)。  @endif */bool repeat;                     /*!< @if Eng Flag to indicate PWM should output continuously.@else   指示PWM应连续输出的标志。  @endif */
} pwm_config_t;
  • low_time:低电平时间;
  • high_time:高电平时间;
  • offset_time:相位偏移;
  • cycles:重复周期;
  • repeat:是否连续周期。

        PWM 的时钟默认是 32MHz,也可以调 uapi_pwm_get_frequency 去获取。low_time 和 high_time 的值是 PWM 时钟的周期数,那么可以得出一个 PWM 周期的时间为:(low\_time+high\_time)\times \frac{1}{32000000}

        cycles 和 repeat 是互斥的,如果设置了 repeat,那么驱动会忽略 cycles 的值。

        然后调用 uapi_pwm_register_interrupt 注册中断回调,当 PWM 完成了一个输出任务时,这个回调就会调用。

如果设置了 repeat 这个中断就永远不会调用,因为输出的任务永远不会结束。

另外,中断回调注册一定要放在 uapi_pwm_open 之前,因为后者会使用驱动默认的中断回调去覆盖回调函数。

        调用 uapi_pwm_set_group 设置 PWM 组,最多可设置 6 个组;参数一为组号,参数二为通道号列表,参数三为通道数。最后调用 uapi_pwm_start_group 去使能对应组的输出任务。

3. 中断回调函数

        在中断回调函数里面去调整占空比,目前的 SDK 比较 low,还没有移植调整占空比的函数,所以只能调用 HAL 层的函数接口去调整。

        调用 hal_pwm_get_funcs 函数可以获取 PWM 底层的操作函数,调用 set_time 函数可以调整 low_time 和 high_time 的值,调整完成后需要调用 set_action 去使能 PWM 输出任务,参数一为组号,参数二填 PWM_ACTION_START。

3.3 测试

        编译并烧录固件,此时就能看到呼吸灯的效果了,下面为部分系统 log。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/95916.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/95916.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

51单片机---硬件学习(电子琴、主从应答模式、modbus模型、DS18B20传感器显示温度)

一、串行通信与并行通信1、串行通信定义&#xff1a;数据一位一位地按顺序通过单条传输线进行传输的通信方式。优点&#xff1a;传输线少&#xff0c;成本低&#xff0c;适合长距离传输缺点&#xff1a;传输速度相对较慢2、并行通信定义&#xff1a;数据的各位同时通过多条并行…

SpringBoot后端开发常用工具详细介绍——SpringSecurity认证用户保证安全

简单的开始 创建SpringBoot项目 首先创建一个简单的springboot项目&#xff0c;假设端口为8888&#xff0c;添加controller控制层&#xff0c;并在其中添加TestController控制类&#xff0c;那么启动springboot项目之后&#xff0c;访localhost:8888/api/message页面会显示my…

别再手工缝合API了!开源LLMOps神器LMForge,让你像搭积木一样玩转AI智能体!

你是否受够了这些&#xff1f; 刚调通OpenAI的API&#xff0c;老板说“咱们试试国产模型降本增效”&#xff0c;你看着满屏的if-else只想说“我晕”。想给AI加上“查天气”、“执行代码”的能力&#xff0c;却发现Function Calling的代码复杂得让人头皮发麻。本地的Agentdemo惊…

window使用ffmep工具,加自定义脚本执行视频转码成h264(运营人员使用)

技术文章大纲&#xff1a;ffmep配合脚本使用1. 需要提供脚本给视频转码的给运营,给运营上传视频使用安装ffmep windows版本(目前我使用的就是windows)将脚本里面的执行路径修改成自己的电脑安装ffmep/bin/ffmep.exe路径处理好之后就点击执行2.环境准备ffmep windows版解压到一个…

Leetcode 240. 搜索二维矩阵 II 矩阵 / 二分

原题链接&#xff1a; Leetcode 240. 搜索二维矩阵 II 解法一&#xff1a;排除法 参考 【图解】排除法&#xff0c;一图秒懂&#xff01;&#xff08;Python/Java/C/C/Go/JS/Rust&#xff09; 从右上角&#xff1a; class Solution { public:bool searchMatrix(vector<vec…

OCR 证件识别:驱动澳门酒店自助入住智能化

澳门酒店作为国际旅游窗口&#xff0c;每日接待持多元证件的旅客&#xff0c;OCR 证件识别技术的应用&#xff0c;让自助入住终端实现 “一证通办”&#xff0c;大幅提升服务效率。​旅客在自助终端办理入住时&#xff0c;只需将护照、港澳通行证、回乡证、电子身份证等证件贴近…

深入解析汇编语言的奥秘

汇编语言简介汇编语言&#xff08;Assembly Language&#xff09;是一种低级编程语言&#xff0c;直接对应计算机的机器指令集。它通过助记符&#xff08;如 MOV、ADD&#xff09;代替二进制操作码&#xff0c;更接近硬件架构&#xff0c;常用于性能优化、嵌入式开发或逆向工程…

Nextcloud 实战:打造属于你的私有云与在线协作平台

随着数据安全与隐私保护意识的提升&#xff0c;越来越多的个人和组织选择自建云平台来替代公有云。Nextcloud 作为一款开源的文件同步与协作套件&#xff0c;不仅能实现类似网盘的文件存储与分享&#xff0c;还提供日历、联系人、即时通讯、在线文档编辑等协作功能&#xff0c;…

实践指南:利用衡石AI Data Agent实现自然语言驱动的指标开发与归因

在数字化转型的深水区&#xff0c;企业数据团队常面临两难困境&#xff1a;业务部门需要敏捷响应的指标分析&#xff0c;但传统BI工具依赖技术团队编写SQL&#xff0c;导致需求交付周期长达数周&#xff1b;而直接暴露底层数据又存在安全与合规风险。衡石科技推出的AI Data Age…

知微集:Python中的线程(三)

欢迎来到"一起学点什么吧"的合集「NLP知微集」。在这里&#xff0c;我们不愿宏大叙事&#xff0c;只聚焦于自然语言处理领域中那些细微却关键的“齿轮”与“螺丝钉”。我相信&#xff0c;真正深刻的理解&#xff0c;源于对细节的洞察。本期&#xff0c;我将为您拆解的…

动态规划入门:从记忆化搜索到动态规划

在开始对动态规划的讲解之前&#xff0c;我们需要先对记忆化搜索进行回顾&#xff1a; 什么是记忆化搜索&#xff1f; 在搜索过程中&#xff0c;当搜索树中存在大量重复的节点时&#xff0c;我们可以通过引入一个"备忘录"&#xff08;通常是一个数组或哈希表&#…

Boost搜索引擎 网络库与前端(4)

文章目录前言一、引入网络库模块引入cpp-httplibcpp-httplib测试正式编写http_server二、前端模块三、项目的可能拓展总结前言 终于到了最后一篇喽&#xff0c;嘻嘻&#xff01; 一、引入网络库模块 引入cpp-httplib 下载地址如下&#xff0c;我个人不喜欢新版本   cpp-http…

Flink反压问题

背景在使用flink的过程中&#xff0c;多次遇到过反压&#xff08;backpressure&#xff09;的问题&#xff0c;这通常是因为数据处理的速率超过了数据源或下游系统的处理能力导致。反压的底层剖析网络流控一个重要的概念是网络流控&#xff0c;如上图&#xff0c;不同的Consume…

Day5-中间件与请求处理

昨天搞定了异步优化&#xff0c;今天来解决一些实际问题。Day4的API虽然性能不错&#xff0c;但还缺少一些企业级应用必备的功能。 现在的问题 前端无法访问API&#xff08;跨域问题&#xff09;没有请求日志&#xff0c;出问题难以排查错误信息格式不统一缺少统一的请求处理机…

【LeetCode热题100道笔记】反转链表

题目描述 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a;输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a;输入&#xff1a;head [1,2] 输出&#xff1a;[2,1] 示例 3&#xff1a;…

Oracle:select top 5

在Oracle数据库中实现SELECT TOP 5功能需采用特定语法&#xff0c;因其原生不支持TOP关键字。以下是两种主流实现方式&#xff1a;‌ROWNUM结合子查询‌先通过子查询排序数据&#xff0c;再在外层用ROWNUM限制行数&#xff1a;SELECT * FROM ( SELECT * FROM 表名 ORDER BY 排序…

Kubernetes(k8s) 增量更新 po

文章目录前言k8s 增量更新 po1. 导出要新建po 的控制器配置2. 配置详解3. 重新生效前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在…

基于stm32的车辆安全驾驶预警系统

若该文为原创文章&#xff0c;转载请注明原文出处。一、 项目背景与引言(一) 研究背景及意义道路交通安全是全球性的重大公共安全问题。据统计&#xff0c;绝大多数交通事故源于驾驶员的危险状态&#xff08;疲劳、分心、健康突发状况&#xff09;和危险驾驶行为&#xff08;超…

React学习教程,从入门到精通, React 新创建组件语法知识点及案例代码(11)

React 新创建组件语法知识点及案例代码 React 是由 Facebook 开发的一个用于构建用户界面的 JavaScript 库。随着 React 的不断发展&#xff0c;创建组件的方式也在不断演进。本文将详细介绍 React 中创建组件的最新语法&#xff0c;包括函数组件&#xff08;Functional Compo…

SQL Server全链路安全防护

SQL Server 的安全性是一个多层次、综合性的体系&#xff0c;旨在保护数据免受未授权访问、篡改和泄露。其核心安全机制可概括为以下几个方面&#xff1a;1. 身份验证&#xff08;Authentication&#xff09; Windows 身份验证&#xff1a; 使用 Windows 账户&#xff08;域/本…