启明智显分享| ESP32学习笔记参考--PWM(脉冲宽度调制) 篇,配PWM控制 LED呼吸灯代码示例参考_esp32pwm-程序员宅基地

技术标签: 乐鑫ESP方案及开发文档  ESP32  PWM  蓝牙  WIFI  串口屏  

提示:启明智显专为智能产品提供一站式彩屏显示+连接+云端服务+APP软件开发、维护等解决方案,帮厂商快速实现硬件的智能化。作为启明云端旗下方案公司,我们用心整理了开发小伙伴在开发过程中可能会遇到的问题以及快速上手的简明教程,同时也用心整理了连接+显示应用的新方案!希望你能第一时间了解并快速用上好的方案和产品!

在这里插入图片描述


参考文献
https://xuhong.blog.csdn.net/article/details/80417430
https://blog.csdn.net/weixin_43677266/article/details/121694652

PWM叫脉冲宽度调制,通过编程控制输出方波的频率和占空比(高电平的比例),广泛应用在测量,通信,功率控制与变换等各种领域(呼吸灯,电机)。

PWM其实就是模拟方式稳定输出,通过调节PWM的占空比和周期来调节电压电流大小

占空比:就是输出的PWM中,高电平保持的时间与该PWM的时钟周期的时间之比。如一个PWM的频率是1000 Hz,那么它的时钟周期就是1000 us,如果高电平出现的时间是200 us,那么低电平的时间肯定是800 us,那么PWM的占空比就是200 : 1000,也就是1 : 5

分辨率:就是占空比最小能达到多少。如8位的PWM,理论的分辨率就是1:255(单斜率),16位的的PWM理论就是1 : 65535(单斜率)。可见,双斜率的计数时间多了一倍,所以输出的PWM频率就慢了一半,但是分辨率却是1:(80+80) =1 :160,就是提高了一倍。

双斜率/单斜率:假设一个PWM从0计数到80,之后又从0计数到80,这个就是单斜率;一个PWM从0计数到80,之后从80计数到0,这个就是双斜率

PWM由定时器驱动,定时器的周期就是PWM的周期,为了控制高低电平的比例,会在定时器的基础上加上一个比较寄存器,同时需要和GPIO口集合输出PWM波

在这里插入图片描述
PWM波的高低电平的顺序是由极性,PWM模式和计数模式共同决定。极性决定有效电平(默认电平),PWM模式指的是一个周期内有效电平和无效电平的顺序。


LED PWM控制器

LED_PWM 主要用于控制 LED 的亮度和颜色,也可以产生 PWM 信号用于其他用途。LED_PWM 有16路通道, 即8路高速通道和8路低速通道。PWM 控制器还能够自动逐渐增加或减少占空比,LED_PWM 还支持小数分频。

下面是LED_PWM基本架构图
在这里插入图片描述
高速通道和低速通道各有4个时钟模块,可以从中任选一个 h/l_timerx

低速通道的分频器相对于高速通道的分频器来说有以下 2 点区别

  1. 高速定位器的时钟源采用了 REF_TICK 或 APB_CLK,低速定位器采用了 REF_TICK 或 SLOW_CLOCK。(置位 LEDC_APB_CLK_SEL 寄存器, SLOW_CLOCK 的频率为 80 MHz,否则为 8 MHz。)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e8FFtNar-1647928339609)(C:\Users\SNKjxn\AppData\Roaming\Typora\typora-user-images\image-20220106165924752.png)]
  2. 当修改了高速通道计数器的最大值或分频系数时,输出信号的更新将会在下一次溢出中断之后生效。而低速通道在置位 LEDC_LSTIMERx_PARA_UP之后,立刻更新计数器的计数范围参数和分频器的分频系数。

常用配置频率及精度

在这里插入图片描述

主要函数

ledc_channel_config()

LEDC 通道配置

