ESP8266_07----------------PWM呼吸灯

2023-05-16

先看下的效果:

呼吸灯

1.硬件电路:

---------------------------LED的阴极与我们的GPIO4相连。----------------------------

2.PWM介绍:

PWM 英文名为 Pulse Width Modulation ,是脉冲宽度调制的缩写,通过对一系列脉冲的宽度    进行调制,来等效地获得所需要的波形(含形状和幅值)。我们通过连续改变占空比就可以控制LED灯的亮度,从而实现呼吸灯的效果。
占空比:是指在一个脉冲循环内,通电时间相对于总时间所占的比例(也就是说高电平时间占的      比例)。

使用时的注意事项:

1.PWM 输出和硬件定时器不能够同时使用,因为他们使用的是同一个硬件。
2. 使用 PWM 输出的时候不支持进入 Deep Sleep 自动睡眠模式。
3.PWM 使用 NMI 中断,最多可以扩展 8 PWM 输出,但是 8 PWM 的周期相同,占空比可       以不同。
4.PWM 的分辨率可最高达到 45ns ,能够稳定输出的 PWM 波信号周期为1000us-10000us,对应     频率为 1kHz-100Hz

3.用到的函数:

PWM 的所有接口文件在“pwm.h”内声明

1.pwm_param结构体:

struct pwm_param {
    uint32 period;//周期
    uint32 freq;  //频率
    uint32  duty[PWM_CHANNEL_NUM_MAX];  //PWM_CHANNEL<=8 //八个通道的各自占空比
};
2..初始化 PWM 配置,设置 PWM 输出的 GPIO 、周期、占空比:
在使用pwm_init()函数之前,要配置好pwm_param结构体,它指明了我们PWM波形的周期和    占空比,而pwm_init()函数的最后一个参数:uint32 (*pin_info_list)[3])指明了我们的PWM各个通道用哪个GPIO端口。
void pwm_init(uint32 period,uint8 *duty,uint32 pwm_channel_num,uint32 (*pin_info_list)[3])
//uint32 period:PWM 周期,单位 us;
//uint8 *duty:各路 PWM 占空比;
//uint32 pwm_channel_num:PWM 输出通道数目;
//uint32 (*pin_info_list)[3]):PWM 各个通道的 GPIO 硬件参数。本参数为一个
//N*3 的数组指针,也就是一个二维数组,每一个通道有三个参数,对应存放在数
//组中,分别是 GPIO 的寄存器、对应的 PIN 脚的 IO 复用功能、GPIO 对应的序号。
//注意:此函数只允许调用一次。

例:

//PWM输出通道配置
uint32_t PWM_GPIO[1][3]={PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4,GPIO_ID_PIN(4)};
//PWM结构体:参数:周期,频率,8路的占空比(存在数组内)
struct pwm_param PWM_Param_Struct={1000,1000,{0}};
//PWM初始化:参数:周期,占空比,通道个数,PWM通道GPIO配置
pwm_init(PWM_Param_Struct.period,PWM_Param_Struct.duty,1,PWM_GPIO);
3..PWM 开始输出:
void pwm_start(void)
//注意:每一次更改了 PWM 的设置的时候都需要调用此函数,因为此函数内部进行了相应的计算。
4.设置 PWM 某一个通道的占空比:
void pwm_set_duty(uint32 duty,uint8 channel)
//设置 PWM 某个通道信号的占空⽐。设置各路 PWM 信号⾼电平所占的时间,duty 的范围随
//PWM 周期改变,最⼤值为:Period * 1000 /45。例如,1KHz PWM,duty 范围是:0 ~ 22222
//注意:设置完成后,需要调⽤ pwm_start ⽣效

 例:在频率=1KHz、通道=0情况下,我们可以计算duty范围: 0 ~ 1000*1000/45(0~22222)

       要产生占空比为50%的PWM波形:duty = 22222/2=11111。

      ( 注意:修改占空比之后需要调用 void pwm_start(void)才有效。)

void pwm_set_duty(11111,0);//配置通道0的占空比为50%
 5.  设置 PWM 的周期:
