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

网站建设套餐表台州做网站优化哪家好

网站建设套餐表,台州做网站优化哪家好,广西建设监理协会网站,著名营销成功案例目录 一、前言 二、GPIO 2.1 GPIO简介 2.2 GPIO函数解析 2.3 LED驱动 2.4 KEY驱动 三、EXIT 3.1 EXIT简介 3.2 EXIT函数解析 3.3 EXIT驱动 四、LEDC 4.1 PWM原理解析 4.2 ESP32的LED PWM控制器介绍 4.3 LEDC函数解析 4.3.1 SW_PWM 4.3.2 HW_PWM 4.4 LEDC驱动 …目录 一、前言 二、GPIO 2.1 GPIO简介 2.2 GPIO函数解析 2.3 LED驱动 2.4 KEY驱动 三、EXIT 3.1 EXIT简介 3.2 EXIT函数解析 3.3 EXIT驱动 四、LEDC 4.1 PWM原理解析 4.2 ESP32的LED PWM控制器介绍 4.3 LEDC函数解析 4.3.1 SW_PWM 4.3.2 HW_PWM 4.4 LEDC驱动 结语 一、前言 博主最近也是找到实习了实习项目用的是 ESP32-S3基于 esp-idf 开发因此想写博客记录一下学习笔记。         esp-idf 是基于 freeRTOS 的框架里面用到的组件以及我们的应用程序都是基于 freeRTOS 来开发的因此我们必须掌握 freeRTOS 的用法。如果我们不深究原理只关注于 freeRTOS 的接口使用我们很快就能掌握。另外因为 freeRTOS 开源免费的特性目前大部分芯片产商做的 SDK 都是基于 freeRTOS 系统开发的因此我们就更有理由要学习 RTOS 了。freeRTOS 可以去看我的专栏FreeRTOS专栏也可以去看韦东山老师的课程尤其是内部原理看完大有收获。 二、GPIO 2.1 GPIO简介 GPIO 是负责控制或采集外部器件信息的外设主要负责输入输出功能。ESP32-S3 芯片具有 45 个物理 GPIO 管脚涵盖 GPIO0 至 GPIO21 以及 GPIO26 至 GPIO48 的广泛范围。 2.2 GPIO函数解析 ESP-IDF 提供了丰富的 GPIO 操作函数在 v5.x.x\esp-idf\components\esp_driver_gpio 路径下找到相关的 gpio.c 和 gpio.h 文件。在 gpio.h 头文件中你可以找到 ESP32-S3 的所有 GPIO 函数定义。 ● GPIO配置函数         该函数用于配置 GPIO 的模式、上下拉、中断等功能函数原型如下 esp_err_t gpio_config(const gpio_config_t *pGPIOConfig); 该函数的形参描述如下表所示 参数描述pGPIOConfigGPIO结构体 返回值ESP_OK 表示配置成功ESP_FAIL 表示配置失败。         pGPIOConfig 为 GPIO 配置结构体指针下面来看一下 gpio_config_t 结构体中的变量。 /* GPIO配置参数 */ typedef struct {uint64_t pin_bit_mask; /* 配置引脚位 */gpio_mode_t mode; /* 设置引脚模式 */gpio_pullup_t pull_up_en; /* 设置上拉 */gpio_pulldown_t pull_down_en; /* 设置下拉 */gpio_int_type_t intr_type; /* 中断配置 */ } gpio_config_t; 各个参数有哪些见下表 类型类型说明可填参数参数说明.pin_bit_mask引脚位 1x其中 x 为 ESP32S3 中可用 GPIO 要用哪个引脚比如 IO1 引脚则写为1ull GPIO NUM 1.mode引脚模式GPIO_MODE_DISABLE GPIO_MODE_INPUT GPIO_MODE_OUTPUT GPIO_MODE_OUTPUT_OD GPIO_MODE_INPUT_OUTPUT_OD GPIO_MODE_INPUT_OUTPUT 失能输入输出模式 仅输入模式 仅输出模式 输出开漏模式 输入输出开漏模式 输入输出模式 .pull_up_en配置上拉 GPIO_PULLUP_DISABLE GPIO_PULLUP_ENABLE 失能上拉 使能上拉 .pull_down_en配置下拉GPIO_PULLDOWN_DISABLE GPIO_PULLDOWN_ENABLE 失能下拉 使能下拉 .intr_type中断配置GPIO_INTR_DISABLE GPIO_INTR_POSEDGE GPIO_INTR_NEGEDGE GPIO_INTR_ANYEDGE GPIO_INTR_LOW_LEVEL GPIO_INTR_HIGH_LEVEL 失能中断 上升沿触发 下降沿触发 上升沿和下降沿触发 输入低电平触发 输入高电平触发 ● 设置管脚输出电平         该函数用于配置某个管脚输出电平该函数原型如下所示 esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level); 该函数的形参描述如下 参数描述gpio_numGPIO 引脚号。在 gpio_types.h 文件中枚举 gpio_num_t 有定义levelGPIO 引脚输出电平。0低电平1高电平 返回值ESP_OK 表示设置成功ESP_FAIL 表示设置失败。 ● 获取管脚电平         该函数用于获取某个管脚的电平该函数原型如下所示 int gpio_get_level(gpio_num_t gpio_num); 该函数的形参描述如下 参数描述gpio_numGPIO 引脚号。在 gpio_types.h 文件中枚举 gpio_num_t 有定义 返回值0 GPIO 输入电平为低电平1 GPIO 输入电平为高电平。 2.3 LED驱动 万物先从点灯开始下面实现led.c及led.h两个文件。led.h负责声明LED相关的函数和变量led.c实现LED的驱动代码。 ● led.h /* 引脚定义 */ #define LED_GPIO_PIN GPIO_NUM_1 /* LED 连接的 GPIO 端口 *//* 引脚的输出的电平状态 */ enum GPIO_OUTPUT_STATE{PIN_RESET,PIN_SET };#define LED(x) do { x ? \gpio_set_level(LED_GPIO_PIN, PIN_SET) : \gpio_set_level(LED_GPIO_PIN, PIN_RESET); \ } while(0)#define LED_TOGGLE() do { gpio_set_level(LED_GPIO_PIN, !gpio_get_level(LED_GPIO_PIN)); } while(0) /* LED 翻转 *//* 函数声明*/ void led_init(void); /* 初始化 LED */ LED(x) 宏用于控制 IO1 管脚的电平状态使用三元运算符传入 1 设置引脚为高电平反之输出低电平。LED_TOGGLE() 宏实现管脚电平翻转。 ● led.c // esp封装的库 #include driver/gpio.h #include led.h/*** brief 初始化 LED* param 无* retval 无*/ void led_init(void) {gpio_config_t gpio_init_struct {.pin_bit_mask 1ull LED_GPIO_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(gpio_init_struct); /* 配置 GPIO */LED(1); } 2.4 KEY驱动 配置 GPIO 为输入模式通常按键直接连接到芯片的引脚没有加上拉电阻因此需要将 GPIO 配置成上拉输入模式。本次按键驱动使用的是最简单的延时消抖下面实现 key.c 及 key.h 两个文件。 ● key.h /* 引脚定义 */ #define BOOT_GPIO_PIN GPIO_NUM_0/*IO 操作*/ #define BOOT gpio_get_level(BOOT_GPIO_PIN)/* 按键按下定义 */ #define BOOT_PRES 1 /* BOOT 按键按下 *//* 函数声明 */ void key_init(void); /* 初始化按键 */ uint8_t key_scan(uint8_t mode); /* 按键扫描函数 */ 通过 BOOT 宏来读取连接按键引脚的电平。 ● key.c #include driver/gpio.h #include key.h/*** brief 初始化按键引脚* param 无* retval 无*/ void key_init(void) {gpio_config_t gpio_init_struct;gpio_init_struct.intr_type GPIO_INTR_DISABLE; /* 失能引脚中断 */gpio_init_struct.mode GPIO_MODE_INPUT; /* 输入模式 */gpio_init_struct.pull_up_en GPIO_PULLUP_ENABLE; /* 使能上拉 */gpio_init_struct.pull_down_en GPIO_PULLDOWN_DISABLE; /* 失能下拉 */gpio_init_struct.pin_bit_mask 1ull BOOT_GPIO_PIN; /* BOOT 按键引脚 */gpio_config(gpio_init_struct); /* 配置使能 */ }/*** brief 按键扫描函数* param mode:0 / 1, 具体含义如下:* 0, 不支持连续按(当按键按下不放时, 只有第一次调用会返回键值,* 必须松开以后, 再次按下才会返回其他键值)* 1, 支持连续按(当按键按下不放时, 每次调用该函数都会返回键值)* retval 键值, 定义如下:* BOOT_PRES, 1, BOOT 按下*/ uint8_t key_scan(uint8_t mode) {uint8_t keyval 0;static uint8_t key_boot 1; /* 按键松开标志 */if(mode){key_boot 1;}if (key_boot (BOOT 0)) /* 按键松开标志为 1且有任意一个按键按下了 */{vTaskDelay(10); /* 去抖动 */key_boot 0;if (BOOT 0){keyval BOOT_PRES;}}else if (BOOT 1){key_boot 1;}return keyval; /* 返回键值 */ } 此函数只有一个形参 mode用于设置按键是否支持连续按下模式。当 mode 为 0 时表示按键不支持连续按下反之则支持连续按下。 三、EXIT 3.1 EXIT简介 外部中断属于硬件中断由微控制器外部事件触发。微控制器的特定引脚被设计为对特定事件如按钮按压、传感器信号变化等作出响应这些引脚通常称为“外部中断引脚”。一旦外部中断事件发生当前程序执行将立即暂停并跳转到相应的中断服务程序ISR进行处理。处理完毕后程序会恢复执行从被中断的地方继续。下图是 CPU 中断处理过程。 ESP32-S3 的外部中断具备两种触发类型         1电平触发高、低电平触发要求保持中断的电平状态直到 CPU 响应。         2边沿触发上升沿和下降沿触发这类型的中断一旦触发CPU 即可响应。         ESP32-S3 的外部中断功能能够以非常精确的方式捕捉外部事件的触发。开发者可以通过配置中断触发方式如上升沿、下降沿、任意电平、低电平保持、高电平保持等来适应不同的外部事件并在事件发生时立即中断当前程序的执行转而执行中断服务函数。ESP32-S3 支持六级中断同时支持中断嵌套也就是低优先级中断可以被高优先级中断打断。数字越大表明该中断的优先级越高。其中NMI 中断拥有最高优先级此类中断已经触发CPU 必须处理。 3.2 EXIT函数解析 ● 注册中断函数         该函数用于注册中断服务原型如下 esp_err_t gpio_install_isr_service(int intr_alloc_flags); 该函数的形参描述如下表所示 参数中断标志位描述intr_alloc_flags   ESP_INTR_FLAG_LEVEL1 使用Level 1中断级别。在中断服务程序执行期间禁用同级别中断。 ESP_INTR_FLAG_LEVEL2 使用Level 2中断级别。在中断服务程序执行期间禁用同级别和Level 1的中断。 ESP_INTR_FLAG_LEVEL3 同理。 ESP_INTR_FLAG_LEVEL4 ESP_INTR_FLAG_LEVEL5 ESP_INTR_FLAG_LEVEL6 ESP_INTR_FLAG_NMI Level 7中断级别最高优先级 ESP_INTR_FLAG_SHARED 中断可以在ISRs之间共享 ESP_INTR_FLAG_EDGE 使用边沿触发方式。使能GPIO边沿触发中断。 ESP_INTR_FLAG_IRAM 如果缓存被禁用ISR可以被调用 ESP_INTR_FLAG_INTRDISABLED 返回时禁用此中断 返回值ESP_OK成功                       ESP_ERR_NO_MEM没有内存来安装此服务                       ESP_ERR_INVALID_STATEISR服务已经安装                       ESP_ERR_NOT_FOUND没有找到具有指定标志的空闲中断                       ESP_ERR_INVALID_ARGGPIO错误。 ● 分配中断函数         该函数设置某个管脚的中断服务函数该函数原型如下所示 esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void *args); 该函数的形参描述如下表所示 参数描述 gpio_num GPIO引脚号指定要分配中断处理程序的GPIO引脚 isr_handler 指向中断处理函数的函数指针。中断处理函数是一个用户定义的回调函数将在中断发生时执行 args 传递给中断处理程序的参数。这是一个指向用户特定数据的指针可以在中断处理程序中使用 返回值ESP_OK成功                       ESP_ERR_INVALID_STATE状态错误ISR服务没有初始化                       ESP_ERR_INVALID_ARG参数错误。 下面是中断处理函数的模板中断处理函数需要声明为 IRAM_ATTR以确保其运行在内存中的可执行区域。 void IRAM_ATTR gpio_isr_handler(void *arg) {/* 处理中断响应 */ } ● 开启外部中断函数         该函数用来配置某个管脚开启外部中断该函数原型如下所示 esp_err_t gpio_intr_enable(gpio_num_t gpio_num); 参数就是要使能哪个GPIO引脚传入引脚号。 返回值ESP_OK成功                       ESP_ERR_INVALID_ARG参数错误。 注意在使用 gpio_intr_enable() 函数之前开发者需要先通过 gpio_install_isr_service() 函数和 gpio_isr_handler_add() 函数来安装和注册中断处理程序。 3.3 EXIT驱动 ● exit.h /*引脚定义*/ #define BOOT_INT_GPIO_PIN GPIO_NUM_0/*IO 操作*/ #define BOOT gpio_get_level(BOOT_INT_GPIO_PIN)/* 函数声明 */ void exit_init(void); /* 外部中断初始化程序 */ ● exit.c /*** brief 外部中断服务函数* param arg中断引脚号* note IRAM_ATTR: 这里的IRAM_ATTR属性用于将中断处理函数存储在内部RAM中目的在于减少延迟* retval 无*/ static void IRAM_ATTR exit_gpio_isr_handler(void *arg) {uint32_t gpio_num (uint32_t) arg;if (gpio_num BOOT_INT_GPIO_PIN){/* 消抖 */esp_rom_delay_us(20000);//注意//这里的延时函数通过空循环消耗CPU时间不会主动释放CPU控制权//但是在ISR中不允许使用可能阻塞的函数如vTaskDelay会触发上下文切换//总的来说还是不希望在中断里进行耗时的操纵这里的20ms勉强能接受if (BOOT 0){LED0_TOGGLE();}} }/*** brief 外部中断初始化程序* param 无* retval 无*/ void exit_init(void) {gpio_config_t gpio_init_struct;/* 配置BOOT引脚和外部中断 */gpio_init_struct.mode GPIO_MODE_INPUT; /* 选择为输入模式 */gpio_init_struct.pull_up_en GPIO_PULLUP_ENABLE; /* 上拉使能 */gpio_init_struct.pull_down_en GPIO_PULLDOWN_DISABLE; /* 下拉失能 */gpio_init_struct.intr_type GPIO_INTR_NEGEDGE; /* 下降沿触发 */gpio_init_struct.pin_bit_mask 1ull BOOT_INT_GPIO_PIN; /* 设置的引脚的位掩码 */ESP_ERROR_CHECK(gpio_config(gpio_init_struct)); /* 配置使能 *//* 注册中断服务 */ESP_ERROR_CHECK(gpio_install_isr_service(0));/* 设置BOOT的中断回调函数 */ESP_ERROR_CHECK(gpio_isr_handler_add(BOOT_INT_GPIO_PIN, exit_gpio_isr_handler, (void*) BOOT_INT_GPIO_PIN));/* 使能GPIO模块中断信号 */ESP_ERROR_CHECK(gpio_intr_enable(BOOT_INT_GPIO_PIN)); } 开启管脚的外部中断操作相对简便。首先需要将管脚配置为下降沿触发GPIO_INTR_NEGEDGE和输入模式GPIO_MODE_INPUT。完成配置后需要调用 gpio_install_isr_service 函数来注册中断服务并调用 gpio_isr_handler_add 函数来注册外部中断的回调函数。最后调用 gpio_intr_enable 函数启用外部中断功能。其中exit_gpio_isr_handler 回调函数负责实现 LED 灯状态的切换。 四、LEDC 4.1 PWM原理解析 PWMPulse Width Modulation简称脉宽调制是一种将模拟信号变为脉冲信号的技术。PWM可以控制LED亮度、直流电机的转速等。         PWM的主要参数如下         ① 频率1s内有多少个PWM周期一个高电平加一个低电平为一个周期单位Hz。         ② 周期频率倒数T1/f。         ③ 占空比在一个周期内高电平的时间与整个周期时间的比例范围0%~100%。 使用PWM控制LED时一个PWM周期持续时间比较长人眼就可以看出LED在闪烁。只要缩小周期直到一个临界值使得人眼无法分辨LED在闪烁改变占空比就改变了LED的亮度。这就是PWM的原理。 4.2 ESP32的LED PWM控制器介绍 ESP32-S3的LED PWM控制器简写为LEDC用于生成脉冲宽度调制信号。         LEDC具有八个独立的PWM生成器八个通道。每个PWM生成器会从四个通用定时器中选择一个以该定时器的计数值作为基准生成PWM信号。LEDC定时器如下图所示 想要实现PWM输出需要先指定PWM通道的参数频率、分辨率、占空比然后将通道映射到指定的引脚该引脚输出对应通道的PWM信号如下图所示 LEDC可以在没有CPU干预的情况下自动改变占空比硬件PWM。 4.3 LEDC函数解析 4.3.1 SW_PWM ESP-IDF提供了一套API来配置PWM。要使用此功能需要包含以下头文件 #include driver/ledc.h ● 配置LEDC使用的定时器的函数         注意在首次配置LEDC时建议先配置定时器再配置通道。这样可以确保IO引脚上的PWM信号自输出开始那一刻起其频率就是正确的。 设置定时器函数原型如下 esp_err_t ledc_timer_config(const ledc_timer_config_t *timer_conf); 该函数的形参描述如下表所示 形参描述timer_conf指向配置LEDC定时器的结构体指针 返回值ESP_OK成功                       ESP_ERR_INVALID_ARG参数错误                       ESP_FAIL无法根据给定的频率和当前的 PWM 分辨率找到一个合适的分频系数                       ESP_ERR_INVALID_STATE无法取消定时器配置因为定时器未配置或未处于暂停状态。         该函数使用 ledc_timer_config_t 类型的结构体变量传入该结构体的定义如下所示 结构体成员变量可选参数ledc_timer_config_t .speed_mode 速度模式 LEDC_HIGH_SPEED_MODE仅存在于ESP32上 高速模式 LEDC_LOW_SPEED_MODE 低速模式 LEDC_SPEED_MODE_MAX 模式上限用于检查模式有效性不可作为实际的模式配置 .duty_resolution PWM占空比分辨率。由 ledc_timer_bit_t 枚举类型定义ESP32-S3支持的范围是1~14位的分辨率。 LEDC_TIMER_X_BITX1~14 .timer_num PWM通道的定时器源由 ledc_timer_t 枚举类型定义。 LEDC_TIMER_0 LEDC_TIMER_1 LEDC_TIMER_2 LEDC_TIMER_3 LEDC_TIMER_MAX 同样用于检查模式有效性不可作为实际的模式配置 .freq_hz PWM脉冲的频率表示LEDC模块的定时器时钟频率单位为Hz uint32_t大小的值 .clk_cfg 时钟源 LEDC_AUTO_CLK 在初始化计时器时LEDC源时钟会根据给定的分辨率和占空比被自动选定。 LEDC_USE_APB_CLK 选择APB作为时钟源。 LEDC_USE_RC_FAST_CLK 选择内部快速RC时钟作为时钟源 LEDC_USE_XTAL_CLK 选择外部晶体时钟作为时钟源 LEDC_USE_RTC8M_CLK LEDC_USE_RC_FAST_CLK的别名 .deconfigure 执行硬件定时器的反初始化停止定时器计数、释放占用的硬件资源、复位内部状态机、使定时器回归未配置状态。需要完全改变定时器参数时使用 bool值 deconfigure 成员变量的使用流程如下 // 1. 暂停定时器必须步骤 ledc_timer_pause(LEDC_LOW_SPEED_MODE, LEDC_TIMER_0);// 2. 准备反配置结构体 ledc_timer_config_t timer_cfg {.speed_mode LEDC_LOW_SPEED_MODE, // 必须匹配原配置.timer_num LEDC_TIMER_0, // 指定要反配置的定时器.deconfigure true // 核心开关// 其他参数自动忽略 };// 3. 执行反配置 ledc_timer_config(timer_cfg); 注意ESP32-S3 不支持定时器专属时钟所有定时器必须共享同一时钟源。禁止混合配置如 TIMER0 用 RC_FAST TIMER1 用 XTAL ● 通道配置函数         函数原型如下 esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf); 形参就是指向LEDC通道的结构体指针来看一下返回值和结构体的具体定义。         返回值ESP_OK成功                       ESP_ERR_INVALID_ARG参数错误。          结构体成员变量可选参数ledc_channel_config_t .gpio_num 配置输出引脚 if you want to use gpio16, gpio_num 16 .speed_mode 速度模式 LEDC_HIGH_SPEED_MODE仅存在于ESP32上 高速模式 LEDC_LOW_SPEED_MODE 低速模式 LEDC_SPEED_MODE_MAX 模式上限用于检查模式有效性不可作为实际的模式配置 .channel LEDC的输出通道PWM输出通道 LEDC_CHANNEL_XX0~7 LEDC_CHANNEL_MAX 用于检查模式有效性不可作为实际的模式配置 .intr_type 中断配置 LEDC_INTR_DISABLE 失能 LEDC_INTR_FADE_END 使能渐变结束中断 LEDC_INTR_MAX 用于检查模式有效性不可作为实际的模式配置 .timer_sel 选择通道的定时器源。由 ledc_timer_t 枚举类型定义和之前配置定时器一样 LEDC_TIMER_0 LEDC_TIMER_1 LEDC_TIMER_2 LEDC_TIMER_3 LEDC_TIMER_MAX 同样用于检查模式有效性不可作为实际的模式配置 .duty LEDC通道的占空比设置 范围为[0, (2**duty_resolution)]duty_resolution为定时器配置时的PWM占空比分辨率 .hpoint led通道hpoint值。一个周期中上升沿开始的时间点一般不太关系给0即可。 int类型的大小 .output_invert 启用或禁用gpio输出反相 1启用0禁用 ● 设置PWM占空比         调用函数 ledc_set_duty() 可以设置新的占空比之后调用函数 ledc_update_duty() 使新配置生效。要查看当前设置的占空比可以使用 ledc_get_duty() 函数。设置PWM占空比的函数原型如下 esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty); 该函数的形参描述如下表所示 形参描述speed_mode速度模式选择 LEDC_HIGH_SPEED_MODE仅存在于ESP32上 高速模式 LEDC_LOW_SPEED_MODE 低速模式 LEDC_SPEED_MODE_MAX 模式上限用于检查模式有效性不可作为实际的模式配置channelLEDC通道 0~LEDC_CHANNEL_MAX-1从 ledc_channel_t 中选择duty占空比范围为[0, (2**duty_resolution)]duty_resolution为定时器配置时的PWM占空比分辨率 返回值ESP_OK成功                       ESP_ERR_INVALID_ARG参数错误。 ● 更新PWM占空比         上一步调用 ledc_set_duty() 后调用 ledc_update_duty() 使得新配置生效函数原型如下 esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel); 该函数的形参描述见上一个函数返回值也一样。 到这里就属于ESP32-S3的软件PWM部分配置好定时器、LEDC通道后就可以搭配使用上面两个改变PWM占空比的函数在指定引脚输出想要的PWM脉冲。之所以叫做软件PWM是因为如果想要实现呼吸灯的效果需要我们不断判断当前的占空比为多少然后手动改变占空比的递增或递减这些操作都需要消耗CPU资源。下面来介绍硬件PWM的功能和用法它可在无需CPU干预的情况下自动改变占空比。 4.3.2 HW_PWM LEDC控制器硬件可逐渐改变占空比的数值要使用此功能可用 ledc_fade_func_install() 使能渐变然后使用下列渐变函数之一进行配置 ledc_set_fade_with_time() ledc_set_fade_with_step() ledc_set_fade() 最后调用 ledc_fade_start() 开启渐变。还记得配置LEDC通道的时候有个参数是使能中断吗可选的只有两项使能渐变结束中断和失能。我查了一下发现这个即使不使能也不影响硬件PWM至于软件PWM中使能这个中断有没有用暂时没找到很明确的说明如果有大佬懂得可以在评论区讨论一下。硬件PWM可以注册一个回调函数在渐变完成之后就会调用回调函数这个回调函数由中断调用但这个中断是我们调用 ledc_fade_func_install() 函数时内部会初始化LEDC的渐变中断和通道配置中的 intr_type 无关。 ● 开启硬件PWM使能渐变         安装LEDC渐变功能。该功能将占用LEDC模块的中断资源。 esp_err_t ledc_fade_func_install(int intr_alloc_flags); 该函数的形参见 esp_intr_alloc.h 里带 ESP_INTR_FLAG_ 前缀的宏定义。但是很多例程里调用这个函数直接传入0即可表示默认的中断优先级。 返回值ESP_OK成功                       ESP_ERR_INVALID_ARG参数错误                       ESP_ERR_NOT_FOUND找不到可用的中断源                       ESP_ERR_INVALID_STATE渐变服务已经安装。 ● 设置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_modeLEDC_HIGH_SPEED_MODE仅存在于ESP32上 高速模式 LEDC_LOW_SPEED_MODE 低速模式 LEDC_SPEED_MODE_MAX 模式上限用于检查模式有效性不可作为实际的模式配置channelLEDC通道 0~LEDC_CHANNEL_MAX-1从 ledc_channel_t 中选择target_duty目标占空比 范围为[0, (2**duty_resolution)]duty_resolution为定时器配置时的PWM占空比分辨率max_fade_time_ms最大渐变时间毫秒 返回值ESP_OK表示成功其他表示配置失败。 ● 开启渐变         函数原型如下 esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode); 前两个参数说烂了来看看第三个参数 第三个参数描述fade_mode渐变模式由 ledc_fade_mode_t 枚举类型定义有以下模式可选 LEDC_FADE_NO_WAIT LEDC_FADE_WAIT_DONE LEDC_FADE_MAX 用于检查模式有效性不可作为实际的模式配置 这个参数就是设置是否阻塞不论选择哪个模式都可以绑定渐变完成回调函数不过阻塞模式下使用回调函数意义不太大因为当阻塞模式下的函数返回时回调函数一定已经执行完毕了回调函数是在渐变结束时、函数返回前由内部驱动调用的。 ● 设置渐变完成回调函数         在非阻塞模式下函数调用之后立即返回想要知道什么时候渐变完成需要绑定一个回调函数当回调函数被调用时在回调函数里设置某些标志位不能调用任何可能导致阻塞的函数。函数原型如下 esp_err_t ledc_cb_register(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_cbs_t *cbs, void *user_arg); 主要看后两个参数 后两个形参描述*cbs 指向ledc_cbs_t结构体的指针。ledc_cbs_t里面只有一个成员变量fade_cb。它是指向回调函数的指针回调函数的类型为ledc_cb_t定义如下 typedef bool (*ledc_cb_t)(const ledc_cb_param_t *param, void *user_arg); param系统传入的事件参数通道号、状态等 user_arg用户自定义的透传参数初始化时传入 *user_arg传给回调函数的参数 4.4 LEDC驱动 使用硬件PWM、非阻塞模式在回调函数里使用事件组实现呼吸灯的效果 #include freertos/FreeRTOS.h // FreeRTOS基础功能 #include freertos/task.h // 任务相关APIxTaskCreatePinnedToCore #include freertos/event_groups.h // 事件组EventGroupHandle_t, xEventGroup* #include driver/gpio.h // GPIO定义LED_GPIO #include driver/ledc.h // LEDC PWM驱动所有ledc_*函数和结构体 #include esp_log.h // 日志系统ESP_ERROR_CHECK//定义LED的GPIO口 #define LED_GPIO GPIO_NUM_1#define TAG LEDC#define LEDC_TIMER LEDC_TIMER_0 //定时器0 #define LEDC_MODE LEDC_LOW_SPEED_MODE //低速模式 #define LEDC_OUTPUT_IO (LED_GPIO) //选择GPIO端口 #define LEDC_CHANNEL LEDC_CHANNEL_0 //PWM通道 #define LEDC_DUTY_RES LEDC_TIMER_13_BIT //分辨率 #define LEDC_DUTY (4095) //最大占空比值这里是2^13-1 #define LEDC_FREQUENCY (5000) //PWM周期//用于通知渐变完成 static EventGroupHandle_t s_ledc_ev NULL;//关灯完成事件标志 #define LEDC_OFF_EV (10)//开灯完成事件标志 #define LEDC_ON_EV (11)//渐变完成回调函数 bool IRAM_ATTR ledc_finish_cb(const ledc_cb_param_t *param, void *user_arg) {BaseType_t xHigherPriorityTaskWoken;if(param-duty){xEventGroupSetBitsFromISR(s_ledc_ev,LEDC_ON_EV,xHigherPriorityTaskWoken);}else{xEventGroupSetBitsFromISR(s_ledc_ev,LEDC_OFF_EV,xHigherPriorityTaskWoken);}return xHigherPriorityTaskWoken; }//ledc 渐变任务 void ledc_breath_task(void* param) {EventBits_t ev;while(1){ev xEventGroupWaitBits(s_ledc_ev,LEDC_ON_EV|LEDC_OFF_EV,pdTRUE,pdFALSE,pdMS_TO_TICKS(5000));if(ev){//设置LEDC开灯渐变if(ev LEDC_OFF_EV){ledc_set_fade_with_time(LEDC_MODE,LEDC_CHANNEL,LEDC_DUTY,2000);ledc_fade_start(LEDC_MODE,LEDC_CHANNEL,LEDC_FADE_NO_WAIT);}else if(ev LEDC_ON_EV) //设置LEDC关灯渐变{ledc_set_fade_with_time(LEDC_MODE,LEDC_CHANNEL,0,2000);ledc_fade_start(LEDC_MODE,LEDC_CHANNEL,LEDC_FADE_NO_WAIT);}}} }//LED呼吸灯初始化 void led_breath_init(void) {//初始化一个定时器ledc_timer_config_t ledc_timer {.speed_mode LEDC_MODE, //低速模式.timer_num LEDC_TIMER, //定时器ID.duty_resolution LEDC_DUTY_RES, //占空比分辨率这里是13位2^13-1.freq_hz LEDC_FREQUENCY, // PWM频率,这里是5KHZ.clk_cfg LEDC_AUTO_CLK // 时钟};ESP_ERROR_CHECK(ledc_timer_config(ledc_timer));//ledc通道初始化ledc_channel_config_t ledc_channel {.speed_mode LEDC_MODE, //低速模式.channel LEDC_CHANNEL, //PWM 通道0-7.timer_sel LEDC_TIMER, //关联定时器也就是上面初始化好的那个定时器.intr_type LEDC_INTR_DISABLE,//不使能中断.gpio_num LEDC_OUTPUT_IO, //设置输出PWM方波的GPIO管脚.duty 0, // 设置默认占空比为0.hpoint 0};ESP_ERROR_CHECK(ledc_channel_config(ledc_channel));//开启硬件PWMledc_fade_func_install(0);//创建一个事件组用于通知任务渐变完成s_ledc_ev xEventGroupCreate();//配置LEDC渐变ledc_set_fade_with_time(LEDC_MODE,LEDC_CHANNEL,LEDC_DUTY,2000);//启动渐变ledc_fade_start(LEDC_MODE,LEDC_CHANNEL,LEDC_FADE_NO_WAIT);//设置渐变完成回调函数ledc_cbs_t cbs {.fade_cbledc_finish_cb,};ledc_cb_register(LEDC_MODE,LEDC_CHANNEL,cbs,NULL);xTaskCreatePinnedToCore(ledc_breath_task,ledc,2048,NULL,3,NULL,1); }// 主函数 void app_main(void) {led_breath_init(); //呼吸灯 } 结语 该系列会持续更新后续可能会更新实习用到的技术栈如JSON、OTA、http和UDP等。
http://www.zqtcl.cn/news/882714/