esp_err_t ledc_channel_config (const ledc_channel_config_t* ledc_conf)
ledc_channel_config_t typedef struct{
     
	int gpio_num; 
    ledc_mode_t speed_mode; //速度 
    ledc_channel_t channel; //通道 
    ledc_intr_type_t intr_type; //中断使能 
    ledc_timer_t timer_sel; //定时器通道 
    uint32_t duty; //占空比 
}ledc_channel_config_t; 
ledc_fade_func_install()

安装 LEDC 淡入淡出功能

esp_err_t ledc_fade_func_install(int intr_alloc_flags)
/*
intr_alloc_flags: 用于分配中断的标志
*/
ledc_set_fade_with_time()

有时间限制的设置LEDC淡入淡出功能

esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms)
/*
speed_mode:		选择指定速度模式的 LEDC 通道组
channel: 		LEDC 通道号,从 ledc_channel_t 中选择
target_duty:	衰落的目标占空比
max_fade_time_ms:衰落的最大时间(毫秒)
*/
ledc_fade_start()

开始LED渐变

esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode)
/*
speed_mode:	选择指定速度模式的 LEDC 通道组
channel: 	LEDC 通道号
fade_mode:	是否阻塞直到淡入淡出完成
*/

LED呼吸灯代码

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"
#include "esp_err.h"

#define LEDC_HS_TIMER LEDC_TIMER_0 //定时器序号(LEDC_TIMER_0)
#define LEDC_HS_MODE LEDC_HIGH_SPEED_MODE // 定时器模式(高速模式)
#define LEDC_HS_CH0_GPIO 2 // IO 映射(GPIO2)
#define LEDC_HS_CH0_CHANNEL LEDC_CHANNEL_0 // PWM 通道0
#define LEDC_HS_CH1_GPIO 18 // IO 映射(GPIO18)
#define LEDC_HS_CH1_CHANNEL LEDC_CHANNEL_1 // PWM 通道1
#define LEDC_HS_CH2_GPIO 19 // IO 映射(GPIO19)
#define LEDC_HS_CH2_CHANNEL LEDC_CHANNEL_2 // PWM 通道2
#define LEDC_TEST_DUTY 8000 //渐变变大的最终目标的占空比
#define LEDC_TEST_FADE_TIME 3000 //变化时长3秒 

//定义配置PWM的结构体 
ledc_channel_config_t ledc_channel_R, ledc_channel_G, ledc_channel_B;
void LEDC_Init(void)
{
     
    //定时器配置结构体 
    ledc_timer_config_t ledc_timer = {
    
        .duty_resolution = LEDC_TIMER_13_BIT, // PWM占空比分辨率(1~15) 
        .freq_hz = 5000, // PWM信号频率 
        .speed_mode = LEDC_HS_MODE, // 定时器模式(速度模式) 
        .timer_num = LEDC_HS_TIMER // 定时器序号(LEDC_TIMER_0)
    };
    ledc_timer_config(&ledc_timer); // 设置定时器 PWM 模式 
    
    //配置ledc_channel_R
    ledc_channel_R.channel = LEDC_HS_CH0_CHANNEL; // PWM 通道0 
    ledc_channel_R.duty = 0; // 占空比为0 
    ledc_channel_R.gpio_num = LEDC_HS_CH0_GPIO; // IO 映射(GPIO18) 
    ledc_channel_R.speed_mode = LEDC_HS_MODE; // 定时器模式(速度模式) 
    ledc_channel_R.timer_sel = LEDC_HS_TIMER; // 定时器序号(LEDC_TIMER_0) 
    ledc_channel_config(&ledc_channel_R); //配置 PWM 
    
    //配置ledc_channel_G 
    ledc_channel_G.channel = LEDC_HS_CH1_CHANNEL; // PWM 通道0 
    ledc_channel_G.duty = 0; // 占空比为0 
    ledc_channel_G.gpio_num = LEDC_HS_CH1_GPIO; // IO 映射(GPIO18) 
    ledc_channel_G.speed_mode = LEDC_HS_MODE; // 定时器模式(速度模式) 
    ledc_channel_G.timer_sel = LEDC_HS_TIMER; // 定时器序号(LEDC_TIMER_0)
    ledc_channel_config(&ledc_channel_G); //配置 PWM 
    
    //配置ledc_channel_B 
    ledc_channel_B.channel = LEDC_HS_CH2_CHANNEL; // PWM 通道0 
    ledc_channel_B.duty = 0; // 占空比为0 
    ledc_channel_B.gpio_num = LEDC_HS_CH2_GPIO; // IO 映射(GPIO18) 
    ledc_channel_B.speed_mode = LEDC_HS_MODE; // 定时器模式(速度模式)
    ledc_channel_B.timer_sel = LEDC_HS_TIMER; // 定时器序号(LEDC_TIMER_0)
	ledc_channel_config(&ledc_channel_B); //配置 PWM 
    
    // 使能 ledc 渐变 
    ledc_fade_func_install(0);
}

