接上次点文章
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();
}
LED是一个很入门的东西,但是LED也是一个很有意思的东西,如果玩得好可以变得很有趣。
本来想用这个GPIO口来做一个PWM控制的呼吸灯功能的,可惜查看了下手册,发现这个GPIO16口没有PWM功能。
再来搞一个程序
扫描附近的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;
}
运行的情况是
8226可以玩的东西还有很多,比如内存、Flash、I2C、SPI
因为我对LED灯还是不死心,就买了一些LED灯回来,等到货了继续给大家看看呼吸灯。
好了,我的商店也上了20个这样的ESP8266,喜欢的可以去看看吧。
现在只有20个的ESP8266