IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 启明智显分享| ESP32学习笔记参考--PWM(脉冲宽度调制) 篇,配PWM控制 LED呼吸灯代码示例参考 -> 正文阅读

[嵌入式]启明智显分享| ESP32学习笔记参考--PWM(脉冲宽度调制) 篇,配PWM控制 LED呼吸灯代码示例参考

提示:启明智显专为智能产品提供一站式彩屏显示+连接+云端服务+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 输出提供时钟。每个单元还能够收集输入,例如检测电机过电流或过电压

在这里插入图片描述

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-03-24 00:45:14  更:2022-03-24 00:46:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/23 21:54:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码