void app_main()
{
     
    LEDC_Init(); 
    while (1) 
    {
    
        printf("1. PWM逐渐变大的周期目标 = %d\n", LEDC_TEST_DUTY);
    	// ledc 渐变至 100%,时间 LEDC_TEST_FADE_TIME
    	ledc_set_fade_with_time(ledc_channel_R.speed_mode, 				 									ledc_channel_R.channel,
                            	LEDC_TEST_DUTY,
                            	LEDC_TEST_FADE_TIME); 
        
    	ledc_fade_start(ledc_channel_R.speed_mode,
                        ledc_channel_R.channel,
                        LEDC_FADE_NO_WAIT);
        vTaskDelay(LEDC_TEST_FADE_TIME / portTICK_PERIOD_MS); //延时3秒 
        
        // ledc 渐变至 100%,时间 LEDC_TEST_FADE_TIME
        ledc_set_fade_with_time(ledc_channel_G.speed_mode,
                                ledc_channel_G.channel,
                                LEDC_TEST_DUTY,
                                LEDC_TEST_FADE_TIME);
        
        ledc_fade_start(ledc_channel_G.speed_mode,
                        ledc_channel_G.channel,
                        LEDC_FADE_NO_WAIT);
        vTaskDelay(LEDC_TEST_FADE_TIME / portTICK_PERIOD_MS); //延时3秒 
        
        // ledc 渐变至 100%,时间 LEDC_TEST_FADE_TIME
        ledc_set_fade_with_time(ledc_channel_B.speed_mode,
                                ledc_channel_B.channel,
                                LEDC_TEST_DUTY,
                                LEDC_TEST_FADE_TIME); 
        
        ledc_fade_start(ledc_channel_B.speed_mode,
                        ledc_channel_B.channel,
                        LEDC_FADE_NO_WAIT);
        vTaskDelay(LEDC_TEST_FADE_TIME / portTICK_PERIOD_MS); //延时3秒 
        printf("2. PWM逐渐变小的周期目标 = 0\n"); 
        // ledc 渐变至 0%,时间  LEDC_TEST_FADE_TIME
        ledc_set_fade_with_time(ledc_channel_R.speed_mode,
                                ledc_channel_R.channel,
                                0,
                                LEDC_TEST_FADE_TIME);
        
        ledc_fade_start(ledc_channel_R.speed_mode,
                        ledc_channel_R.channel,
                        LEDC_FADE_NO_WAIT); 
        vTaskDelay(LEDC_TEST_FADE_TIME / portTICK_PERIOD_MS); //延时3秒
        
        // ledc 渐变至 0%,时间 LEDC_TEST_FADE_TIME
        ledc_set_fade_with_time(ledc_channel_G.speed_mode,
                                ledc_channel_G.channel,
                                0, 
                                LEDC_TEST_FADE_TIME); 
        ledc_fade_start(ledc_channel_G.speed_mode,
                        ledc_channel_G.channel,
                        LEDC_FADE_NO_WAIT); 
        vTaskDelay(LEDC_TEST_FADE_TIME / portTICK_PERIOD_MS); //延时3秒 
        
        // ledc 渐变至 0%,时间 LEDC_TEST_FADE_TIME
        ledc_set_fade_with_time(ledc_channel_B.speed_mode,
                                ledc_channel_B.channel,
                                0,
                                LEDC_TEST_FADE_TIME); 
        ledc_fade_start(ledc_channel_B.speed_mode,
                        ledc_channel_B.channel,
                        LEDC_FADE_NO_WAIT);
        vTaskDelay(LEDC_TEST_FADE_TIME / portTICK_PERIOD_MS); //延时3秒 
    } 
}

