本次实验是使用GOOUUU-ESP32-C3开发板,芯片型号为ESP32-C3-MINI-1,使用下载方式是USB串口,芯片资料:ESP32-C3-MINI-1/ESP32-C3-MINI-1U数据手册,通过VSCode中的espressif-idf插件开发。
1、通过数据手册可以得知芯片的所引脚,且启动管脚为IO2、IO8和IO9。
2、查看开发板原理图可以得知开发板有一个三色LED的引脚为IO3、IO4、IO5,分别控制着红色,绿色和蓝色
1、打开VSCode,快捷键Ctrl+Shift+P打开命令面板,输入show exmaples projects打开示例程序,选择sample_project样本示例,里面是个空项目,并且选择不要出现中文或空格的路径保存,否则程序无法编译,会报错;
步骤1:打开示例项目
步骤2:选择样本示例,保存项目路径
2、通过硬件得知LED为IO3、IO4、IO5控制,本实验只控制蓝色LED,引脚为IO5,打开main.c文件,所有程序就在main.c文件编写了,首先就得引用所需的头文件,定义LED引脚,配置LED,控制LED亮灭;
步骤1:打开main.c文件
步骤2:引用头文件,定义LED引脚
#include "driver/gpio.h" //GPIO固件库
#define blueLED GPIO_NUM_2 //定义蓝色LED引脚
步骤3:配置LED推挽输出
gpio_reset_pin(blueLED); //复位LED
gpio_set_direction(blueLED, GPIO_MODE_OUTPUT); //配置LED输入输出
步骤4::通过硬件电路,得知LED一端连接VCC,另一端连接LED引脚,所以通过控制LED引脚高电平让LED灭,低电平让LED,但程序执行效率很快,肉眼无法直观看到LED亮灭,所以需要延时;
a、引用头文件
#include "freertos/FreeRTOS.h" //FreeRTOS固件库
#include "freertos/task.h" //延时函数需要用到该头文件
b、在app_main函数中循环
while(true)
{
gpio_set_level(blueLED, 0); //LED亮
vTaskDelay(1000 / portTICK_PERIOD_MS); //延时1000ms,portTICK_PERIOD_MS为毫米周期
gpio_set_level(blueLED, 1); //LED灭
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
main.c程序
#include <stdio.h>
#include "driver/gpio.h" //GPIO固件库
#include "freertos/FreeRTOS.h" //FreeROTS固件库
#include "freertos/task.h" //延时函数需要用到该头文件
#define blueLED GPIO_NUM_5 //定义蓝色LED引脚
void app_main(void)
{
gpio_reset_pin(blueLED); //复位LED
gpio_set_direction(blueLED, GPIO_MODE_OUTPUT); //配置LED输入输出
while (true)
{
gpio_set_level(blueLED, 0); //LED亮
vTaskDelay(1000 / portTICK_PERIOD_MS); //延时1000ms,portTICK_PERIOD_MS为毫米周期
gpio_set_level(blueLED, 1); //LED灭
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
3、连接开发板,在VSCode底部有espressif工具,选择对应的端口号、芯片型号和烧录方式,进行程序编译,最后点击下载,查看实验效果;
实验效果:
1、本次实验是利用LED PWM控制器实现的呼吸灯,具体可以查看ESP32-C3技术参考手册,工程创建不用多说了,就是上面的步骤,后面直接编写程序;
步骤1:查看手册可以知道,LED PWM控制可以由4个定时器,由6个通道控制。本地实验选用定时器0,PWM0通道控制,首先配置LED PWM;
a、添加头文件
#include "driver/gpio.h" //GPIO固件库
#include "freertos/FreeRTOS.h" //FreeRTOS固件库
#include "freertos/task.h" //延时函数需要用到该头文件
#include "driver/ledc.h" //LED PWM固件库
b、创建LED PWM配置函数,将LED PWM配置成5KPWM频率,13位精度,占空比为0
#define blueLED GPIO_NUM_5 //定义蓝色LED引脚
ledc_channel_config_t ledc_channel; //定义LED PWM通道
void breathingLed_init(void); //配置LED PWM控制器
void breathingLed_init(void)
{
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_13_BIT, //PWM分辨率
.freq_hz = 5000, //频率
.speed_mode = 0, //速度
.timer_num = LEDC_TIMER_0, //选择定时器
};
ledc_timer_config(&ledc_timer); //配置LED为定时器PWM模式
ledc_channel.channel = LEDC_CHANNEL_0; //LED PWM通道
ledc_channel.duty = 0; //占空比
ledc_channel.gpio_num = blueLED; //IO口映射
ledc_channel.speed_mode = 0; //速度
ledc_channel.timer_sel = LEDC_TIMER_0; //选择定时器
ledc_channel_config(&ledc_channel); //配置LED PWM通道
ledc_fade_func_install(0); //开启LEDC渐变功能,参数为是否允许中断
}
步骤2:实现呼吸效果
a、因为配置LED PWM控制器的时候,设置13位分辨率,占空比为0%,所以要让占空比达到100%,占空比值就需要2^13-1 = 8191,通过ledc_set_fade_with_time函数设置,第4个参数是从原来的占空比到达指定占空比时,所需花费的时间;
//LED渐变到100%,需要花费1000ms
ledc_set_fade_with_time(ledc_channel.speed_mode, ledc_channel.channel, 8191, 1000);
b、将LED PWM占空比调到0%也是一样的原理;
//LED渐变到0%,需要花费1000ms
ledc_set_fade_with_time(ledc_channel.speed_mode, ledc_channel.channel, 0, 1000);
c、设置好占空比之后,需要让LED PWM运行起来,就需要用到ledc_fade_start函数;
ledc_fade_start(ledc_channel.speed_mode,ledc_channel.channel, LEDC_FADE_NO_WAIT);
main.c程序
#include <stdio.h>
#include "driver/gpio.h" //GPIO固件库
#include "freertos/FreeRTOS.h" //FreeRTOS固件库
#include "freertos/task.h" //延时函数需要用到该头文件
#include "driver/ledc.h" //LED PWM固件库
#define blueLED GPIO_NUM_5 //定义蓝色LED引脚
ledc_channel_config_t ledc_channel; //定义LED PWM通道
void breathingLed_init(void); //配置LED PWM控制器
void app_main(void)
{
breathingLed_init();
while (true)
{
//LED渐变到100%,需要花费1000ms
ledc_set_fade_with_time(ledc_channel.speed_mode,
ledc_channel.channel,
8191,
1000);
ledc_fade_start(ledc_channel.speed_mode,ledc_channel.channel, LEDC_FADE_NO_WAIT);
vTaskDelay(1000 / portTICK_PERIOD_MS); //延时1000ms
//LED渐变到0%,需要花费1000ms
ledc_set_fade_with_time(ledc_channel.speed_mode,
ledc_channel.channel,
0,
1000);
ledc_fade_start(ledc_channel.speed_mode,ledc_channel.channel, LEDC_FADE_NO_WAIT);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void breathingLed_init(void)
{
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_13_BIT, //PWM分辨率
.freq_hz = 5000, //频率
.speed_mode = 0, //速度
.timer_num = LEDC_TIMER_0, //选择定时器
};
ledc_timer_config(&ledc_timer); //配置LED为定时器PWM模式
ledc_channel.channel = LEDC_CHANNEL_0; //LED PWM通道
ledc_channel.duty = 0; //占空比
ledc_channel.gpio_num = blueLED; //IO口映射
ledc_channel.speed_mode = 0; //速度
ledc_channel.timer_sel = LEDC_TIMER_0; //选择定时器
ledc_channel_config(&ledc_channel); //配置LED PWM通道
ledc_fade_func_install(0); //开启LEDC渐变功能,参数为是否允许中断
}
2、编译后烧录程序查看实验效果
思路:RGB灯从呼吸灯实验只用到了一种颜色,所以如果把RGB三种颜色都用上了,不就可以形成多种颜色组合,变成彩虹色了吗?就此展开本次实验。
1、一开始想着很简单,因为LED PWM控制器有4个定时,6个PWM通道,那么每个引脚用一个定时器一个PWM通道控制完成了
main.c代码如下:
#include <stdio.h>
#include "driver/gpio.h" //GPIO固件库
#include "freertos/FreeRTOS.h" //FreeRTOS固件库
#include "freertos/task.h" //延时函数需要用到该头文件
#include "driver/ledc.h" //LED PWM固件库
#define blueLED GPIO_NUM_5 //定义蓝色LED引脚
#define greenLED GPIO_NUM_4 //定义绿色LED引脚
#define redLED GPIO_NUM_3 //定义红色LED引脚
ledc_channel_config_t ledc_channel0; //定义LED PWM0通道
ledc_channel_config_t ledc_channel1; //定义LED PWM1通道
ledc_channel_config_t ledc_channel2; //定义LED PWM2通道
//配置LEDC PWM控制器
void breathingLed_init(ledc_timer_t timer, //定时器
ledc_channel_config_t channel_config, //LED PWM控制配置器
ledc_channel_t channel, //PWM通道
gpio_num_t gpio_num); //IO映射
void ledc_pwmDir(ledc_channel_config_t channel, bool flag); //LED PWM占空比调节
void app_main(void)
{
breathingLed_init(LEDC_TIMER_0, ledc_channel0, LEDC_CHANNEL_0, blueLED);//配置蓝灯
breathingLed_init(LEDC_TIMER_1, ledc_channel1, LEDC_CHANNEL_1, greenLED);//配置绿灯
breathingLed_init(LEDC_TIMER_2, ledc_channel2, LEDC_CHANNEL_2, redLED);//配置红灯
while (true)
{
ledc_pwmDir(ledc_channel0, false);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ledc_pwmDir(ledc_channel0, true);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ledc_pwmDir(ledc_channel1, false);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ledc_pwmDir(ledc_channel1, true);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ledc_pwmDir(ledc_channel2, false);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ledc_pwmDir(ledc_channel2, true);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void breathingLed_init(ledc_timer_t timer, ledc_channel_config_t channel_config, ledc_channel_t channel, gpio_num_t gpio_num)
{
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_13_BIT, //PWM分辨率
.freq_hz = 5000, //频率
.speed_mode = 0, //速度
.timer_num = timer, //选择定时器
};
ledc_timer_config(&ledc_timer); //配置LED为定时器PWM模式
channel_config.channel = channel; //LED PWM通道
channel_config.duty = 8191; //占空比
channel_config.gpio_num = gpio_num; //IO口映射
channel_config.speed_mode = 0; //速度
channel_config.timer_sel = timer; //选择定时器
ledc_channel_config(&channel_config); //配置LED PWM通道
ledc_fade_func_install(0); //开启LEDC渐变功能,参数为是否允许中断
}
void ledc_pwmDir(ledc_channel_config_t channel, bool flag)
{
ledc_set_fade_with_time(channel.speed_mode,channel.channel,flag ? 8191 : 0, 1000);
ledc_fade_start(channel.speed_mode,channel.channel, LEDC_FADE_NO_WAIT);
}
实验效果:只有蓝色灯在渐变
2、经过此次实验,又查到ESP32-C3技术参考手册,修改了几次代码,最后查到了第十章 ESP32开发指南---PWM全彩LED灯显示这篇内容,得知:LED PWM控制只能通过一个定时器控制,不同通道来控制不同的IO输出,但需要注意的事:
a、配置LED PWM控制器智能配置一次,否则会有问题,如下代码不能重复。
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_13_BIT, //PWM分辨率
.freq_hz = 5000, //频率
.speed_mode = 0, //速度
.timer_num = timer, //选择定时器
};
ledc_timer_config(&ledc_timer); //配置LED为定时器PWM模式
b、如下函数是对LED PWM控制器进行启动的,所以也只需在配置完LED PWM控制器后执行一次就行。
ledc_fade_func_install(0); //开启LEDC渐变功能,参数为是否允许中断
main.c代码如下:
#include <stdio.h>
#include "driver/gpio.h" //GPIO固件库
#include "freertos/FreeRTOS.h" //FreeRTOS固件库
#include "freertos/task.h" //延时函数需要用到该头文件
#include "driver/ledc.h" //LED PWM固件库
#define blueLED GPIO_NUM_5 //定义蓝色LED引脚
#define greenLED GPIO_NUM_4 //定义绿色LED引脚
#define redLED GPIO_NUM_3 //定义红色LED引脚
ledc_channel_config_t ledc_channel0; //定义LED PWM0通道
ledc_channel_config_t ledc_channel1; //定义LED PWM1通道
ledc_channel_config_t ledc_channel2; //定义LED PWM2通道
void breathingLed_init(void); //配置LED PWM控制器
void ledc_pwmDir(ledc_channel_config_t channel, bool flag); //LED PWM占空比调节
void app_main(void)
{
breathingLed_init();//配置LED PWM控制器
while (true)
{
ledc_pwmDir(ledc_channel0, false);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ledc_pwmDir(ledc_channel0, true);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ledc_pwmDir(ledc_channel1, false);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ledc_pwmDir(ledc_channel1, true);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ledc_pwmDir(ledc_channel2, false);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ledc_pwmDir(ledc_channel2, true);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void breathingLed_init(void)
{
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_13_BIT, //PWM分辨率
.freq_hz = 5000, //频率
.speed_mode = 0, //速度
.timer_num = LEDC_TIMER_0, //选择定时器
};
ledc_timer_config(&ledc_timer); //配置LED为定时器PWM模式
ledc_channel0.channel = LEDC_CHANNEL_0; //LED PWM通道
ledc_channel0.duty = 8191; //占空比
ledc_channel0.gpio_num = blueLED; //IO口映射
ledc_channel0.speed_mode = 0; //速度
ledc_channel0.timer_sel = LEDC_TIMER_0; //选择定时器
ledc_channel_config(&ledc_channel0); //配置LED PWM通道
ledc_channel1.channel = LEDC_CHANNEL_1; //LED PWM通道
ledc_channel1.duty = 8191; //占空比
ledc_channel1.gpio_num = greenLED; //IO口映射
ledc_channel1.speed_mode = 0; //速度
ledc_channel1.timer_sel = LEDC_TIMER_0; //选择定时器
ledc_channel_config(&ledc_channel1); //配置LED PWM通道
ledc_channel2.channel = LEDC_CHANNEL_2; //LED PWM通道
ledc_channel2.duty = 8191; //占空比
ledc_channel2.gpio_num = redLED; //IO口映射
ledc_channel2.speed_mode = 0; //速度
ledc_channel2.timer_sel = LEDC_TIMER_0; //选择定时器
ledc_channel_config(&ledc_channel2); //配置LED PWM通道
ledc_fade_func_install(0); //开启LEDC渐变功能,参数为是否允许中断
}
void ledc_pwmDir(ledc_channel_config_t channel, bool flag)
{
ledc_set_fade_with_time(channel.speed_mode,channel.channel,flag ? 8191 : 0, 1000);
ledc_fade_start(channel.speed_mode,channel.channel, LEDC_FADE_NO_WAIT);
}
实验效果:三种颜色渐变,在切换颜色的短暂时间会有颜色融合的效果,形成其他颜色,可以修改while(true)函数里面内容进行自由搭配
改进一下main.c代码:彩虹灯效果更好看
#include <stdio.h>
#include "driver/gpio.h" //GPIO固件库
#include "freertos/FreeRTOS.h" //FreeRTOS固件库
#include "freertos/task.h" //延时函数需要用到该头文件
#include "driver/ledc.h" //LED PWM固件库
#define blueLED GPIO_NUM_5 //定义蓝色LED引脚
#define greenLED GPIO_NUM_4 //定义绿色LED引脚
#define redLED GPIO_NUM_3 //定义红色LED引脚
ledc_channel_config_t ledc_channel0; //定义LED PWM0通道
ledc_channel_config_t ledc_channel1; //定义LED PWM1通道
ledc_channel_config_t ledc_channel2; //定义LED PWM2通道
void breathingLed_init(void); //配置LED PWM控制器
void app_main(void)
{
breathingLed_init();//配置LED PWM控制器
while (true)
{
ledc_set_fade_with_time(ledc_channel0.speed_mode, ledc_channel0.channel, 8191, 1000); //蓝色渐变灭
ledc_set_fade_with_time(ledc_channel1.speed_mode, ledc_channel1.channel, 0, 1000); //绿灯渐变亮
ledc_fade_start(ledc_channel0.speed_mode, ledc_channel0.channel, LEDC_FADE_NO_WAIT); //开始渐变
ledc_fade_start(ledc_channel1.speed_mode, ledc_channel1.channel, LEDC_FADE_NO_WAIT);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ledc_set_fade_with_time(ledc_channel1.speed_mode, ledc_channel1.channel, 8191, 1000);
ledc_set_fade_with_time(ledc_channel2.speed_mode, ledc_channel2.channel, 0, 1000);
ledc_fade_start(ledc_channel1.speed_mode, ledc_channel1.channel, LEDC_FADE_NO_WAIT);
ledc_fade_start(ledc_channel2.speed_mode, ledc_channel2.channel, LEDC_FADE_NO_WAIT);
vTaskDelay(1000 / portTICK_PERIOD_MS);
ledc_set_fade_with_time(ledc_channel2.speed_mode, ledc_channel2.channel, 8191, 1000);
ledc_set_fade_with_time(ledc_channel0.speed_mode, ledc_channel0.channel, 0, 1000);
ledc_fade_start(ledc_channel2.speed_mode,ledc_channel2.channel, LEDC_FADE_NO_WAIT);
ledc_fade_start(ledc_channel0.speed_mode, ledc_channel0.channel, LEDC_FADE_NO_WAIT);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void breathingLed_init(void)
{
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_13_BIT, //PWM分辨率
.freq_hz = 5000, //频率
.speed_mode = 0, //速度
.timer_num = LEDC_TIMER_0, //选择定时器
};
ledc_timer_config(&ledc_timer); //配置LED为定时器PWM模式
ledc_channel0.channel = LEDC_CHANNEL_0; //LED PWM通道
ledc_channel0.duty = 0; //占空比
ledc_channel0.gpio_num = blueLED; //IO口映射
ledc_channel0.speed_mode = 0; //速度
ledc_channel0.timer_sel = LEDC_TIMER_0; //选择定时器
ledc_channel_config(&ledc_channel0); //配置LED PWM通道
ledc_channel1.channel = LEDC_CHANNEL_1; //LED PWM通道
ledc_channel1.duty = 8191; //占空比
ledc_channel1.gpio_num = greenLED; //IO口映射
ledc_channel1.speed_mode = 0; //速度
ledc_channel1.timer_sel = LEDC_TIMER_0; //选择定时器
ledc_channel_config(&ledc_channel1); //配置LED PWM通道
ledc_channel2.channel = LEDC_CHANNEL_2; //LED PWM通道
ledc_channel2.duty = 8191; //占空比
ledc_channel2.gpio_num = redLED; //IO口映射
ledc_channel2.speed_mode = 0; //速度
ledc_channel2.timer_sel = LEDC_TIMER_0; //选择定时器
ledc_channel_config(&ledc_channel2); //配置LED PWM通道
ledc_fade_func_install(0); //开启LEDC渐变功能,参数为是否允许中断
}
注意:
1、Micro-USB是数据线,不是电源线,数据线能用作下载线,但电源线仅供电;
2、再次提示项目路径不能存在中文或者空格,否则会报错,编译不成功;
3、编译成功会在终端显示内存大小,
4、编译成功后依然提示有问题,忽略就可以。
5、因为GOOUUU-ESP32-C3开发板有自动下载电路,所以可以直接接USB烧录程序,不用改变启动管脚,如果没有自动下载电路,需要手动设置启动管脚。
6、开发板中的RGB灯是由3个引脚控制的,相当于三个不同颜色的LED灯而已,而WS2812 RGB灯是由1个引脚控制,两者控制方式不同。