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

艹,终于在8226上把灯点亮了

接上次点文章

ESP8266还可以这样玩

这次,我终于学会了在ESP8266上面点亮LED灯了

现在一个单片机的价格是几块,加上一个晶振,再来一个快递费,十几块钱还是需要的。

所以能用这个ESP8266来当单片机玩,还是比较不错的

可以在ubuntu、windows、Macos上开发

来了,先点亮一个LED灯

LED灯的GPIO口是 16

直接看代码,我们现在看到的代码实际上已经是跑了freertos的,这也是我为什么不用ardino玩,脱离了C语言就好像已经不是在做嵌入式了,要想了解底层还是用C语言比较有亲切感。

看代码

/* Hello World Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "driver/gpio.h"
#define GPIO_LED_NUM 16

void app_main()
{
    printf("Hello world!\n");

    /* 1.定义一个gpio配置结构体 */
    gpio_config_t gpio_config_structure;

    /* 2.初始化gpio配置结构体*/
    gpio_config_structure.pin_bit_mask = (1ULL << GPIO_LED_NUM);/* 选择gpio2 */
    gpio_config_structure.mode = GPIO_MODE_OUTPUT; /* 输出模式 */
    gpio_config_structure.pull_up_en = 0; /* 不上拉 */
    gpio_config_structure.pull_down_en = 0; /* 不下拉 */
    gpio_config_structure.intr_type = GPIO_INTR_DISABLE; /* 禁止中断 */

    /* 3.根据设定参数初始化并使能 */
    gpio_config(&gpio_config_structure);

    /* 4.输出低电平,点亮LED*/
    gpio_set_level(GPIO_LED_NUM, 0);

    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    printf("This is ESP8266 chip with %d CPU cores, WiFi, ",
            chip_info.cores);

    printf("silicon revision %d, ", chip_info.revision);

    printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
            (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

    for (int i = 100000; i >= 0; i--) {
        printf("Restarting in %d seconds...\n", i);
        gpio_set_level(GPIO_LED_NUM, 0);
        vTaskDelay(500 / portTICK_PERIOD_MS);
        gpio_set_level(GPIO_LED_NUM, 1);
        vTaskDelay(500 / portTICK_PERIOD_MS);
    }
    printf("Restarting now.\n");
    fflush(stdout);
    esp_restart();
}

70858ba5c8a4e82b124930b5c6fd6940.gif

LED是一个很入门的东西,但是LED也是一个很有意思的东西,如果玩得好可以变得很有趣。

本来想用这个GPIO口来做一个PWM控制的呼吸灯功能的,可惜查看了下手册,发现这个GPIO16口没有PWM功能。

86a0df1a1a1b0252784d71a1ad515cfc.png

再来搞一个程序

扫描附近的wifi,如果搞好了继续往深的玩,可以做一个这样的设备,专门用来扫描附近的热点,然后用随机密码连接,连接上了打印密码,是不是也很酷。

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"

static EventGroupHandle_t wifi_event_group;//定义一个事件的句柄
const int SCAN_DONE_BIT = BIT0;//定义事件,占用事件变量的第0位,最多可以定义32个事件。
static wifi_scan_config_t scanConf = { //定义scanConf结构体,供函数esp_wifi_scan_start调用
    .ssid = NULL,
    .bssid = NULL,
    .channel = 0,
    .show_hidden = 1
};

static const char *TAG = "example";

esp_err_t event_handler(void *ctx, system_event_t *event)
{
    if (event->event_id == SYSTEM_EVENT_SCAN_DONE) {
        xEventGroupSetBits(wifi_event_group, SCAN_DONE_BIT); //设置事件位
    }
    return ESP_OK;
}

static void initialise_wifi(void)        //define a static function ,it's scope is this file
{
    wifi_event_group = xEventGroupCreate(); //创建一个事件标志组
    ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));//创建事件的任务
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();//设置默认的wifi栈参数
    ESP_ERROR_CHECK(esp_wifi_init(&cfg)); //初始化WiFi Alloc资源为WiFi驱动,如WiFi控制结构,RX / TX缓冲区,WiFi NVS结构等,此WiFi也启动WiFi任务。
    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));// Set the WiFi API configuration storage type
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));//Set the WiFi operating mode
    ESP_ERROR_CHECK(esp_wifi_start());
}