MCPWM篇(电机控制PWM)

ESP32 有两个 MCPWM 单元,可用于控制不同类型的电机。每个单元具有三对 PWM 输出。

在这里插入图片描述
下面是MCPWM的详细框图,每个 A/B 对可由三个定时器 Timer 0、1 和 2 中的任何一个提供时钟。同一个定时器可用于为一对以上的 PWM 输出提供时钟。每个单元还能够收集输入,例如检测电机过电流或过电压

在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ami82/article/details/123658844

智能推荐

伪元素选择器和伪类选择器_伪类选择器和伪元素选择器-程序员宅基地

文章浏览阅读506次。伪类选择器是用来向某些选择器来添加效果。不修改DOM内容,通过一些特定的选择器根据特定的状态、特定条件来修改元素的样式。伪元素选择器是一个附加在选择器末尾的关键词,通过伪元素不需要借助元素的 ID 或 class 属性就可以对被选择元素的特定部分定义样式。_伪类选择器和伪元素选择器

websock报错:The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for caller-程序员宅基地

文章浏览阅读9.3k次。网上看到了一些关于这个错误的产生场景参考:场景:使用websocket遇到的一个小问题 The remote endpoint was in state [TEXT_PARTIAL_WRITING] which is an invalid stat我这里产生错误的场景是不同的,记录一下背景提供websocket服务的公司,其内部的系统已经与websocket server建立了长连接,图中的nginx是一个出口网关,其运维要求是出口网关与上游服务是不能建立长连接的。而我们作为外部公司_the remote endpoint was in state [text_full_writing] which is an invalid sta

.NET Core 3.0之深入源码理解Configuration(三)-程序员宅基地

文章浏览阅读350次。写在前面上一篇文章讨论了文件型配置的基本内容,本篇内容讨论JSON型配置的实现方式,理解了这一种配置类型的实现方式,那么其他类型的配置实现方式基本可以触类旁通。看过了上一篇文章的朋友,应该看得出来似曾相识。此图主要表达了文件型配置的实现,当然其他配置,包括自定义配置,都会按照这样的方式去实现。JSON配置组件的相关内容该组件有四个类JsonConfigura..._streamconfigurationprovider

助力企业应用与基础架构现代化 VMware这波组合拳够强!_助力企业应用与基础架构现代化 vmware这波组合拳够强!-程序员宅基地

文章浏览阅读2.7w次。顺应时代的发展,“数字化转型”已经成为企业发展的必由之路。应用作为数字化转型的核心,能够帮助企业向客户提供定制化的数字化体验,创造新的收入来源。在数字化转型道路上,中国企业走的并不慢甚至非常之快,在此过程中企业正逐步实现应用现代化,以此充分拥抱云环境潜力,并助力其在数字化道路上轻松迈进。正如VMware大中华区战略发展副总裁李映博士所言:“企业对于数字化转型,不再仅作为一个愿景看待,而是作为未..._助力企业应用与基础架构现代化 vmware这波组合拳够强!

设计一个形状类Shape,方法:求周长和求面积 形状类的子类:Rect(矩形),Circle(圆形) Rect类的子类:Square(正方形)-程序员宅基地

