当前位置: 首页 > news >正文

LED闪烁 + PWM呼吸灯

LED灯闪烁实验

FreeRTOS操作系统

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"#define LED_Pin GPIO_NUM_2// 定义一个任务
void led_flashing_task()
{int gpio_pin = 0;while(1){vTaskDelay(pdMS_TO_TICKS(500));gpio_pin = gpio_pin ? 0 : 1;gpio_set_level(LED_Pin, gpio_pin);}
}
void app_main(void)
{// 初始化gpio管脚// 首先定义一个结构体// 然后往结构体里面添加成员// 然后这个结构体就成为了一个配置项// 将这个配置通过一个API设置到底层里面去gpio_config_t led_config = {.pin_bit_mask = (1 << LED_Pin),.mode = GPIO_MODE_OUTPUT,.pull_up_en = GPIO_PULLUP_DISABLE,.pull_down_en = GPIO_PULLDOWN_DISABLE,.intr_type = GPIO_INTR_DISABLE,};gpio_config(&led_config);xTaskCreatePinnedToCore(led_flashing_task, "led", 2048, NULL, 3, NULL, 1);}

esp32-wroom-32开发板自带的led灯是GPIO2号管脚。

PWM波形实验

deepseek给出的参考,可以实现呼吸灯效果

/*LED+PWM呼吸灯效果*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/ledc.h"#define LED_Pin GPIO_NUM_2    // 2号管脚
#define PWM_TIMER LEDC_TIMER_0  // 定时器0-
#define PWM_MODE LEDC_LOW_SPEED_MODE    // 低速模式
#define PWM_CHANNEL LEDC_CHANNEL_0    // 8个通道 选择通道0// 定义PWM呼吸灯任务
void led_breathing_task()
{// pwm配置结构体ledc_timer_config_t timer_config = {.speed_mode = PWM_MODE,.duty_resolution = LEDC_TIMER_13_BIT,    // 13位分辨率(0-8191).timer_num = PWM_TIMER,.freq_hz = 5000,    // pwm频率设置为5000hz.clk_cfg = LEDC_AUTO_CLK};ledc_timer_config(&timer_config);// 通道配置ledc_channel_config_t channel_config = {.channel = PWM_CHANNEL,.duty = 0,.gpio_num = LED_Pin,.hpoint = 0,.speed_mode = PWM_MODE,.timer_sel = PWM_TIMER};ledc_channel_config(&channel_config);// 设置渐变功能ledc_fade_func_install(0);    // 不使用中断int direction = 1;    // 设置亮灭标志位uint16_t duty = 0;const uint32_t max_duty = 8191;    // 13位最大占空比while(1){// 设置新的占空比并渐变ledc_set_fade_with_time(PWM_MODE,PWM_CHANNEL,duty, 200);    // 200ms内完成渐变ledc_fade_start(PWM_MODE,PWM_CHANNEL,LEDC_FADE_NO_WAIT);// 更新占空比值duty += direction * (max_duty / 20);// 改变方向if (duty >= max_duty){duty = max_duty;direction = -1;}else if (duty <= 0){duty = 0;direction = 1;}// 等待渐变完成vTaskDelay(pdMS_TO_TICKS(200));}
}void app_main(void)
{// 创建呼吸灯任务xTaskCreatePinnedToCore(led_breathing_task, "breathing_led", 2048, NULL, 3, NULL, 1);
}

根据官网和课程编写的如下,效果可以实现

#if 1
// 这段代码实现了基于事件驱动的呼吸灯效果,充分利用了FreeRTOS的事件组和LEDC的渐变功能,避免了在任务中轮询或延时,提高了效率。
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/ledc.h"#define LED_Pin GPIO_NUM_2// 定义一个事件组句柄
static EventGroupHandle_t ledc_event_handel;
// 定义两个事件标志位
#define FULL_EV_BIT0 BIT0
#define EMPTY_EV_BIT BIT1// 函数指针 回调函数,提示渐变已经完成   添加了一个IRAM_ATTR宏
bool IRAM_ATTR ledc_cb_t0(const ledc_cb_param_t *param, void *user_arg)
{BaseType_t taskWoken;// 渐变 0- 满 满-0if (param->duty){xEventGroupSetBitsFromISR(ledc_event_handel, FULL_EV_BIT0, &taskWoken); }else{xEventGroupSetBitsFromISR(ledc_event_handel,EMPTY_EV_BIT, &taskWoken);}return taskWoken;}// 定义PWM呼吸灯任务
void led_breathing_task()
{// 设置新的占空比并渐变EventBits_t ev;while(1){ev = xEventGroupWaitBits(ledc_event_handel, FULL_EV_BIT0 | EMPTY_EV_BIT, pdTRUE, pdFALSE, pdMS_TO_TICKS(5000));if (ev & FULL_EV_BIT0){ledc_set_fade_with_time(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 0, 2000);    // 2000ms内完成渐变// LEDC_FADE_NO_WAIT不用等渐变完成,这个函数立刻返回,不用阻塞ledc_fade_start(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0,LEDC_FADE_NO_WAIT);}if (ev & EMPTY_EV_BIT){ledc_set_fade_with_time(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 8191, 2000);    // 2000ms内完成渐变// LEDC_FADE_NO_WAIT不用等渐变完成,这个函数立刻返回,不用阻塞ledc_fade_start(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0,LEDC_FADE_NO_WAIT);}}
}void app_main(void)
{// GPIO结构体配置gpio_config_t led_config = {// 掩码.pin_bit_mask = (1 << LED_Pin),// GPIO的模式.mode = GPIO_MODE_OUTPUT,// 配置上拉使能.pull_up_en = GPIO_PULLUP_DISABLE,// 配置下拉使能.pull_down_en = GPIO_PULLDOWN_DISABLE,// 配置终端类型.intr_type = GPIO_INTR_DISABLE,};// 配置项传递给配置结构体,配置结构体通过地址映射设置到对应的寄存器gpio_config(&led_config);// pwm配置结构体ledc_timer_config_t timer_config = {.speed_mode = LEDC_LOW_SPEED_MODE,.duty_resolution = LEDC_TIMER_13_BIT,    // 占空比的分辨率 13位分辨率(0-8191).timer_num = LEDC_TIMER_0,  // 定时器0.freq_hz = 5000,    // pwm频率设置为5000hz.clk_cfg = LEDC_AUTO_CLK};ledc_timer_config(&timer_config);// 通道配置ledc_channel_config_t channel_config = {.channel = LEDC_CHANNEL_0,.duty = 0,    // 占空比.gpio_num = LED_Pin,.speed_mode = LEDC_LOW_SPEED_MODE,.timer_sel = LEDC_TIMER_0};ledc_channel_config(&channel_config);// 设置渐变功能ledc_fade_func_install(0);    // 不使用中断ledc_set_fade_with_time(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 8191, 2000);    // 2000ms内完成渐变// LEDC_FADE_NO_WAIT不用等渐变完成,这个函数立刻返回,不用阻塞ledc_fade_start(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0,LEDC_FADE_NO_WAIT);// 什么时候知道渐变完成呢? 设置一个渐变完成的回调函数ledc_cbs_t cbs = {.fade_cb = ledc_cb_t0};ledc_cb_register(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, &cbs, NULL);ledc_event_handel = xEventGroupCreate();xTaskCreatePinnedToCore(led_breathing_task, "led", 2048, NULL, 3, NULL, 1);}
#endif

上述代码需要熟悉FreeRTOS事件组中断回调函数 相关知识

http://www.lryc.cn/news/579721.html

相关文章:

  • 【React Native原生项目不能运行npx react-native run-android项目】
  • Redis 持久化详解、使用及注意事项
  • 《C++MLpack库 聚类算法》实战指南
  • day15——Java常用API(二):常见算法、正则表达式与异常处理详解
  • 玄机——某医院系统被脱库
  • 板凳-------Mysql cookbook学习 (十一--------3)
  • 项目中数据库表设计规范与实践(含案例)
  • OS15.【Linux】gdb调试器的简单使用
  • 力扣网编程第80题:删除有序数组中的重复项(简单)
  • springsecurity---使用流程、加密机制、自定义密码匹配器、token字符串生成
  • 【STM32实践篇】:I2C驱动编写
  • Vue如何处理数据、v-HTML的使用及总结
  • 8分钟讲完 Tomcat架构及工作原理
  • Node.js与Webpack
  • 前端面试专栏-算法篇:17. 排序算法
  • Spring SseEmitter 系统详细讲解
  • XILINX FPGA如何做时序分析和时序优化?
  • 手机内存融合是什么意思
  • Redis—哨兵模式
  • C++之路:类基础、构造析构、拷贝构造函数
  • 算法学习笔记:5.后缀数组——从原理到实战,涵盖 LeetCode 与考研 408 例题
  • MySQL 学习 之 你还在用 TIMESTAMP 吗?
  • Functionize 结合了 AI 与云平台的现代化自动化测试工具
  • MySQL 8.0 OCP 1Z0-908 题目解析(16)
  • curl for android
  • 高通QCS8550部署Yolov10模型与性能测试
  • ADC笔试面试题型和详细解析下
  • 蒙特卡洛方法:随机抽样的艺术与科学
  • c++ 的标准库 --- std::
  • {{ }}和v-on:click