void pwm_set_period(uint32 period)
//uint32 period:PWM 输出的周期,单位 us。稳定的 PWM 输出周期范围1000us-10000us;
//注意:修改周期之后需要调用 void pwm_start(void)才有效。
6.获取某路 PWM 通道的 duty (也就是或者 PWM 输出通道的占空比,但是实际的占空比需要经过计算获得)
uint8 pwm_get_duty(uint8 channel)
//uint8 channel:需要查询的 PWM 输出通道号,通道号从 0 开始;
//注意:调用此 API 获取到的是 PWM 波对应通道的 duty 值,实际的占空比
//大小需要经过计算,实际占空比= (duty*45)/ (period*1000)。
7.获取 PWM 的周期:
uint32 pwm_get_period(void)
//返回值:PWM 周期,单位 us。
8.查询 PWM 的版本信息:
uint32 pwm_get_period(void)
//返回值:PWM 版本信息

4.程序的编写:

因为我们需要用到定时器不断改变占空比,所以直接复制软件定时器的工程,然后新建pwm_driver.cpwm_driver.h文件,然后将他们分别添加到app/driverapp/include/driver下,刷新工程。

1.pwm_driver.h:

#ifndef __PWM_DRIVER_H
#define __PWM_DRIVER_H

#include "ets_sys.h"
#include "osapi.h"   //系统函数
#include "user_interface.h"
#include "pwm.h"

extern struct pwm_param PWM_Structure;

#endif

2.pwm_driver.c:

#include "./driver/pwm_driver.h"

//PWM结构体
struct pwm_param PWM_Structure={1000,1000,{0}};//周期,频率,占空比

//PWM输出通道配置
uint32_t PWM_GPIO[1][3]={PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4,GPIO_ID_PIN(4)};

//PWM初始化
void ICACHE_FLASH_ATTR PWM_Init(void)
{
	pwm_init(PWM_Structure.period,PWM_Structure.duty,1,PWM_GPIO);//pwm初始化

}

3.os_timer.h:

#ifndef __OS_TIMER_H
#define __OS_TIMER_H

#include "ets_sys.h"
#include "osapi.h"   //系统函数
#include "user_interface.h"
#include "pwm.h"

void OS_Timer_1_Cb(void);//定时器回调函数
void OS_Timer_Init(uint32_t ms,bool repeat_flag);//定时器初始化函数

#endif /* OS_TIMER_H */

4.os_timer.c:

#include "./driver/os_timer.h"
#include "./driver/pwm_driver.h"

os_timer_t os_timer_1;//定义软件定时器结构体变量

//软件定时器回调函数
void OS_Timer_1_Cb(void)
{
	static uint8_t direction=0;
	int span = 300;//每次的增量或减量

	if(direction==0 && PWM_Structure.duty[0]<=22222)//占空比增大
	   {
		    PWM_Structure.duty[0]+=span;
	    }
	if(direction==1 && PWM_Structure.duty[0]>=0)//占空比减小
		{
			PWM_Structure.duty[0]-=span;
		}
	if(PWM_Structure.duty[0]>22222)//改变方向
	    {
		  direction=1;
	    }
	if(PWM_Structure.duty[0]<=span)//改变方向
		{
		  direction=0;
		}
	pwm_set_duty(PWM_Structure.duty[0],0);//设置占空比
	pwm_start();
}

//软件定时器配置初始化
void OS_Timer_Init(uint32_t ms,bool repeat_flag)
{
	os_timer_disarm(&os_timer_1);//关闭软件定时器
	os_timer_setfn(&os_timer_1,(os_timer_func_t*)OS_Timer_1_Cb,NULL);//注册软件定时器回调函数
	os_timer_arm(&os_timer_1,ms,repeat_flag);//打开软件定时器,设置定时周期,设置是否自动重装
}

5.user_main.c:

#include "ets_sys.h"
#include "user_config.h"//用户配置
#include "eagle_soc.h"//GPIO函数,宏定义
#include "c_types.h" //变量类型
#include "osapi.h"   //系统函数
#include "user_interface.h"
#include "pwm.h"