文章浏览阅读3.3w次,点赞21次,收藏98次。package homework;/*1.设计一个形状类Shape,方法:求周长和求面积形状类的子类:Rect(矩形),Circle(圆形)Rect类的子类:Square(正方形)不同的子类会有不同的计算周长和面积的方法创建三个不同的形状对象,放在Shape类型的数组里,分别打印出每个对象的周长和面积*/public class Shape { double sum=0;//周长 double a...

Matlab感知器算法实现(代码、结果)-程序员宅基地

文章浏览阅读8.5k次,点赞4次,收藏72次。目的1. 用感知器实现2分类2. 并画出决策面3. 画出不同weight初始值下的决策面、打乱样本顺序的决策面结构train.m 主文件 grad.m计算梯度并更新w、btrain.mclear;%load datadata = load('toydata.mat');X = data.X';y = data.label';m = length(y);l..._matlab感知器算法

随便推点

fir.im Weekly - 8 个不能错过的 iOS / Android 技术分享-程序员宅基地

文章浏览阅读812次。本期 fir.im Weekly 收集了 2 月下旬新鲜出炉的 iOS /Android 技术分享、源码等,iOS 中图片技术的解压缩、逆向实战、iOS SDK 实践,Android架构思考、Android触摸事件分发、蘑菇街Android热修复、MVP+Retrofit+RxJava网络请求框架搭建,希望对你有用。『 iOS开发分享』谈谈 iOS 中图片的解压缩“对于大多数 iOS 应用来说,图片

Ubuntu实时内核安装&Igh主站安装配置_invalid cpu passed to numa_node_of_cpu(4)-程序员宅基地

文章浏览阅读2.3k次,点赞3次,收藏38次。具体说明了Ubuntu实时内核配置和Igh EtherCAT Master主站搭建_invalid cpu passed to numa_node_of_cpu(4)

OpencvSharp图像融合_opencvsharp实现图像融合-程序员宅基地

文章浏览阅读2.7k次,点赞2次,收藏5次。最近学习OpencvSharp使用Opencv仿照C++opencv翻译过来。举个例子,图像融合C++版 clock_t start1, end1; clock_t start2, end2; Mat src = imread("D:/dd.jpg"); Mat dst = imread("D:/ss.jpg "); Mat src_mask = 25..._opencvsharp实现图像融合

Ubuntu 22.04 更新完内核重启卡在 grub 命令行解决办法_warning: os-prober will not be executed to detect -程序员宅基地

文章浏览阅读2.6k次。(sda是你的硬盘号码,千万不要指定分区号码,例如sda1,sda5等都不对)说是更新到 Grub 2.06 的 os-prober 用户需要手动干预。因为卡在 Grub 2 命令行界面,我们需要手动输命令引导。不管何种原因导致的故障,我们都往。_warning: os-prober will not be executed to detect other bootable partitions.

赋能零售成长型企业营销增长,云徙「数盈·新营销中台」发布_巨石崩塌后,有人看到了恐惧,有人看到了光-程序员宅基地

文章浏览阅读4.1k次。巨石崩裂时,有人看见了恐惧,有人看见了光。因为有光,万物生长。 疫情给每个企业的影响都是巨大的。但在疫情冲击之下,由中台技术推动企业数字化转型,又给企业带来了希望。 从2016年创业至今,云徙科技的每一次亮相,都在自我突破,引领创新,制造惊喜。今天,云徙科技召开「数in未来 一起发光」新品线上发布会,以3D科技秀的方式向企业伙伴及业界朋友正式介绍这款面向成长型企业用户产品「数盈·新营销中台..._巨石崩塌后,有人看到了恐惧,有人看到了光

git 手动master_git pull --rebase的正确使用-程序员宅基地

文章浏览阅读1.2k次。在多人使用同一个远程分支合作开发的时候,很可能出现 push 代码的时候出现以下问题:$ git push origin master# 结果如下To github.com:hello/demo.git! [rejected] master -> master (fetch first)error: failed to push some refs to 'git@github..._git pull --rebase master