static void scan_task(void *pvParameters)
{
    while(1) {
        xEventGroupWaitBits(wifi_event_group, SCAN_DONE_BIT, 0, 1, portMAX_DELAY); //等待事件被置位,即等待扫描完成
        ESP_LOGI(TAG, "WIFI scan doen");
        xEventGroupClearBits(wifi_event_group, SCAN_DONE_BIT);//清除事件标志位

        uint16_t apCount = 0;
        esp_wifi_scan_get_ap_num(&apCount);//Get number of APs found in last scan
        printf("Number of access points found: %d\n", apCount);
        if (apCount == 0) {
            ESP_LOGI(TAG, "Nothing AP found");
            return;
        }//如果apCount没有受到数据,则说明没有路由器
        wifi_ap_record_t *list = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * apCount);//定义一个wifi_ap_record_t的结构体的链表空间
        ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&apCount, list));//获取上次扫描中找到的AP列表。
        int i;
        printf("======================================================================\n");
        printf(" SSID | RSSI | AUTH \n");
        printf("======================================================================\n");
        for (i=0; i<apCount; i++) {
            char *authmode;
            switch(list[i].authmode) {
            case WIFI_AUTH_OPEN: authmode = "WIFI_AUTH_OPEN";
               break;
            case WIFI_AUTH_WEP: authmode = "WIFI_AUTH_WEP";
               break;
            case WIFI_AUTH_WPA_PSK: authmode = "WIFI_AUTH_WPA_PSK";
               break;
            case WIFI_AUTH_WPA2_PSK: authmode = "WIFI_AUTH_WPA2_PSK";
               break;
            case WIFI_AUTH_WPA_WPA2_PSK: authmode = "WIFI_AUTH_WPA_WPA2_PSK";
               break;
            default: authmode = "Unknown";
               break;
            }
            printf("%26.26s | % 4d | %22.22s\n",list[i].ssid, list[i].rssi, authmode);
        }//将链表的数据信息打印出来
        free(list);//释放链表
        printf("\n\n");//换行

        // scan again
        vTaskDelay(2000 / portTICK_PERIOD_MS);//调用延时函数,再次扫描
        //The true parameter cause the function to block until the scan is done.
        ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, 1));//扫描所有可用的AP。
    }


}

int app_main(void)
{
    nvs_flash_init();//初始化NVS flash storage
    tcpip_adapter_init();//初始化i本机TCP/IP协议
    initialise_wifi();//初始化wifi

    xTaskCreate(&scan_task, "scan_task", 2048, NULL, 15, NULL);//创建扫描任务

    ESP_ERROR_CHECK(esp_wifi_scan_start(&scanConf, 1)); //The true parameter cause the function to block until
                                                              //the scan is done.
    return 0;
}

运行的情况是

c8496ba90c09731bdc2cb24811963d08.png

8226可以玩的东西还有很多,比如内存、Flash、I2C、SPI

因为我对LED灯还是不死心,就买了一些LED灯回来,等到货了继续给大家看看呼吸灯。

好了,我的商店也上了20个这样的ESP8266,喜欢的可以去看看吧。

现在只有20个的ESP8266

e2c794cf571622e2a56817e3f6250427.jpeg

11e64e9437f1cc20d34cb41a49703673.jpeg

da1bb589da8e6b5e467a0d936a36f3e8.png

相关文章:

  • Linux上用Samba建立共享文件夹并通过Linux测试
  • shell简单使用介绍
  • 关于中级开发工程师常问的面试题
  • 蓝桥杯刷题第二十天
  • 二叉树(数据结构系列9)
  • mybatis-plus的批量新增insertBatchSomeColumn
  • Linux内核IO基础知识与概念
  • Java - 配置中心初体验
  • 面试--每日一经
  • 算法训练营第五十九天|LeetCode647、516
  • 音视频开发—MediaCodec 解码H264/H265码流视频
  • 【python进阶】序列切片还能这么用?切片的强大比你了解的多太多
  • 内网升级“高效安全”利器!统信软件发布私有化更新管理平台
  • 什么是Vue
  • [图像识别]关于cv2库无法安装的故障问题解决,全网最全解决方案!本人亲身测试,参考了stackoverflow、51CTO等博客文章总结而成
  • 【个人向】《HTTP图解》阅后小结
  • Babel配置的不完全指南
  • JavaScript HTML DOM
  • PHP 7 修改了什么呢 -- 2
  • React Transition Group -- Transition 组件
  • React的组件模式
  • Terraform入门 - 1. 安装Terraform
  • TypeScript迭代器
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 回顾2016
  • 排序算法学习笔记
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 在Unity中实现一个简单的消息管理器
  • hi-nginx-1.3.4编译安装
  • ​TypeScript都不会用,也敢说会前端?
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • $GOPATH/go.mod exists but should not goland
  • (C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (ZT)北大教授朱青生给学生的一封信:大学,更是一个科学的保证
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (四)linux文件内容查看
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)视频码率,帧率和分辨率的联系与区别
  • (转)四层和七层负载均衡的区别
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .NET Framework与.NET Framework SDK有什么不同?
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .NET/C# 获取一个正在运行的进程的命令行参数
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .NET/C# 中设置当发生某个特定异常时进入断点(不借助 Visual Studio 的纯代码实现)
  • .NET中使用Protobuffer 实现序列化和反序列化
  • @EventListener注解使用说明
  • @serverendpoint注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • [C#] 我的log4net使用手册