相关文章:

  • 国外对企业网站开发的研究山西住房与城乡建设厅定额网站
  • 国家工信部网站备案postfix wordpress
  • 兴宁电子商务网站建设网站模板在线制作
  • 汕头整站优化营销推广网
  • 云服务器搭建网站教程加盟教育培训机构
  • 建筑网站设置工资单人换了怎么换太原做网站找谁
  • 网站做推广需要什么条件重庆网站推广哪家服务好
  • 怎样做理财网站wordpress做产品页教程视频
  • 官网模板建站塔山双喜北京网站建设兴田德润官网多少
  • 网站优化推广外包深圳专业网站建设定制
  • 网站开发aichengkeji元凤建盏简介
  • 移动端网站怎么制作asp做的网站如何发布
  • 做的网站用户密码在哪里找凡科申请的网站和qq空间一样吗
  • 如何自己做网站发布到服务器上面wordpress没有幻灯片
  • 闽侯县建设局网站企业建设网站例文
  • 家居类企业响应式网站搭建电商系统
  • 临沂哪里做网站比较好中国建设银行企业信息门户网站
  • 低价建网站提高网站订单转化率
  • 家居网站应该怎么做网站seo推广软件
  • 旅游网站建设报告关键词优化排名价格
  • 上海网站开发caiyiduo微信建微网站
  • 做网站和做网店哪个好用cms做单页网站怎么做
  • 阿里云有主体新增网站可以免费制作网页的网站
  • 网站备案幕布拍照是什么莱芜网络推广公司服务
  • 招个网站建设维护国家高新技术企业官网
  • 建设医疗网站做企业官网哪家公司好
  • 网站建设常见问题及解决办法站长网站大全
  • 二手网站建设模块500做网站
  • 建设展示型网站公司哪家好广告制作费和广告服务费区别
  • 网站排版设计欣赏网站建设制作设计seo优化南宁