/******************************************************************************
 * FunctionName : user_rf_cal_sector_set
 * Description  : SDK just reversed 4 sectors, used for rf init data and paramters.
 *                We add this function to force users to set rf cal sector, since
 *                we don't know which sector is free in user's application.
 *                sector map for last several sectors : ABCCC
 *                A : rf cal
 *                B : rf init data
 *                C : sdk parameters
 * Parameters   : none
 * Returns      : rf cal sector
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map) {
        case FLASH_SIZE_4M_MAP_256_256:
            rf_cal_sec = 128 - 5;
            break;

        case FLASH_SIZE_8M_MAP_512_512:
            rf_cal_sec = 256 - 5;
            break;

        case FLASH_SIZE_16M_MAP_512_512:
            rf_cal_sec = 512 - 5;
            break;
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;
            break;

        case FLASH_SIZE_32M_MAP_512_512:
            rf_cal_sec = 1024 - 5;
            break;
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;
            break;

        case FLASH_SIZE_64M_MAP_1024_1024:
            rf_cal_sec = 2048 - 5;
            break;
        case FLASH_SIZE_128M_MAP_1024_1024:
            rf_cal_sec = 4096 - 5;
            break;
        default:
            rf_cal_sec = 0;
            break;
    }

    return rf_cal_sec;
}

void ICACHE_FLASH_ATTR
user_rf_pre_init(void)
{
}

//毫秒延时函数
void ICACHE_FLASH_ATTR
delay_ms(u32 ms)
{
	for(;ms>0;ms--){
		os_delay_us(1000);//1ms
	}
}
/******************************************************************************
 * FunctionName : user_init
 * Description  : entry of user application, init user function here
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_init(void)
{
  os_printf("\r\nESP8266PWM呼吸灯实验\r\n");//波特率=74880
  PWM_Init();//PWM初始化
  OS_Timer_Init(10,1);//10ms改变一次占空比,重装载
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ESP8266_07----------------PWM呼吸灯 的相关文章

  • CH7-广播机制

    文章目录 目标一 广播机制的概述目标 二 广播接收者目标2 1 什么是广播接收者2 2 创建广播接收者动态注册静态注册 三 自定义广播与广播的类型目标3 1 自定义广播3 2 实战演练 饭堂小广播3 3 广播的类型无序广播有序广播有序广播的
  • 【零基础】看懂理解傅里叶变换后的频谱图-附例题

    首先安利一个网站 xff0c 在线做傅里叶变换 xff0c 不用等MATLAB漫长的启动了 https sci2fig herokuapp com fourier 文章中部分图片来自 https blog csdn net ViatorSu
  • 【GO】vscode下安装go-outliner等go语言插件extension失败:no log

    不要再去git clone后install了 xff0c 根本没用 xff01 在powershell中分别运行以下命令 xff1a env GO111MODULE 61 on env GOPROXY 61 https goproxy io
  • 远控免杀从入门到实践之白名单(113个)总结篇

    郑重声明 xff1a 文中所涉及的技术 思路和工具仅供以安全为目的的学习交流使用 xff0c 任何人不得将其用于非法用途以及盈利等目的 xff0c 否则后果自行承担 xff01 远控免杀从入门到实践 系列文章目录 xff1a 1 远控免杀从
  • 计算机基础和Linux安装

    成功不易 xff0c 加倍努力 xff01 一 计算机系统1 计算机硬件1 1 计算机发展历史1 2 冯诺依曼体系理论的要点1 3 计算机分类1 4 服务器硬件组成 2 操作系统2 1 操作系统功能2 2 操作系统相关概念 一 计算机系统
  • LInux高级编程 - 线程(Threads)

    http www 91linux com html article program cpp 20090105 15374 html ALP Chapter 4 线程 xff08 Threads xff09 线程可以简单理解成为进程的下级 一
  • 网络协议和管理

    成功不易 xff0c 加倍努力 xff01 1 网络基础1 1 网络概念1 2 常见的网络物理组件1 3 网络应用程序1 3 1 各种网络应用1 3 2 应用程序对网络的要求 1 4 网络的特征1 4 1 速度 带宽 1 4 2 网络拓扑
  • Linux进阶_OpenSSL

    成功不易 xff0c 加倍努力 xff01 OpenSSL1 OpenSSL 介绍2 Base64 编码3 openssl命令3 1 openssl命令对称加密3 2 openssl命令单向哈希加密3 3 openssl命令生成用户密码3
  • Linux进阶_SSH服务

    成功不易 xff0c 加倍努力 xff01 ssh服务1 ssh服务介绍1 1 公钥交换原理1 2 ssh加密通讯原理 2 openssh2 1 客户端ssh命令2 2 ssh登录验证方式介绍2 3 实现基于密钥的登录方式3 4 其它ssh
  • 运维自动化之ANSIBLE

    成功不易 xff0c 加倍努力 xff01 运维自动化之ANSIBLE本章内容1 自动化运维应用场景1 1 云计算运维工程师核心职能1 2 运维职业发展路线1 3 企业实际应用场景分析1 3 1 Dev开发环境1 3 2 测试环境1 3 3
  • 企业级监控ZABBIX

    第一部分 Zabbix安装部署 实现分布式监控及网络知识 Zabbix 监控及业务整体规划图安装Zabbix Server端和数据库安装客户端实现被动模式监控监控tomcat安装Zabbix proxy端和数据库配置zabbix 主动模式代
  • 26.Nginx详解

    文章目录 一 Web服务基础介绍 xff1a 1 1 互联网发展历程回顾 xff1a 1 2 xff1a web服务介绍 xff1a 1 2 1 Apace 早期的web服务端 xff1a 1 2 1 3 xff1a Apache even
  • 38.DevOps之基于Jenkins实现的CI与CD

    文章目录 一 DevOps 简介1 1 什么是 DevOps1 2 为什么要推广 DevOps xff1f 1 3 传统技术团队1 4 DevOps 技术团队1 5 什么是持续集成 CI Continuous integration 1 6
  • ELK日志系统详解

    文章目录 前言什么是 ELK xff1f 什么是 Elasticsearch什么是 Logstash什么是 kibana为什么使用 ELK xff1f ELK 的好处谁在使用 ELK 一 elasticsearch 部署1 1 环境初始化1
  • 流感传染(信息学奥赛一本通)

    题目描述 有一批易感人群住在网格状的宿舍区内 xff0c 宿舍区为 n n 的矩阵 xff0c 每个格点为一个房间 xff0c 房间里可能住人 xff0c 也可能空着 在第一天 xff0c 有些房间里的人得了流感 xff0c 以后每天 xf
  • 问题解决——VMware中Ubuntu的桌面和字体很小

    问题解决 VMware中Ubuntu的桌面和字体很小 方法 xff1a 更改Ubuntu分辨率 xff08 1 xff09 设置VMware xff0c 让虚拟机的桌面铺满 xff08 2 xff09 右键桌面 xff08 3 xff09
  • 转载:对offsetParent的理解

    来源 cnblogs 啊T 网上对offsetParent和parentNode差异的解释都是同一篇文章千篇一律 xff0c 讲的不是很清楚 offsetParent用的最普遍的就是来计算元素在页面中的位置 xff0c 前面的日志理讲了 通
  • vs 开发 qt 遇到 无法找到 Visual Studio 2010 的生成工具(平台工具集 =“v100”) 解决方案

    vs 开发 qt 遇到 无法找到 Visual Studio 2010 的生成工具 平台工具集 61 v100 解决方案 参考文章 xff1a xff08 1 xff09 vs 开发 qt 遇到 无法找到 Visual Studio 201
  • 取一个整数a从右端开始的4~7位。

    取一个整数a从右端开始的4 xff5e 7位 思路 xff1a 先除1000取整数部分 xff1b xff08 去掉个 十 百3位数 xff09 然后取余第7位后面的数 xff08 去掉百万位左边的数 xff09 程序 xff1a impo
  • C语言结构体实现简单通讯录管理系统

    效果如图 xff1a 代码及详情如下 xff1a include lt stdio h gt include lt string h gt include lt stdlib h gt 通讯录管理 问题描述 xff1a 利用线性表实现一个通

随机推荐