代码正文
我将注释给修改了下,方便理解
/* Blink Example*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "led_strip.h"
#include "sdkconfig.h"
static const char *TAG = "example";
/*
使用项目配置面板(idf.py menuconfig)来设置GPIO使led闪烁
或者编辑下行代码来设置GPIO号
*/
#define BLINK_GPIO CONFIG_BLINK_GPIO
static uint8_t s_led_state = 0;
/*
#ifdef CONFIG_BLINK_LED_RMT
static led_strip_t *pStrip_a;
static void blink_led(void)
{
/* If the addressable LED is enabled */
if (s_led_state) {
/* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */
pStrip_a->set_pixel(pStrip_a, 0, 16, 16, 16);
/* Refresh the strip to send data */
pStrip_a->refresh(pStrip_a, 100);
} else {
/* Set all LED off to clear all pixels */
pStrip_a->clear(pStrip_a, 50);
}
}
static void configure_led(void)
{
ESP_LOGI(TAG, "Example configured to blink addressable LED!");
/* LED strip initialization with the GPIO and pixels number*/
pStrip_a = led_strip_init(CONFIG_BLINK_LED_RMT_CHANNEL, BLINK_GPIO, 1);
/* Set all LED off to clear all pixels */
pStrip_a->clear(pStrip_a, 50);
}
*/
#ifdef CONFIG_BLINK_LED_GPIO
static void blink_led(void)
{
/*设置引脚电平,来控制亮灭*/
gpio_set_level(BLINK_GPIO, s_led_state);
}
static void configure_led(void)
{
ESP_LOGI(TAG, "Example configured to blink GPIO LED!");
gpio_reset_pin(BLINK_GPIO); //设置为推挽输出模式
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); //设置引脚方向:输出
}
#endif
void app_main(void)
{
configure_led(); //根据led具体型号进行配置
while (1) {
ESP_LOGI(TAG, "Turning the LED %s!", s_led_state == true ? "ON" : "OFF");
blink_led();
s_led_state = !s_led_state; //改变状态
vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS); //延时1s
}
}
运行效果
剖析
整个代码实现的功能很简单,配置led所在GPIO,循环控制引脚输出高低电平以控制led亮灭,同时串口输出信息。
1.定义led所在GPIO
#define BLINK_GPIO CONFIG_BLINK_GPIO
不得不说vscode确实方便,可以很快捷的跳转到定义上
这里跳转找到CONFIG_BLINK_GPIO定义语句
可以看到,GPIO2是led所在引脚,值得一提的是我是用的优信电子家的esp32开发板,管脚布局和乐鑫esp32还是有些许出入的,我从优信家要来相关开发板数据手册和与原理图
原文是CONFIG_BLINK_GPIO 5
我修改为CONFIG_BLINK_GPIO 2
这算是最简单的移植吧
2.定义led状态变量
static uint8_t s_led_state = 0;
3.条件编译
接下来可以看到代码里的
#ifdef
代码段
#elif
代码段
#endif
条件编译的具体作用,请自行百度学习,总之是开发项目中方便调试的必备用法
/*
#ifdef CONFIG_BLINK_LED_RMT
static led_strip_t *pStrip_a;
static void blink_led(void)
{
/* If the addressable LED is enabled */
if (s_led_state) {
/* Set the LED pixel using RGB from 0 (0%) to 255 (100%) for each color */
pStrip_a->set_pixel(pStrip_a, 0, 16, 16, 16);
/* Refresh the strip to send data */
pStrip_a->refresh(pStrip_a, 100);
} else {
/* Set all LED off to clear all pixels */
pStrip_a->clear(pStrip_a, 50);
}
}
static void configure_led(void)
{
ESP_LOGI(TAG, "Example configured to blink addressable LED!");
/* LED strip initialization with the GPIO and pixels number*/
pStrip_a = led_strip_init(CONFIG_BLINK_LED_RMT_CHANNEL, BLINK_GPIO, 1);
/* Set all LED off to clear all pixels */
pStrip_a->clear(pStrip_a, 50);
}
*/
这里我们跳转看看定义,发现没有定义,也就是说该例程里它注定不会生效
从字面意思来说,CONFIG_BLINK_LED_RMT
远程配置led闪烁?
实际上从下面代码的注释不难看出
如果条件编译通过,我们可以配置led的RGB比例,来发出不同颜色的光。
那么这段注定不会生效的代码的作用也很明了了:
如果外设led用的是支持RGB的led,我们可以用该预编译里的功能,但实际上开发板上配置的蓝光led并不支持RGB功能,所以CONFIG_BLINK_LED_RMT没有被定义,此段预编译不会生效,为了方便理解,代码也就被我注释掉了。
继续看下一段代码
#ifdef CONFIG_BLINK_LED_GPIO
static void blink_led(void)
{
/*设置引脚电平,来控制亮灭*/
gpio_set_level(BLINK_GPIO, s_led_state);
}
static void configure_led(void)
{
ESP_LOGI(TAG, "Example configured to blink GPIO LED!");
gpio_reset_pin(BLINK_GPIO); //设置为推挽输出模式
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); //设置引脚方向:输出
}
#endif
跳转定义,我们看到CONFIG_BLINK_LED_GPIO是被定义为1的
所以这段预编译代码会生效
里面函数的功能,我已经注释了,很容易理解
就是用来配置led所在引脚的
至于推挽输出模式
参考:开漏输出(open drain)与推挽输出(push pull)学习详解及某个踩到的坑分享
4.主函数
void app_main(void)
{
configure_led(); //根据led具体型号进行配置
while (1) {
ESP_LOGI(TAG, "Turning the LED %s!", s_led_state == true ? "ON" : "OFF");
blink_led();
s_led_state = !s_led_state; //改变状态
vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS); //延时1s
}
}
相关功能我也有注释
里面有几句代码写法值得学习
这句里的条件运算符就用的很好
ESP_LOGI(TAG, "Turning the LED %s!", s_led_state == true ? "ON" : "OFF");
这里的延时函数也很巧妙
vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS); //延时1s
我们跳转CONFIG_BLINK_PERIOD的定义,可以看到设为1000
再看portTICK_PERIOD_MS
这个TickType_t是int(根据OS字长决定是32位还是16位)的别名,嵌入式开发常识了,不过我还是提一句
那么这个1000/configTICK_RATE_HZ
configTICK_RATE_HZ又是什么呢?
继续跳转
原来是时钟速率设为1000hz
及portTICK_PERIOD_MS=1000/configTICK_RATE_HZ=1ms
所以vTaskDelay(CONFIG_BLINK_PERIOD / portTICK_PERIOD_MS);
等价于vTaskDelay(1000/1000)=vTaskDelay(1)=1s
结束,该例程剖析完毕
后言
记录这篇博客的时候,感觉自己写的太细了,像在灌水,不过回想起自己刚入门嵌入式时的各种困惑,还是决定偏新手向一点,也算回顾知识点了。
修改GPIO引脚定义在头文件里改不行,会被配置文件重置
需要修改配置文件里的定义